Skip to content

Commit

Permalink
Conditional validation
Browse files Browse the repository at this point in the history
  • Loading branch information
SAUL committed Oct 24, 2024
1 parent 8977f94 commit dadfb61
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 21 deletions.
35 changes: 30 additions & 5 deletions src/main/kotlin/core/form/validation/CommonRules.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package core.form.validation

import core.form.FormField
import java.util.*

val emailRule: ValidationRule = ValidationRule(
Expand All @@ -9,8 +10,19 @@ val emailRule: ValidationRule = ValidationRule(
errorMessage = "Invalid email address"
)

val emailIfNotNullRule: ValidationRule = ValidationRule(
condition = { email ->
if (email.isNotEmpty()) {
emailRule.condition.invoke(email)
} else {
true
}
},
errorMessage = "Invalid email address"
)

val urlRule: ValidationRule = ValidationRule(
condition = {url ->
condition = { url ->
url.matches(Regex("^https?://(?:www\\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\\.[a-zA-Z0-9()]{1,6}\\b[-a-zA-Z0-9()@:%_+.~#?&/=]*$"))
},
errorMessage = "Invalid URL"
Expand All @@ -19,10 +31,10 @@ val urlRule: ValidationRule = ValidationRule(
val passwordRule: ValidationRule = ValidationRule(
condition = { password ->
password.length >= 8 &&
password.any { it.isDigit() } &&
password.any { it.isUpperCase() } &&
password.any { it.isLowerCase() } &&
password.any { it in "!@#$%^&*()-_=+[]{}|;:'\",.<>?/~`" }
password.any { it.isDigit() } &&
password.any { it.isUpperCase() } &&
password.any { it.isLowerCase() } &&
password.any { it in "!@#$%^&*()-_=+[]{}|;:'\",.<>?/~`" }
},
errorMessage = "Password must be 8+ chars, with a number, symbol, upper & lower case."
)
Expand Down Expand Up @@ -69,3 +81,16 @@ fun notNullRule(field: String): ValidationRule {
errorMessage = "$field must not be null"
)
}

fun conditionalRule(comparingField: () -> FormField, rules: List<ValidationRule>): ValidationRule {
return ValidationRule(
condition = { input ->
if (comparingField().value.value.isNotEmpty()) {
true
} else {
rules.all { rule -> rule.condition(input) }
}
},
errorMessage = rules.firstOrNull()?.errorMessage ?: "Invalid input"
)
}
11 changes: 8 additions & 3 deletions src/main/kotlin/core/form/validation/Validator.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,19 @@ class Validator {
private val rules = mutableListOf<ValidationRule>()

fun addRule(rule: ValidationRule): Validator {
rules.add(rule)
this.rules.add(rule)
return this
}

fun addRules(additionalRules: List<ValidationRule>): Validator {
this.rules.addAll(additionalRules)
return this
}

fun validate(input: String): Pair<Boolean, String?> {
return rules.firstOrNull { !it.condition(input) }
?.let { false to it.errorMessage }
?: (true to null)
?.let { false to it.errorMessage }
?: (true to null)
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import repository.password.Password
import repository.password.PasswordRepository
import repository.password.PasswordsTable
import repository.password.projection.PasswordSummary
import java.util.*

class PasswordRepositoryImpl(
private val db: Database,
Expand All @@ -41,13 +42,13 @@ class PasswordRepositoryImpl(
query.andWhere { PasswordsTable.user eq it }
}

query.orderBy(toSort(searchCriteria.sort), toOrder(searchCriteria.sort)).map {
query.orderBy(toSort(searchCriteria.sort), toOrder(searchCriteria.sort)).map { resultRow ->
PasswordSummary(
id = it[PasswordsTable.id].value,
name = it[PasswordsTable.name],
username = it[PasswordsTable.username],
email = it[PasswordsTable.email],
favorite = it[PasswordsTable.favorite]
id = resultRow[PasswordsTable.id].value,
name = resultRow[PasswordsTable.name].replaceFirstChar { if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else it.toString() },
username = resultRow[PasswordsTable.username],
email = resultRow[PasswordsTable.email],
favorite = resultRow[PasswordsTable.favorite]
)
}
}.let { Result.Success(it) }
Expand Down
2 changes: 2 additions & 0 deletions src/main/kotlin/ui/components/forms/PasswordForm.kt
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ fun PasswordForm(
onValueChange = { newValue ->
userName?.value?.value = newValue
formValidator.validateField(PasswordFormFieldName.USERNAME)
formValidator.validateField(PasswordFormFieldName.EMAIL)
},
label = "Username",
icon = Icons.Filled.AccountCircle,
Expand All @@ -112,6 +113,7 @@ fun PasswordForm(
onValueChange = { newValue ->
email?.value?.value = newValue
formValidator.validateField(PasswordFormFieldName.EMAIL)
formValidator.validateField(PasswordFormFieldName.USERNAME)
},
label = "Email",
icon = Icons.Filled.Email,
Expand Down
28 changes: 21 additions & 7 deletions src/main/kotlin/ui/validators/PasswordFormValidator.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,16 @@ import core.models.dto.PasswordDto
import repository.user.User

fun passwordFormValidator(): FormValidator {
return FormValidator()
val validator = FormValidator()
.addField(
PasswordFormFieldName.USERNAME, FormField(
validator = Validator()
.addRule(notNullRule(PasswordFormFieldName.USERNAME.fieldName))
.addRule(lengthRule(PasswordFormFieldName.USERNAME.fieldName, 1))
)
)
.addField(
PasswordFormFieldName.EMAIL, FormField(
validator = Validator()
.addRule(notNullRule(PasswordFormFieldName.EMAIL.fieldName))
.addRule(lengthRule(PasswordFormFieldName.EMAIL.fieldName, 1))
.addRule(emailRule)
.addRule(emailIfNotNullRule)
)
)
.addField(
Expand Down Expand Up @@ -52,7 +48,25 @@ fun passwordFormValidator(): FormValidator {
.addRule(lengthRule(PasswordFormFieldName.WEBSITE_ICON_URL.fieldName, 1))
.addRule(urlRule)
)
).validateAllFields()
)

validator.getField(PasswordFormFieldName.USERNAME)?.validator
?.addRule(
conditionalRule(
{ validator.getField(PasswordFormFieldName.EMAIL)!! },
listOf(notNullRule(PasswordFormFieldName.USERNAME.fieldName))
)
)

validator.getField(PasswordFormFieldName.EMAIL)?.validator
?.addRule(
conditionalRule(
{ validator.getField(PasswordFormFieldName.USERNAME)!! },
listOf(notNullRule(PasswordFormFieldName.EMAIL.fieldName))
)
)

return validator.validateAllFields()
}

fun toPasswordDto(formValidator: FormValidator, user: User): PasswordDto {
Expand Down

0 comments on commit dadfb61

Please sign in to comment.