From 3899e0b308d51019ff33e24bd36938091cef444f Mon Sep 17 00:00:00 2001 From: Wikijito7 Date: Sun, 18 Dec 2022 20:37:29 +0100 Subject: [PATCH] Revert "Google auth (#4)" This reverts commit b6710b89d94186e2968aa105c20e0cdda9e2b9a7. --- .gitignore | 3 +- build.gradle.kts | 14 -- gradle.properties | 3 +- src/main/kotlin/es/wokis/Application.kt | 16 +-- .../es/wokis/data/bo/invoice/InvoiceBO.kt | 37 ----- .../kotlin/es/wokis/data/bo/user/UserBO.kt | 15 -- .../data/bo/verification/VerificationBO.kt | 10 -- .../wokis/data/constants/ServerConstants.kt | 6 - .../es/wokis/data/database/AppDataBase.kt | 30 ---- .../data/datasource/UserLocalDataSource.kt | 69 ---------- .../es/wokis/data/dbo/invoice/InvoiceDBO.kt | 28 ---- .../kotlin/es/wokis/data/dbo/user/UserDBO.kt | 16 --- .../es/wokis/data/dto/invoice/InvoiceDTO.kt | 43 ------ .../kotlin/es/wokis/data/dto/user/UserDTO.kt | 12 -- .../es/wokis/data/dto/user/auth/Auth.kt | 17 --- .../data/mapper/invoice/InvoiceMapper.kt | 36 ----- .../es/wokis/data/mapper/user/UserMapper.kt | 64 --------- .../data/repository/user/UserRepository.kt | 129 ------------------ .../kotlin/es/wokis/di/DataSourceModule.kt | 21 --- .../kotlin/es/wokis/di/RepositoryModule.kt | 9 -- src/main/kotlin/es/wokis/plugins/Config.kt | 24 ---- src/main/kotlin/es/wokis/plugins/Firebase.kt | 21 --- src/main/kotlin/es/wokis/plugins/HTTP.kt | 19 +-- src/main/kotlin/es/wokis/plugins/Koin.kt | 14 +- src/main/kotlin/es/wokis/plugins/Routing.kt | 10 +- src/main/kotlin/es/wokis/plugins/Security.kt | 74 +++------- .../kotlin/es/wokis/routing/AuthRouting.kt | 46 ------- .../es/wokis/routing/InvoicesRouting.kt | 5 - .../kotlin/es/wokis/routing/UserRouting.kt | 19 --- .../kotlin/es/wokis/services/EmailService.kt | 61 --------- .../es/wokis/services/NotificationService.kt | 24 ---- .../kotlin/es/wokis/utils/BooleanUtils.kt | 5 - .../kotlin/es/wokis/utils/CredentialsUtils.kt | 12 -- src/main/kotlin/es/wokis/utils/DateUtils.kt | 15 -- .../kotlin/es/wokis/utils/HashGenerator.kt | 23 ---- src/main/resources/app.conf | 29 ---- src/main/resources/application.conf | 24 ---- 37 files changed, 37 insertions(+), 966 deletions(-) delete mode 100644 src/main/kotlin/es/wokis/data/bo/invoice/InvoiceBO.kt delete mode 100644 src/main/kotlin/es/wokis/data/bo/user/UserBO.kt delete mode 100644 src/main/kotlin/es/wokis/data/bo/verification/VerificationBO.kt delete mode 100644 src/main/kotlin/es/wokis/data/constants/ServerConstants.kt delete mode 100644 src/main/kotlin/es/wokis/data/database/AppDataBase.kt delete mode 100644 src/main/kotlin/es/wokis/data/datasource/UserLocalDataSource.kt delete mode 100644 src/main/kotlin/es/wokis/data/dbo/invoice/InvoiceDBO.kt delete mode 100644 src/main/kotlin/es/wokis/data/dbo/user/UserDBO.kt delete mode 100644 src/main/kotlin/es/wokis/data/dto/invoice/InvoiceDTO.kt delete mode 100644 src/main/kotlin/es/wokis/data/dto/user/UserDTO.kt delete mode 100644 src/main/kotlin/es/wokis/data/dto/user/auth/Auth.kt delete mode 100644 src/main/kotlin/es/wokis/data/mapper/invoice/InvoiceMapper.kt delete mode 100644 src/main/kotlin/es/wokis/data/mapper/user/UserMapper.kt delete mode 100644 src/main/kotlin/es/wokis/data/repository/user/UserRepository.kt delete mode 100644 src/main/kotlin/es/wokis/di/DataSourceModule.kt delete mode 100644 src/main/kotlin/es/wokis/di/RepositoryModule.kt delete mode 100644 src/main/kotlin/es/wokis/plugins/Config.kt delete mode 100644 src/main/kotlin/es/wokis/plugins/Firebase.kt delete mode 100644 src/main/kotlin/es/wokis/routing/AuthRouting.kt delete mode 100644 src/main/kotlin/es/wokis/routing/UserRouting.kt delete mode 100644 src/main/kotlin/es/wokis/services/EmailService.kt delete mode 100644 src/main/kotlin/es/wokis/services/NotificationService.kt delete mode 100644 src/main/kotlin/es/wokis/utils/BooleanUtils.kt delete mode 100644 src/main/kotlin/es/wokis/utils/CredentialsUtils.kt delete mode 100644 src/main/kotlin/es/wokis/utils/DateUtils.kt delete mode 100644 src/main/kotlin/es/wokis/utils/HashGenerator.kt delete mode 100644 src/main/resources/app.conf delete mode 100644 src/main/resources/application.conf diff --git a/.gitignore b/.gitignore index 2c55ad9..c426c32 100644 --- a/.gitignore +++ b/.gitignore @@ -33,5 +33,4 @@ out/ /.nb-gradle/ ### VS Code ### -.vscode/ -/config/ +.vscode/ \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts index 674d0a0..bcb20c3 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -3,7 +3,6 @@ val kotlin_version: String by project val logback_version: String by project val kmongo_version: String by project val koin_version: String by project -val firebase_version: String by project plugins { application @@ -48,19 +47,6 @@ dependencies { // Koin implementation("io.insert-koin:koin-ktor:$koin_version") implementation("io.insert-koin:koin-logger-slf4j:$koin_version") - - // Firebase - implementation("com.google.firebase:firebase-admin:$firebase_version") - - // BCrypt - implementation("org.mindrot:jbcrypt:0.4") - - // Google auth - implementation("com.google.api-client:google-api-client:2.1.1") - - // JavaMail - implementation("javax.mail:javax.mail-api:1.6.2") - implementation("com.sun.mail:javax.mail:1.6.2") } ktor { diff --git a/gradle.properties b/gradle.properties index 4b31c03..0c9830e 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,7 +1,6 @@ -ktor_version=2.2.1 +ktor_version=2.1.3 kotlin_version=1.7.21 logback_version=1.4.4 kmongo_version=4.7.2 koin_version=3.2.2 -firebase_version=9.1.1 kotlin.code.style=official diff --git a/src/main/kotlin/es/wokis/Application.kt b/src/main/kotlin/es/wokis/Application.kt index aa9d056..a758f7f 100644 --- a/src/main/kotlin/es/wokis/Application.kt +++ b/src/main/kotlin/es/wokis/Application.kt @@ -1,26 +1,16 @@ package es.wokis -import com.typesafe.config.ConfigFactory -import es.wokis.plugins.* import io.ktor.server.application.* -import io.ktor.server.config.* import io.ktor.server.engine.* import io.ktor.server.netty.* +import es.wokis.plugins.* fun main() { - embeddedServer(Netty, environment = applicationEngineEnvironment { - config = HoconApplicationConfig(ConfigFactory.load("application.conf")) - - connector { - host = config.host - port = config.port - } - }).start(wait = true) + embeddedServer(Netty, port = 8080, host = "0.0.0.0", module = Application::module) + .start(wait = true) } fun Application.module() { - initConfig() - configureFirebase() configureKoin() configureSerialization() configureMonitoring() diff --git a/src/main/kotlin/es/wokis/data/bo/invoice/InvoiceBO.kt b/src/main/kotlin/es/wokis/data/bo/invoice/InvoiceBO.kt deleted file mode 100644 index 7417fee..0000000 --- a/src/main/kotlin/es/wokis/data/bo/invoice/InvoiceBO.kt +++ /dev/null @@ -1,37 +0,0 @@ -package es.wokis.data.bo.invoice - -import es.wokis.data.constants.ServerConstants.EMPTY_TEXT -import java.util.* - -data class InvoiceBO( - val id: String? = null, - val idApp: Long = 0L, - val title: String = EMPTY_TEXT, - val description: String = EMPTY_TEXT, - val quantity: Int = 0, - val date: Date = Date(), - val type: InvoiceType, - val userId: String, - val category: CategoryBO? = null, - val reactions: List = emptyList() -) - -data class CategoryBO( - val id: Long, - val title: String, - val color: String, -) - -data class ReactionBO( - val id: Long, - val unicode: String -) - -enum class InvoiceType(val key: String) { - DEPOSIT("DEPOSIT"), - EXPENSE("EXPENSE"); - - companion object { - fun getFromKey(key: String) = values().find { it.key == key } ?: DEPOSIT - } -} diff --git a/src/main/kotlin/es/wokis/data/bo/user/UserBO.kt b/src/main/kotlin/es/wokis/data/bo/user/UserBO.kt deleted file mode 100644 index 67905f3..0000000 --- a/src/main/kotlin/es/wokis/data/bo/user/UserBO.kt +++ /dev/null @@ -1,15 +0,0 @@ -package es.wokis.data.bo.user - -import es.wokis.data.constants.ServerConstants.DEFAULT_LANG -import es.wokis.data.constants.ServerConstants.EMPTY_TEXT -import io.ktor.server.auth.* - -data class UserBO( - val id: String? = null, - val username: String, - val email: String, - val password: String, - val image: String = EMPTY_TEXT, - val lang: String = DEFAULT_LANG, - val devices: List = emptyList() -) : Principal \ No newline at end of file diff --git a/src/main/kotlin/es/wokis/data/bo/verification/VerificationBO.kt b/src/main/kotlin/es/wokis/data/bo/verification/VerificationBO.kt deleted file mode 100644 index a521127..0000000 --- a/src/main/kotlin/es/wokis/data/bo/verification/VerificationBO.kt +++ /dev/null @@ -1,10 +0,0 @@ -package es.wokis.data.bo.verification - -import java.util.* - -data class VerificationBO( - val id: Long? = null, - val email: String, - val verificationToken: String, - val timeStamp: Date = Date() -) \ No newline at end of file diff --git a/src/main/kotlin/es/wokis/data/constants/ServerConstants.kt b/src/main/kotlin/es/wokis/data/constants/ServerConstants.kt deleted file mode 100644 index 8dd4254..0000000 --- a/src/main/kotlin/es/wokis/data/constants/ServerConstants.kt +++ /dev/null @@ -1,6 +0,0 @@ -package es.wokis.data.constants - -object ServerConstants { - const val EMPTY_TEXT = "" - const val DEFAULT_LANG = "en" -} \ No newline at end of file diff --git a/src/main/kotlin/es/wokis/data/database/AppDataBase.kt b/src/main/kotlin/es/wokis/data/database/AppDataBase.kt deleted file mode 100644 index 371f3f3..0000000 --- a/src/main/kotlin/es/wokis/data/database/AppDataBase.kt +++ /dev/null @@ -1,30 +0,0 @@ -package es.wokis.data.database - -import com.mongodb.ConnectionString -import com.mongodb.MongoClientSettings -import com.mongodb.MongoCredential -import es.wokis.data.dbo.invoice.InvoiceDBO -import es.wokis.data.dbo.user.UserDBO -import es.wokis.plugins.config -import org.litote.kmongo.KMongo -import org.litote.kmongo.getCollection - -class AppDataBase { - private val username = config.getString("db.user") - private val password = config.getString("db.password") - private val dataBaseUrl = "$MONGODB_PREFIX$username:$password@${config.getString("db.ip")}:${config.getString("db.port")}" - private val databaseName = config.getString("db.databaseName") - private val client = KMongo.createClient( - MongoClientSettings.builder() - .credential(MongoCredential.createCredential(username, databaseName, password.toCharArray())) - .applyConnectionString(ConnectionString(dataBaseUrl)).build() - ) - - val database by lazy { client.getDatabase(databaseName) } - val usersCollection by lazy { database.getCollection("users") } - val invoicesCollection by lazy { database.getCollection("invoices") } - - companion object { - private const val MONGODB_PREFIX = "mongodb://" - } -} \ No newline at end of file diff --git a/src/main/kotlin/es/wokis/data/datasource/UserLocalDataSource.kt b/src/main/kotlin/es/wokis/data/datasource/UserLocalDataSource.kt deleted file mode 100644 index 6b44867..0000000 --- a/src/main/kotlin/es/wokis/data/datasource/UserLocalDataSource.kt +++ /dev/null @@ -1,69 +0,0 @@ -package es.wokis.data.datasource - -import com.mongodb.client.MongoCollection -import es.wokis.data.bo.user.UserBO -import es.wokis.data.constants.ServerConstants.EMPTY_TEXT -import es.wokis.data.dbo.user.UserDBO -import es.wokis.data.mapper.user.toBO -import es.wokis.data.mapper.user.toDBO -import org.bson.types.ObjectId -import org.litote.kmongo.* -import org.litote.kmongo.id.toId -import java.util.regex.Pattern - -interface UserLocalDataSource { - suspend fun getAllUsers(): List - suspend fun getUserById(id: String): UserBO? - suspend fun getUserByEmail(email: String): UserBO? - suspend fun getUserByUsername(username: String): UserBO? - - suspend fun getUserByUsernameOrEmail(username: String, email: String = EMPTY_TEXT): UserBO? - - suspend fun createUser(user: UserBO): Boolean - suspend fun updateUser(user: UserBO): Boolean -} - -class UserLocalDataSourceImpl(private val userCollection: MongoCollection) : UserLocalDataSource { - - private val getCaseInsensitive: (element: String) -> Pattern = { - Pattern.compile(it, Pattern.CASE_INSENSITIVE) - } - - override suspend fun getAllUsers(): List = userCollection.find().map { - it.toBO() - }.toList() - - override suspend fun getUserById(id: String): UserBO? { - val bsonId: Id = ObjectId(id).toId() - return userCollection.findOne(UserDBO::id eq bsonId)?.toBO() - } - - override suspend fun getUserByEmail(email: String): UserBO? = - userCollection.findOne(UserDBO::email.regex(getCaseInsensitive(email)))?.toBO() - - override suspend fun getUserByUsername(username: String): UserBO? = - userCollection.findOne(UserDBO::username.regex(getCaseInsensitive(username)))?.toBO() - - override suspend fun getUserByUsernameOrEmail(username: String, email: String): UserBO? = - userCollection.findOne( - or( - UserDBO::username.regex(getCaseInsensitive(username)), - UserDBO::email.regex(getCaseInsensitive(email.takeIf { it.isNotBlank() } ?: username)) - ) - )?.toBO() - - override suspend fun createUser(user: UserBO): Boolean { - return try { - userCollection.insertOne(user.toDBO()).wasAcknowledged() - - } catch (e: Throwable) { - println(e.stackTraceToString()) - false - } - } - - override suspend fun updateUser(user: UserBO): Boolean { - val bsonId: Id = ObjectId(user.id).toId() - return userCollection.updateOne(UserDBO::id eq bsonId, user.toDBO()).wasAcknowledged() - } -} \ No newline at end of file diff --git a/src/main/kotlin/es/wokis/data/dbo/invoice/InvoiceDBO.kt b/src/main/kotlin/es/wokis/data/dbo/invoice/InvoiceDBO.kt deleted file mode 100644 index 5366524..0000000 --- a/src/main/kotlin/es/wokis/data/dbo/invoice/InvoiceDBO.kt +++ /dev/null @@ -1,28 +0,0 @@ -package es.wokis.data.dbo.invoice - -import es.wokis.data.constants.ServerConstants -import org.litote.kmongo.Id - -data class InvoiceDBO( - val id: Id? = null, - val idApp: Long = 0L, - val title: String = ServerConstants.EMPTY_TEXT, - val description: String = ServerConstants.EMPTY_TEXT, - val quantity: Int = 0, - val date: Long = 0L, - val type: String? = null, - val userId: String? = null, - val category: CategoryDBO? = null, - val reactions: List = emptyList() -) - -data class CategoryDBO( - val id: Long, - val title: String, - val color: String, -) - -data class ReactionDBO( - val id: Long, - val unicode: String -) \ No newline at end of file diff --git a/src/main/kotlin/es/wokis/data/dbo/user/UserDBO.kt b/src/main/kotlin/es/wokis/data/dbo/user/UserDBO.kt deleted file mode 100644 index 59dabec..0000000 --- a/src/main/kotlin/es/wokis/data/dbo/user/UserDBO.kt +++ /dev/null @@ -1,16 +0,0 @@ -package es.wokis.data.dbo.user - -import es.wokis.data.constants.ServerConstants -import org.bson.codecs.pojo.annotations.BsonId -import org.litote.kmongo.Id - -data class UserDBO( - @BsonId - val id: Id? = null, - val username: String, - val email: String, - val password: String, - val lang: String, - val image: String = ServerConstants.EMPTY_TEXT, - val devices: List = emptyList() -) \ No newline at end of file diff --git a/src/main/kotlin/es/wokis/data/dto/invoice/InvoiceDTO.kt b/src/main/kotlin/es/wokis/data/dto/invoice/InvoiceDTO.kt deleted file mode 100644 index 33f1960..0000000 --- a/src/main/kotlin/es/wokis/data/dto/invoice/InvoiceDTO.kt +++ /dev/null @@ -1,43 +0,0 @@ -package es.wokis.data.dto.invoice - -import com.google.gson.annotations.SerializedName -import es.wokis.data.constants.ServerConstants.EMPTY_TEXT - -data class InvoiceDTO( - @SerializedName("server_id") - val id: String? = null, - @SerializedName("id") - val idApp: Long = 0L, - @SerializedName("title") - val title: String = EMPTY_TEXT, - @SerializedName("description") - val description: String = EMPTY_TEXT, - @SerializedName("quantity") - val quantity: Int = 0, - @SerializedName("date") - val date: Long = 0L, - @SerializedName("type") - val type: String? = null, - @SerializedName("userId") - val userId: String? = null, - @SerializedName("category") - val category: CategoryDTO? = null, - @SerializedName("reactions") - val reactions: List = emptyList() -) - -data class CategoryDTO( - @SerializedName("id") - val id: Long, - @SerializedName("title") - val title: String, - @SerializedName("color") - val color: String, -) - -data class ReactionDTO( - @SerializedName("id") - val id: Long, - @SerializedName("unicode") - val unicode: String -) \ No newline at end of file diff --git a/src/main/kotlin/es/wokis/data/dto/user/UserDTO.kt b/src/main/kotlin/es/wokis/data/dto/user/UserDTO.kt deleted file mode 100644 index 28bf509..0000000 --- a/src/main/kotlin/es/wokis/data/dto/user/UserDTO.kt +++ /dev/null @@ -1,12 +0,0 @@ -package es.wokis.data.dto.user - -import es.wokis.data.constants.ServerConstants - -data class UserDTO( - val id: String, - val username: String, - val email: String, - val image: String = ServerConstants.EMPTY_TEXT, - val lang: String, - val devices: List = emptyList() -) \ No newline at end of file diff --git a/src/main/kotlin/es/wokis/data/dto/user/auth/Auth.kt b/src/main/kotlin/es/wokis/data/dto/user/auth/Auth.kt deleted file mode 100644 index 45bb9ae..0000000 --- a/src/main/kotlin/es/wokis/data/dto/user/auth/Auth.kt +++ /dev/null @@ -1,17 +0,0 @@ -package es.wokis.data.dto.user.auth - -import es.wokis.data.constants.ServerConstants.DEFAULT_LANG - -data class LoginDTO( - val username: String, - val password: String, - val isGoogleAuth: Boolean = false -) - -data class RegisterDTO( - val username: String, - val email: String, - val password: String, - val lang: String = DEFAULT_LANG, - val isGoogleAuth: Boolean = false -) \ No newline at end of file diff --git a/src/main/kotlin/es/wokis/data/mapper/invoice/InvoiceMapper.kt b/src/main/kotlin/es/wokis/data/mapper/invoice/InvoiceMapper.kt deleted file mode 100644 index 82b5005..0000000 --- a/src/main/kotlin/es/wokis/data/mapper/invoice/InvoiceMapper.kt +++ /dev/null @@ -1,36 +0,0 @@ -package es.wokis.data.mapper.invoice - -import es.wokis.data.bo.invoice.CategoryBO -import es.wokis.data.bo.invoice.InvoiceBO -import es.wokis.data.bo.invoice.InvoiceType -import es.wokis.data.bo.invoice.ReactionBO -import es.wokis.data.dto.invoice.CategoryDTO -import es.wokis.data.dto.invoice.InvoiceDTO -import es.wokis.data.dto.invoice.ReactionDTO -import java.util.* - -fun InvoiceDTO.toBO() = InvoiceBO( - id = id, - idApp = idApp, - title = title, - description = description, - quantity = quantity, - date = Date(date), - type = InvoiceType.valueOf(type.orEmpty()), - userId = userId.orEmpty(), - category = category?.toBO(), - reactions = reactions.toBO() -) - -fun CategoryDTO.toBO() = CategoryBO( - id = id, - title = title, - color = color -) - -fun List?.toBO() = this?.map { it.toBO() }.orEmpty() - -fun ReactionDTO.toBO() = ReactionBO( - id = id, - unicode = unicode -) \ No newline at end of file diff --git a/src/main/kotlin/es/wokis/data/mapper/user/UserMapper.kt b/src/main/kotlin/es/wokis/data/mapper/user/UserMapper.kt deleted file mode 100644 index ff24351..0000000 --- a/src/main/kotlin/es/wokis/data/mapper/user/UserMapper.kt +++ /dev/null @@ -1,64 +0,0 @@ -package es.wokis.data.mapper.user - -import es.wokis.data.bo.user.UserBO -import es.wokis.data.constants.ServerConstants.EMPTY_TEXT -import es.wokis.data.dbo.user.UserDBO -import es.wokis.data.dto.user.UserDTO -import es.wokis.data.dto.user.auth.LoginDTO -import es.wokis.data.dto.user.auth.RegisterDTO -import org.bson.types.ObjectId -import org.litote.kmongo.id.toId -import org.mindrot.jbcrypt.BCrypt - -fun RegisterDTO.toBO() = UserBO( - username = username, - email = email, - lang = lang, - password = BCrypt.hashpw(password, BCrypt.gensalt()), -) - -fun RegisterDTO.toLoginDTO() = LoginDTO( - username = username, - password = password -) - -fun UserDTO.toBO() = UserBO( - id = id, - username = username, - email = email, - password = EMPTY_TEXT, - image = image, - lang = lang, - devices = devices -) - -fun UserBO.toDBO() = UserDBO( - id = id?.let { ObjectId(it).toId() }, - username = username, - email = email, - password = password, - lang = lang, - image = image, - devices = devices -) - -fun UserDBO.toBO() = UserBO( - id = id.toString(), - username = username, - email = email, - password = password, - image = image, - lang = lang, - devices = devices -) - -fun List?.toDTO() = this?.map { it.toDTO() }.orEmpty() - -fun UserBO.toDTO() = UserDTO( - id = id.orEmpty(), - username = username, - email = email, - image = image, - lang = lang, - devices = devices -) \ No newline at end of file diff --git a/src/main/kotlin/es/wokis/data/repository/user/UserRepository.kt b/src/main/kotlin/es/wokis/data/repository/user/UserRepository.kt deleted file mode 100644 index 26eb4b7..0000000 --- a/src/main/kotlin/es/wokis/data/repository/user/UserRepository.kt +++ /dev/null @@ -1,129 +0,0 @@ -package es.wokis.data.repository.user - -import com.google.api.client.googleapis.auth.oauth2.GoogleIdToken -import com.google.api.client.googleapis.auth.oauth2.GoogleIdTokenVerifier -import com.google.api.client.http.javanet.NetHttpTransport -import com.google.api.client.json.gson.GsonFactory -import es.wokis.data.bo.user.UserBO -import es.wokis.data.constants.ServerConstants.DEFAULT_LANG -import es.wokis.data.constants.ServerConstants.EMPTY_TEXT -import es.wokis.data.datasource.UserLocalDataSource -import es.wokis.data.dto.user.auth.LoginDTO -import es.wokis.data.dto.user.auth.RegisterDTO -import es.wokis.data.mapper.user.toBO -import es.wokis.plugins.config -import es.wokis.plugins.makeToken -import es.wokis.utils.HashGenerator -import es.wokis.utils.generatePassword -import org.mindrot.jbcrypt.BCrypt - -interface UserRepository { - suspend fun login(login: LoginDTO): String? - suspend fun loginWithGoogle(googleToken: String): String? - suspend fun register(register: RegisterDTO): String? - suspend fun getUsers(): List - suspend fun getUserById(id: String?): UserBO? - suspend fun getUserByUsername(name: String?): UserBO? - suspend fun getUserByEmail(email: String?): UserBO? - suspend fun updateUser(user: UserBO): Boolean -} - -class UserRepositoryImpl(private val userLocalDataSource: UserLocalDataSource) : UserRepository { - - override suspend fun login(login: LoginDTO): String? { - val user = userLocalDataSource.getUserByUsernameOrEmail(login.username) - return user?.let { - if (BCrypt.checkpw(login.password, it.password)) { - makeToken(it) - - } else { - null - } - } - } - - override suspend fun loginWithGoogle(googleToken: String): String? { - val verifier: GoogleIdTokenVerifier = - GoogleIdTokenVerifier.Builder( - NetHttpTransport(), - GsonFactory() - ) - .setAudience(listOf(config.getString("google.clientId"))) - .setIssuer("https://accounts.google.com") - .build() - - return verifier.verify(googleToken)?.let { - val payload: GoogleIdToken.Payload = it.payload - - // Print user identifier - val userId: String = payload.subject - println("User ID: $userId") - - // Get profile information from payload - val email: String = payload.email - val imageUrl: String = (payload["picture"] as? String).orEmpty() - val locale: String = payload["locale"] as? String ?: DEFAULT_LANG - val username = email.split("@").firstOrNull() ?: HashGenerator.generateHash() - val user = getUserByEmail(email) - val token = if (user == null) { - val token = register( - RegisterDTO( - username = username, - email = email, - password = EMPTY_TEXT, - isGoogleAuth = true, - lang = locale - ) - ) - getUserByEmail(email)?.let { userNotNull -> - updateUser( - userNotNull.copy( - image = imageUrl - ) - ) - } - token - - } else { - login( - LoginDTO(username = username, password = EMPTY_TEXT, isGoogleAuth = true) - ) - } - token - } - } - - override suspend fun register(register: RegisterDTO): String? { - val currentUser = userLocalDataSource.getUserByUsernameOrEmail(register.username, register.email) - val user = register.toBO() - return if (currentUser == null) { - val wasRegistered = userLocalDataSource.createUser(user) - if (wasRegistered) { - makeToken(user) - - } else { - null - } - - } else { - null - } - } - - override suspend fun getUsers(): List = userLocalDataSource.getAllUsers() - - override suspend fun getUserById(id: String?): UserBO? = id?.let { - userLocalDataSource.getUserById(id) - } - - override suspend fun getUserByUsername(name: String?): UserBO? = name?.let { - userLocalDataSource.getUserByUsername(it) - } - - - override suspend fun getUserByEmail(email: String?): UserBO? = email?.let { - userLocalDataSource.getUserByEmail(it) - } - - override suspend fun updateUser(user: UserBO): Boolean = userLocalDataSource.updateUser(user) -} \ No newline at end of file diff --git a/src/main/kotlin/es/wokis/di/DataSourceModule.kt b/src/main/kotlin/es/wokis/di/DataSourceModule.kt deleted file mode 100644 index 4d39a30..0000000 --- a/src/main/kotlin/es/wokis/di/DataSourceModule.kt +++ /dev/null @@ -1,21 +0,0 @@ -package es.wokis.di - -import com.mongodb.client.MongoCollection -import es.wokis.data.database.AppDataBase -import es.wokis.data.datasource.UserLocalDataSource -import es.wokis.data.datasource.UserLocalDataSourceImpl -import es.wokis.data.dbo.invoice.InvoiceDBO -import es.wokis.data.dbo.user.UserDBO -import org.koin.core.qualifier.named -import org.koin.dsl.module - -val dataSourceModule = module { - single { AppDataBase() } - single(named("usersCollection")) { getUsersCollection(get()) as MongoCollection } - single(named("invoicesCollection")) { getInvoicesCollection(get()) as MongoCollection } - single { UserLocalDataSourceImpl(get(named("usersCollection"))) as UserLocalDataSource } -} - -private fun getUsersCollection(database: AppDataBase) = database.usersCollection - -private fun getInvoicesCollection(database: AppDataBase) = database.invoicesCollection \ No newline at end of file diff --git a/src/main/kotlin/es/wokis/di/RepositoryModule.kt b/src/main/kotlin/es/wokis/di/RepositoryModule.kt deleted file mode 100644 index b425df8..0000000 --- a/src/main/kotlin/es/wokis/di/RepositoryModule.kt +++ /dev/null @@ -1,9 +0,0 @@ -package es.wokis.di - -import es.wokis.data.repository.user.UserRepository -import es.wokis.data.repository.user.UserRepositoryImpl -import org.koin.dsl.module - -val repositoryModule = module { - single { UserRepositoryImpl(get()) as UserRepository } -} \ No newline at end of file diff --git a/src/main/kotlin/es/wokis/plugins/Config.kt b/src/main/kotlin/es/wokis/plugins/Config.kt deleted file mode 100644 index c6b5e33..0000000 --- a/src/main/kotlin/es/wokis/plugins/Config.kt +++ /dev/null @@ -1,24 +0,0 @@ -package es.wokis.plugins - -import com.typesafe.config.Config -import com.typesafe.config.ConfigFactory -import io.ktor.server.application.* -import java.io.File -import java.nio.file.Files -import java.nio.file.Paths -import java.nio.file.StandardCopyOption - -private val configFile = File("config/", "app.conf") -lateinit var config: Config - -fun Application.initConfig() { - // si no existe la config interna, tira una excepción - val internalConf = this::class.java.getResourceAsStream("/app.conf") ?: throw IllegalAccessException() - - if (!configFile.exists()) { - configFile.mkdirs() - Files.copy(internalConf, Paths.get(configFile.path), StandardCopyOption.REPLACE_EXISTING) - } - - config = ConfigFactory.parseFile(File("config/app.conf")) -} diff --git a/src/main/kotlin/es/wokis/plugins/Firebase.kt b/src/main/kotlin/es/wokis/plugins/Firebase.kt deleted file mode 100644 index b27dcbd..0000000 --- a/src/main/kotlin/es/wokis/plugins/Firebase.kt +++ /dev/null @@ -1,21 +0,0 @@ -package es.wokis.plugins - -import com.google.auth.oauth2.GoogleCredentials -import com.google.firebase.FirebaseApp -import com.google.firebase.FirebaseOptions -import io.ktor.server.application.* -import java.io.FileInputStream - - -fun Application.configureFirebase() { - val fileDirectory = config.getString("firebaseSdkDir") - - val serviceAccount = FileInputStream(fileDirectory) - - val options = FirebaseOptions - .builder() - .setCredentials(GoogleCredentials.fromStream(serviceAccount)) - .build() - - FirebaseApp.initializeApp(options) -} \ No newline at end of file diff --git a/src/main/kotlin/es/wokis/plugins/HTTP.kt b/src/main/kotlin/es/wokis/plugins/HTTP.kt index 059df4d..5ac312b 100644 --- a/src/main/kotlin/es/wokis/plugins/HTTP.kt +++ b/src/main/kotlin/es/wokis/plugins/HTTP.kt @@ -1,28 +1,19 @@ package es.wokis.plugins import io.ktor.http.* -import io.ktor.server.application.* import io.ktor.server.plugins.cors.routing.* -import java.time.Duration +import io.ktor.server.application.* +import io.ktor.server.response.* +import io.ktor.server.request.* fun Application.configureHTTP() { install(CORS) { allowMethod(HttpMethod.Options) - allowMethod(HttpMethod.Get) - allowMethod(HttpMethod.Post) allowMethod(HttpMethod.Put) allowMethod(HttpMethod.Delete) allowMethod(HttpMethod.Patch) - allowHeader(HttpHeaders.AccessControlAllowHeaders) - allowHeader(HttpHeaders.ContentType) - allowHeader(HttpHeaders.AccessControlAllowOrigin) allowHeader(HttpHeaders.Authorization) - - allowNonSimpleContentTypes = true - allowCredentials = true - allowSameOrigin = true - maxAgeInSeconds = Duration.ofDays(1).toMinutes() * 60L - - anyHost() // TODO: No dejarlo como anyhost, limitarlo al host final + allowHeader("MyCustomHeader") + anyHost() // @TODO: Don't do this in production if possible. Try to limit it. } } diff --git a/src/main/kotlin/es/wokis/plugins/Koin.kt b/src/main/kotlin/es/wokis/plugins/Koin.kt index 44de897..c775efd 100644 --- a/src/main/kotlin/es/wokis/plugins/Koin.kt +++ b/src/main/kotlin/es/wokis/plugins/Koin.kt @@ -1,19 +1,17 @@ package es.wokis.plugins -import es.wokis.di.dataSourceModule -import es.wokis.di.repositoryModule import io.ktor.server.application.* +import org.koin.dsl.module import org.koin.ktor.plugin.Koin import org.koin.logger.slf4jLogger +val appModules = module { + // TODO: Modules +} + fun Application.configureKoin() { install(Koin) { slf4jLogger() - modules( - listOf( - dataSourceModule, - repositoryModule - ) - ) + modules(appModules) } } \ No newline at end of file diff --git a/src/main/kotlin/es/wokis/plugins/Routing.kt b/src/main/kotlin/es/wokis/plugins/Routing.kt index 9569603..9410408 100644 --- a/src/main/kotlin/es/wokis/plugins/Routing.kt +++ b/src/main/kotlin/es/wokis/plugins/Routing.kt @@ -1,20 +1,14 @@ package es.wokis.plugins import es.wokis.routing.setUpInvoicesRouting -import es.wokis.routing.setUpAuthRouting -import es.wokis.routing.setUpUserRouting import io.ktor.server.routing.* +import io.ktor.http.* import io.ktor.server.application.* import io.ktor.server.response.* +import io.ktor.server.request.* fun Application.configureRouting() { routing { - get("/") { - call.respondText("Hello World from Project Finance!") - } - - setUpAuthRouting() setUpInvoicesRouting() - setUpUserRouting() } } diff --git a/src/main/kotlin/es/wokis/plugins/Security.kt b/src/main/kotlin/es/wokis/plugins/Security.kt index d1b5221..215724a 100644 --- a/src/main/kotlin/es/wokis/plugins/Security.kt +++ b/src/main/kotlin/es/wokis/plugins/Security.kt @@ -1,67 +1,31 @@ package es.wokis.plugins +import io.ktor.server.auth.* +import io.ktor.util.* +import io.ktor.server.auth.jwt.* import com.auth0.jwt.JWT import com.auth0.jwt.JWTVerifier import com.auth0.jwt.algorithms.Algorithm -import com.google.firebase.auth.hash.Bcrypt -import es.wokis.data.bo.user.UserBO -import es.wokis.data.repository.user.UserRepository -import es.wokis.utils.orGeneratePassword import io.ktor.server.application.* -import io.ktor.server.auth.* -import io.ktor.server.auth.jwt.* -import org.koin.ktor.ext.inject -import org.mindrot.jbcrypt.BCrypt -import java.util.* - -private lateinit var jwtIssuer: String -private lateinit var jwtAudience: String -private lateinit var algorithm: Algorithm +import io.ktor.server.response.* +import io.ktor.server.request.* fun Application.configureSecurity() { - val privateKey = config.getString("secretKey") - val userRepository by inject() - val jwtRealm = environment.config.property("jwt.realm").getString() - jwtIssuer = environment.config.property("jwt.domain").getString() - jwtAudience = environment.config.property("jwt.audience").getString() - algorithm = Algorithm.HMAC256(privateKey) - + authentication { - jwt { - realm = jwtRealm - verifier(makeJwtVerifier(jwtIssuer, jwtAudience)) - validate { credential -> - val name = credential.payload.getClaim("username").asString() - val password = credential.payload.getClaim("password").asString() - - val user = userRepository.getUserByUsername(name) - - user?.takeIf { password == it.password } + jwt { + val jwtAudience = this@configureSecurity.environment.config.property("jwt.audience").getString() + realm = this@configureSecurity.environment.config.property("jwt.realm").getString() + verifier( + JWT + .require(Algorithm.HMAC256("secret")) + .withAudience(jwtAudience) + .withIssuer(this@configureSecurity.environment.config.property("jwt.domain").getString()) + .build() + ) + validate { credential -> + if (credential.payload.audience.contains(jwtAudience)) JWTPrincipal(credential.payload) else null + } } } - } - } - -private fun makeJwtVerifier(issuer: String, audience: String): JWTVerifier = - JWT - .require(algorithm) - .withAudience(audience) - .withIssuer(issuer).build() - -/** - * A function that creates a token with given user data. - * - * @param user the user whose token is being made - */ - -fun makeToken(user: UserBO): String = - JWT - .create() - .withSubject("Authentication") - .withIssuer(jwtIssuer) - .withAudience(jwtAudience) - .withClaim("username", user.username) - .withClaim("password", user.password.takeIf { it.isNotBlank() }.orGeneratePassword() ) - .withClaim("timestamp", Date().time) - .sign(algorithm) diff --git a/src/main/kotlin/es/wokis/routing/AuthRouting.kt b/src/main/kotlin/es/wokis/routing/AuthRouting.kt deleted file mode 100644 index cc21e4e..0000000 --- a/src/main/kotlin/es/wokis/routing/AuthRouting.kt +++ /dev/null @@ -1,46 +0,0 @@ -package es.wokis.routing - -import es.wokis.data.dto.user.auth.LoginDTO -import es.wokis.data.dto.user.auth.RegisterDTO -import es.wokis.data.repository.user.UserRepository -import io.ktor.http.* -import io.ktor.server.application.* -import io.ktor.server.request.* -import io.ktor.server.response.* -import io.ktor.server.routing.* -import org.koin.ktor.ext.inject - -fun Routing.setUpAuthRouting() { - val userRepository by inject() - - post("/login") { - val user = call.receive() - val token: String? = userRepository.login(user) - - token?.let { - call.respond(HttpStatusCode.OK, it) - } ?: run { - call.respond(HttpStatusCode.NotFound, "Wrong username or password") - } - } - - post("/register") { - val user = call.receive() - - val token: String? = userRepository.register(user) - - token?.let { - call.respond(HttpStatusCode.OK, it) - } ?: run { - call.respond(HttpStatusCode.Conflict, "That user already exists") - } - } - - post("/google-auth") { - val googleToken = call.receive() - val token: String? = userRepository.loginWithGoogle(googleToken) - token?.let { - call.respond(HttpStatusCode.OK, it) - } ?: call.respond(HttpStatusCode.NotFound, "That user doesn't exists.") - } -} \ No newline at end of file diff --git a/src/main/kotlin/es/wokis/routing/InvoicesRouting.kt b/src/main/kotlin/es/wokis/routing/InvoicesRouting.kt index c67d2f2..c1924b0 100644 --- a/src/main/kotlin/es/wokis/routing/InvoicesRouting.kt +++ b/src/main/kotlin/es/wokis/routing/InvoicesRouting.kt @@ -1,12 +1,7 @@ package es.wokis.routing -import es.wokis.data.repository.user.UserRepository -import io.ktor.server.application.* -import io.ktor.server.response.* import io.ktor.server.routing.* -import org.koin.ktor.ext.inject fun Routing.setUpInvoicesRouting() { - val userRepository by inject() // TODO: change to invoices repository } \ No newline at end of file diff --git a/src/main/kotlin/es/wokis/routing/UserRouting.kt b/src/main/kotlin/es/wokis/routing/UserRouting.kt deleted file mode 100644 index 5a37939..0000000 --- a/src/main/kotlin/es/wokis/routing/UserRouting.kt +++ /dev/null @@ -1,19 +0,0 @@ -package es.wokis.routing - -import es.wokis.data.mapper.user.toDTO -import es.wokis.data.repository.user.UserRepository -import io.ktor.server.application.* -import io.ktor.server.auth.* -import io.ktor.server.response.* -import io.ktor.server.routing.* -import org.koin.ktor.ext.inject - -fun Routing.setUpUserRouting() { - val userRepository by inject() - authenticate { - get("/users") { - val users = userRepository.getUsers().toDTO() - call.respond(users) - } - } -} \ No newline at end of file diff --git a/src/main/kotlin/es/wokis/services/EmailService.kt b/src/main/kotlin/es/wokis/services/EmailService.kt deleted file mode 100644 index 14e4383..0000000 --- a/src/main/kotlin/es/wokis/services/EmailService.kt +++ /dev/null @@ -1,61 +0,0 @@ -package es.wokis.services - -import es.wokis.data.bo.user.UserBO -import es.wokis.data.bo.verification.VerificationBO -import es.wokis.plugins.config -import es.wokis.utils.HashGenerator -import java.util.* -import javax.mail.Message -import javax.mail.MessagingException -import javax.mail.Session -import javax.mail.internet.InternetAddress -import javax.mail.internet.MimeMessage - -class EmailService { - private val fromEmail = config.getString("mail.user") - private val fromPassword = config.getString("mail.pass") - - private val about = "Invitacion" - - fun sendEmail(user: UserBO): VerificationBO { - val emailHtml = this::class.java.getResource("/emails/${user.lang}/email-verify.html") ?: throw IllegalAccessException() - - val properties: Properties = System.getProperties().apply { - put("mail.smtp.host", "email.wokis.es") - put("mail.smtp.user", fromEmail) - put("mail.smtp.clave", fromPassword) - put("mail.smtp.auth", "true") - put("mail.smtp.starttls.enable", "true") - put("mail.smtp.ssl.trust", "email.wokis.es"); - put("mail.smtp.port", 587) - } - val hash = HashGenerator.generateHash(20) - val cuerpo = emailHtml.readText() - - val session = Session.getDefaultInstance(properties) - val message = MimeMessage(session) - - try { - with(message) { - setFrom(InternetAddress(fromEmail)) - addRecipients(Message.RecipientType.TO, user.email) - subject = about - setContent(cuerpo, "text/html") - } - - with(session.getTransport("smtp")) { - connect("email.wokis.es", fromEmail, fromPassword) - sendMessage(message, message.allRecipients) - close() - } - - } catch (e: MessagingException) { - println(e.message) - } - - return VerificationBO( - email = user.email, - verificationToken = hash - ) - } -} \ No newline at end of file diff --git a/src/main/kotlin/es/wokis/services/NotificationService.kt b/src/main/kotlin/es/wokis/services/NotificationService.kt deleted file mode 100644 index 1431cac..0000000 --- a/src/main/kotlin/es/wokis/services/NotificationService.kt +++ /dev/null @@ -1,24 +0,0 @@ -package es.wokis.services - -import com.google.firebase.messaging.FirebaseMessaging -import com.google.firebase.messaging.MulticastMessage -import es.wokis.data.bo.user.UserBO - - -fun sendNotifications(users: List) { - val registrationTokens: List = users.flatMap { it.devices } - - val message = MulticastMessage.builder() - .putData("score", "850") - .putData("time", "2:45") - .addAllTokens(registrationTokens) - .build() - val response = FirebaseMessaging.getInstance().sendMulticast(message) - if (response.failureCount > 0) { - val responses = response.responses - val failedTokens: List = responses.mapIndexedNotNull { index, sendResponse -> - if (!sendResponse.isSuccessful) registrationTokens[index] else null - } - println("List of tokens that caused failures: $failedTokens") - } -} diff --git a/src/main/kotlin/es/wokis/utils/BooleanUtils.kt b/src/main/kotlin/es/wokis/utils/BooleanUtils.kt deleted file mode 100644 index 562b6ae..0000000 --- a/src/main/kotlin/es/wokis/utils/BooleanUtils.kt +++ /dev/null @@ -1,5 +0,0 @@ -package es.wokis.utils - -fun Boolean?.isTrue() = this == true - -fun Boolean?.isFalse() = this == false \ No newline at end of file diff --git a/src/main/kotlin/es/wokis/utils/CredentialsUtils.kt b/src/main/kotlin/es/wokis/utils/CredentialsUtils.kt deleted file mode 100644 index d78dd8f..0000000 --- a/src/main/kotlin/es/wokis/utils/CredentialsUtils.kt +++ /dev/null @@ -1,12 +0,0 @@ -package es.wokis.utils - -import es.wokis.data.bo.user.UserBO -import io.ktor.server.application.* -import io.ktor.server.auth.* -import org.mindrot.jbcrypt.BCrypt - -val ApplicationCall.user: UserBO? get() = authentication.principal() - -fun String?.orGeneratePassword(): String = this ?: generatePassword() - -fun generatePassword() = BCrypt.hashpw(HashGenerator.generateHash(20), BCrypt.gensalt()) \ No newline at end of file diff --git a/src/main/kotlin/es/wokis/utils/DateUtils.kt b/src/main/kotlin/es/wokis/utils/DateUtils.kt deleted file mode 100644 index d387270..0000000 --- a/src/main/kotlin/es/wokis/utils/DateUtils.kt +++ /dev/null @@ -1,15 +0,0 @@ -package es.wokis.projectfinance.utils - -import java.text.SimpleDateFormat -import java.util.* - -private const val DATE_FORMAT = "dd/MM/yyyy" - -private val dateFormatter = SimpleDateFormat(DATE_FORMAT, Locale.ROOT) - -fun String.toDate(): Date = dateFormatter.parse(this) ?: Date() - -fun Date.toStringFormatted(): String = dateFormatter.format(this) - -fun getDateFormatted(day: Int, month: Int, year: Int): String = - "$day/$month/$year".toDate().toStringFormatted() \ No newline at end of file diff --git a/src/main/kotlin/es/wokis/utils/HashGenerator.kt b/src/main/kotlin/es/wokis/utils/HashGenerator.kt deleted file mode 100644 index 69a09bd..0000000 --- a/src/main/kotlin/es/wokis/utils/HashGenerator.kt +++ /dev/null @@ -1,23 +0,0 @@ - -package es.wokis.utils - -import es.wokis.data.constants.ServerConstants -import java.util.* -import kotlin.streams.asSequence - -object HashGenerator { - /** - * Genera un hash aleatorio con la longitud indicada. - * - * @param length la longitud del hash. Es opcional, tiene una de serie de 12 caracteres. - * @return el hash generado como [String] - * - */ - fun generateHash(length: Long = 12L): String { - val hashSource = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-_" - return Random().ints(length, 0, hashSource.length-1) - .asSequence() - .map(hashSource::get) - .joinToString(ServerConstants.EMPTY_TEXT) - } -} \ No newline at end of file diff --git a/src/main/resources/app.conf b/src/main/resources/app.conf deleted file mode 100644 index e24c1a7..0000000 --- a/src/main/resources/app.conf +++ /dev/null @@ -1,29 +0,0 @@ -# Hello, human! This is ProjectFinance's Server config. -# If you're seeing this, welcome! Just edit whatever you want, but be sure what are you editing. - -# Used to generate the token -secretKey = "pestillo" - -# Some DB conf, if you don't know what you're modifying, leave it at it is. -db { - ip = "localhost" - port = "27017" - user = "user" - password = "pass" - databaseName = "project-finance" -} - -# used to store avatars -imageFolder = "images/" - -mail { - user = "test@test.es" - pass = "abc123." -} - -firebaseSdkDir = "config/firebaseSdk.json" - -google { - clientId = "google_client_id" - clientSecret = "google_client_secret" -} \ No newline at end of file diff --git a/src/main/resources/application.conf b/src/main/resources/application.conf deleted file mode 100644 index 8ac2e4d..0000000 --- a/src/main/resources/application.conf +++ /dev/null @@ -1,24 +0,0 @@ -# ktor config -ktor { - deployment { - host = "0.0.0.0" - port = 8080 - } - - application { - modules = [ es.wokis.ApplicationKt.module ] - development = false - } -} - -#jwt config -jwt { - domain = "https://finance.projectalpha.es/" - audience = "wokis" - realm = "projectfinance wokis" -} - -# secret key for JWT encryption -secret { - key = "pestillo" -} \ No newline at end of file