Skip to content

Commit

Permalink
Merge pull request #5 from groupeminaste/fix/validators
Browse files Browse the repository at this point in the history
Using validators to check user payloads
  • Loading branch information
nathanfallet committed Dec 8, 2023
2 parents 0a08996 + ce4370e commit 4df10da
Show file tree
Hide file tree
Showing 12 changed files with 72 additions and 33 deletions.
6 changes: 3 additions & 3 deletions extopy-backend/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ kotlin {
val koinVersion = "3.5.0"
val exposedVersion = "0.40.1"
val logbackVersion = "0.9.30"
val ktorxVersion = "1.6.1"
val ktorxVersion = "1.6.2"

sourceSets {
val commonMain by getting {
Expand Down Expand Up @@ -60,13 +60,13 @@ kotlin {
implementation("ch.qos.logback:logback-core:$logbackVersion")
implementation("ch.qos.logback:logback-classic:$logbackVersion")

implementation("me.nathanfallet.i18n:i18n:1.0.4")
implementation("me.nathanfallet.i18n:i18n:1.0.5")
implementation("me.nathanfallet.ktorx:ktor-i18n:$ktorxVersion")
implementation("me.nathanfallet.ktorx:ktor-i18n-freemarker:$ktorxVersion")
implementation("me.nathanfallet.ktorx:ktor-routers:$ktorxVersion")
implementation("me.nathanfallet.ktorx:ktor-routers-locale:$ktorxVersion")
implementation("me.nathanfallet.ktorx:ktor-sentry:$ktorxVersion")
implementation("me.nathanfallet.cloudflare:cloudflare-api-client:4.0.7")
implementation("me.nathanfallet.cloudflare:cloudflare-api-client:4.0.8")

implementation("com.mysql:mysql-connector-j:8.0.33")
implementation("at.favre.lib:bcrypt:0.9.0")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,24 @@ class DatabaseUsersRepository(
override suspend fun update(id: String, payload: UpdateUserPayload, context: IContext?): Boolean {
return database.dbQuery {
Users.update({ Users.id eq id }) {
payload.displayName?.let { displayName -> it[Users.displayName] = displayName }
payload.username?.let { username -> it[Users.username] = username }
payload.biography?.let { biography -> it[Users.biography] = biography }
payload.avatar?.let { avatar -> it[Users.avatar] = avatar }
payload.personal?.let { personal -> it[Users.personal] = personal }
payload.username?.let { username ->
it[Users.username] = username
}
payload.displayName?.let { displayName ->
it[Users.displayName] = displayName
}
payload.password?.let { password ->
it[Users.password] = password
}
payload.biography?.let { biography ->
it[Users.biography] = biography
}
payload.avatar?.let { avatar ->
it[Users.avatar] = avatar
}
payload.personal?.let { personal ->
it[Users.personal] = personal
}
}
} == 1
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import me.nathanfallet.extopy.usecases.application.SendEmailUseCase
import me.nathanfallet.extopy.usecases.auth.*
import me.nathanfallet.extopy.usecases.users.CreateUserUseCase
import me.nathanfallet.extopy.usecases.users.GetUserForCallUseCase
import me.nathanfallet.extopy.usecases.users.UpdateUserUseCase
import me.nathanfallet.i18n.usecases.localization.TranslateUseCase
import me.nathanfallet.ktorx.controllers.IModelController
import me.nathanfallet.ktorx.controllers.auth.AuthWithCodeController
Expand All @@ -39,7 +40,6 @@ import me.nathanfallet.usecases.models.create.ICreateModelSuspendUseCase
import me.nathanfallet.usecases.models.get.context.GetModelWithContextFromRepositorySuspendUseCase
import me.nathanfallet.usecases.models.get.context.IGetModelWithContextSuspendUseCase
import me.nathanfallet.usecases.models.update.IUpdateModelSuspendUseCase
import me.nathanfallet.usecases.models.update.UpdateModelFromRepositorySuspendUseCase
import org.koin.core.qualifier.named
import org.koin.dsl.module
import org.koin.ktor.plugin.Koin
Expand Down Expand Up @@ -107,7 +107,7 @@ fun Application.configureKoin() {
CreateUserUseCase(get(), get())
}
single<IUpdateModelSuspendUseCase<User, String, UpdateUserPayload>>(named<User>()) {
UpdateModelFromRepositorySuspendUseCase(get<IUsersRepository>())
UpdateUserUseCase(get(), get())
}
}
val controllerModule = module {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,6 @@ class CreateUserUseCase(
) : ICreateModelSuspendUseCase<User, CreateUserPayload> {

override suspend fun invoke(input: CreateUserPayload): User? {
// TODO: Update with https://github.com/nathanfallet/usecases/issues/16
if (input.username.length > 25) throw ControllerException(
HttpStatusCode.BadRequest,
"auth_register_username_too_long"
)
if (input.displayName.length > 40) throw ControllerException(
HttpStatusCode.BadRequest,
"auth_register_displayName_too_long"
)
if (!User.usernameRegex.matches(input.username)) throw ControllerException(
HttpStatusCode.BadRequest,
"auth_register_username_invalid"
)
repository.getForUsernameOrEmail(input.username, false)?.let {
throw ControllerException(
HttpStatusCode.BadRequest,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package me.nathanfallet.extopy.usecases.users

import io.ktor.http.*
import me.nathanfallet.extopy.models.users.UpdateUserPayload
import me.nathanfallet.extopy.models.users.User
import me.nathanfallet.extopy.repositories.users.IUsersRepository
import me.nathanfallet.extopy.usecases.auth.IHashPasswordUseCase
import me.nathanfallet.ktorx.models.exceptions.ControllerException
import me.nathanfallet.usecases.models.update.IUpdateModelSuspendUseCase

class UpdateUserUseCase(
private val repository: IUsersRepository,
private val hashPasswordUseCase: IHashPasswordUseCase,
) : IUpdateModelSuspendUseCase<User, String, UpdateUserPayload> {

override suspend fun invoke(input1: String, input2: UpdateUserPayload): User? {
input2.username?.let {
repository.getForUsernameOrEmail(it, false)?.let {
throw ControllerException(
HttpStatusCode.BadRequest,
"auth_register_username_taken"
)
}
}
val updatedUser = input2.password?.let {
input2.copy(password = hashPasswordUseCase(it))
} ?: input2
return if (repository.update(input1, updatedUser)) repository.get(input1)
else null
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,6 @@ auth_register_code_created=Please check your inbox to complete your registration
auth_register_email_taken=This email is already taken
auth_register_email_title=Suite BDE - Registration
auth_register_email_body=Please click on the following link to complete your registration: {0}
auth_register_username_too_long=Username is too long (max length is 25 characters)
auth_register_displayName_too_long=Display name is too long (max length is 40 characters)
auth_register_username_invalid=Username can only contain alphanumeric characters and underscores
auth_register_username_taken=This username is already taken
auth_reset_title=Reset my password
auth_code_invalid=Invalid code
Expand All @@ -29,3 +26,6 @@ users_create_not_allowed=You are not allowed to create users
users_update_not_allowed=You are not allowed to update users
users_delete_not_allowed=You cannot delete users
users_list_not_allowed=You are not allowed to list users
users_username_regex=Username can only contain alphanumeric characters and underscores
users_username_maxLength=Username is too long (max length is 25 characters)
users_displayName_maxLength=Display name is too long (max length is 40 characters)
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
users_not_found=Utilisateur non trouv\u00E9
auth_register_displayName_too_long=Nom d'affichage trop long (maximum 40 caract\u00E8res)
users_displayName_maxLength=Nom d'affichage trop long (maximum 40 caract\u00E8res)
error_body_invalid=Corps invalide
auth_field_displayName=Nom d'affichage
users_update_not_allowed=Vous n'avez pas le droit de modifier des utilisateurs
auth_hint_password_forgotten=Mot de passe oubli\u00E9 ?
auth_code_invalid=Code invalide
auth_field_password=Mot de passe
auth_reset_title=R\u00E9initialiser mon mot de passe
auth_register_username_invalid=Le nom d'utilisateur ne peut contenir que des caract\u00E8res alphanum\u00E9riques et des underscores
users_username_regex=Le nom d'utilisateur ne peut contenir que des caract\u00E8res alphanum\u00E9riques et des underscores
auth_hint_no_account=Pas encore de compte ?
auth_register_email_taken=Cette adresse email est d\u00E9j\u00E0 utilis\u00E9e
error_internal=Une erreur interne est survenue
auth_invalid_credentials=Identifiants incorrects
auth_register_username_too_long=Nom d'utilisateur trop long (maximum 25 caract\u00E8res)
users_username_maxLength=Nom d'utilisateur trop long (maximum 25 caract\u00E8res)
auth_register_username_taken=Nom d'utilisateur d\u00E9j\u00E0 utilis\u00E9
auth_field_username=Nom d'utilisateur
auth_redirect=Redirection\u2026
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ class DatabaseUsersRepositoryTest {
displayName = "displayName2",
biography = "biography2",
)
val payload = UpdateUserPayload("username2", "displayName2", "biography2", null, null)
val payload = UpdateUserPayload("username2", "displayName2", null, "biography2")
assertEquals(true, repository.update(user.id, payload))
val userFromDatabase = database.dbQuery {
Users
Expand All @@ -163,7 +163,7 @@ class DatabaseUsersRepositoryTest {
fun updateUserNotExists() = runBlocking {
val database = Database(protocol = "h2", name = "updateUserNotExists")
val repository = DatabaseUsersRepository(database)
val payload = UpdateUserPayload("username2", "displayName2", "biography2", null, null)
val payload = UpdateUserPayload("username2", "displayName2", null, "biography2")
assertEquals(false, repository.update("userId", payload))
}

Expand Down
2 changes: 1 addition & 1 deletion extopy-commons/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ kotlin {

applyDefaultHierarchyTemplate()

val usecasesVersion = "1.5.0"
val usecasesVersion = "1.5.1"

sourceSets {
val commonMain by getting {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,13 @@ package me.nathanfallet.extopy.models.users

import kotlinx.datetime.LocalDate
import kotlinx.serialization.Serializable
import me.nathanfallet.usecases.models.annotations.validators.StringPropertyValidator

@Serializable
data class CreateUserPayload(
@StringPropertyValidator(regex = User.USERNAME_REGEX, maxLength = 25)
val username: String,
@StringPropertyValidator(maxLength = 40)
val displayName: String,
val email: String,
val password: String,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
package me.nathanfallet.extopy.models.users

import kotlinx.serialization.Serializable
import me.nathanfallet.usecases.models.annotations.validators.StringPropertyValidator

@Serializable
data class UpdateUserPayload(
@StringPropertyValidator(regex = User.USERNAME_REGEX, maxLength = 25)
val username: String? = null,
@StringPropertyValidator(maxLength = 40)
val displayName: String? = null,
val password: String? = null,
val biography: String? = null,
val avatar: String? = null,
val personal: Boolean? = null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ data class User(

companion object {

val usernameRegex = Regex("[a-zA-Z0-9_]+")
const val USERNAME_REGEX = "[a-zA-Z0-9_]+"

}

Expand Down

0 comments on commit 4df10da

Please sign in to comment.