Refactor: Use common password validator
Refactors password validation logic to use a common `PasswordValidator` utility. This ensures consistent password validation rules across different parts of the application, including: - User login - Email sign-up - Password change - Account removal Also adds a string resource for password too long error message.
This commit is contained in:
@@ -30,6 +30,7 @@ import com.aiosman.ravenow.ui.comment.NoticeScreenHeader
|
||||
import com.aiosman.ravenow.ui.composables.ActionButton
|
||||
import com.aiosman.ravenow.ui.composables.StatusBarSpacer
|
||||
import com.aiosman.ravenow.ui.composables.TextInputField
|
||||
import com.aiosman.ravenow.utils.PasswordValidator
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
/**
|
||||
@@ -58,7 +59,7 @@ fun ChangePasswordScreen() {
|
||||
var currentPassword by remember { mutableStateOf("") }
|
||||
var newPassword by remember { mutableStateOf("") }
|
||||
var confirmPassword by remember { mutableStateOf("") }
|
||||
var errorMessage by remember { mutableStateOf("") }
|
||||
|
||||
val scope = rememberCoroutineScope()
|
||||
val navController = LocalNavController.current
|
||||
var oldPasswordError by remember { mutableStateOf<String?>(null) }
|
||||
@@ -66,17 +67,18 @@ fun ChangePasswordScreen() {
|
||||
var passwordError by remember { mutableStateOf<String?>(null) }
|
||||
val AppColors = LocalAppTheme.current
|
||||
fun validate(): Boolean {
|
||||
oldPasswordError =
|
||||
if (currentPassword.isEmpty()) "Please enter your current password" else null
|
||||
passwordError = when {
|
||||
newPassword.length < 8 -> "Password must be at least 8 characters long"
|
||||
!newPassword.any { it.isDigit() } -> "Password must contain at least one digit"
|
||||
!newPassword.any { it.isUpperCase() } -> "Password must contain at least one uppercase letter"
|
||||
!newPassword.any { it.isLowerCase() } -> "Password must contain at least one lowercase letter"
|
||||
else -> null
|
||||
}
|
||||
confirmPasswordError =
|
||||
if (newPassword != confirmPassword) "Passwords do not match" else null
|
||||
// 使用通用密码校验器校验当前密码
|
||||
val currentPasswordValidation = PasswordValidator.validateCurrentPassword(currentPassword, context)
|
||||
oldPasswordError = if (!currentPasswordValidation.isValid) currentPasswordValidation.errorMessage else null
|
||||
|
||||
// 使用通用密码校验器校验新密码
|
||||
val newPasswordValidation = PasswordValidator.validatePassword(newPassword, context)
|
||||
passwordError = if (!newPasswordValidation.isValid) newPasswordValidation.errorMessage else null
|
||||
|
||||
// 使用通用密码确认校验器
|
||||
val confirmPasswordValidation = PasswordValidator.validatePasswordConfirmation(newPassword, confirmPassword, context)
|
||||
confirmPasswordError = if (!confirmPasswordValidation.isValid) confirmPasswordValidation.errorMessage else null
|
||||
|
||||
return passwordError == null && confirmPasswordError == null && oldPasswordError == null
|
||||
}
|
||||
Column(
|
||||
|
||||
@@ -46,6 +46,7 @@ import com.aiosman.ravenow.ui.NavigationRoute
|
||||
import com.aiosman.ravenow.ui.comment.NoticeScreenHeader
|
||||
import com.aiosman.ravenow.ui.composables.ActionButton
|
||||
import com.aiosman.ravenow.ui.composables.StatusBarSpacer
|
||||
import com.aiosman.ravenow.utils.PasswordValidator
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@Composable
|
||||
@@ -58,8 +59,10 @@ fun RemoveAccountScreen() {
|
||||
val context = LocalContext.current
|
||||
|
||||
fun removeAccount(password: String) {
|
||||
if (password.isEmpty()) {
|
||||
passwordError = "Please enter your correct password"
|
||||
// 使用通用密码校验器
|
||||
val passwordValidation = PasswordValidator.validateCurrentPassword(password, context)
|
||||
if (!passwordValidation.isValid) {
|
||||
passwordError = passwordValidation.errorMessage
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -39,6 +39,7 @@ import com.aiosman.ravenow.ui.composables.CheckboxWithLabel
|
||||
import com.aiosman.ravenow.ui.composables.PolicyCheckbox
|
||||
import com.aiosman.ravenow.ui.composables.StatusBarSpacer
|
||||
import com.aiosman.ravenow.ui.composables.TextInputField
|
||||
import com.aiosman.ravenow.utils.PasswordValidator
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@@ -70,24 +71,13 @@ fun EmailSignupScreen() {
|
||||
|
||||
else -> null
|
||||
}
|
||||
passwordError = when {
|
||||
// 非空
|
||||
password.isEmpty() -> context.getString(R.string.text_error_password_required)
|
||||
// 至少6位
|
||||
password.length < 6 -> context.getString(R.string.text_error_password_format)
|
||||
// 至少一个数字
|
||||
!password.matches(Regex(".*\\d.*")) -> context.getString(R.string.text_error_password_format)
|
||||
// 包含字母
|
||||
!password.matches(Regex(".*[a-zA-Z].*")) -> context.getString(R.string.text_error_password_format)
|
||||
else -> null
|
||||
}
|
||||
confirmPasswordError = when {
|
||||
// 非空
|
||||
confirmPassword.isEmpty() -> context.getString(R.string.text_error_confirm_password_required)
|
||||
// 与密码一致
|
||||
confirmPassword != password -> context.getString(R.string.text_error_confirm_password_mismatch)
|
||||
else -> null
|
||||
}
|
||||
// 使用通用密码校验器
|
||||
val passwordValidation = PasswordValidator.validatePassword(password, context)
|
||||
passwordError = if (!passwordValidation.isValid) passwordValidation.errorMessage else null
|
||||
|
||||
// 使用通用密码确认校验器
|
||||
val confirmPasswordValidation = PasswordValidator.validatePasswordConfirmation(password, confirmPassword, context)
|
||||
confirmPasswordError = if (!confirmPasswordValidation.isValid) confirmPasswordValidation.errorMessage else null
|
||||
if (!acceptTerms) {
|
||||
scope.launch(Dispatchers.Main) {
|
||||
Toast.makeText(
|
||||
|
||||
@@ -51,6 +51,7 @@ import com.aiosman.ravenow.ui.composables.StatusBarSpacer
|
||||
import com.aiosman.ravenow.ui.composables.TextInputField
|
||||
import com.aiosman.ravenow.ui.modifiers.noRippleClickable
|
||||
import com.aiosman.ravenow.utils.GoogleLogin
|
||||
import com.aiosman.ravenow.utils.PasswordValidator
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
|
||||
@@ -71,8 +72,11 @@ fun UserAuthScreen() {
|
||||
fun validateForm(): Boolean {
|
||||
emailError =
|
||||
if (email.isEmpty()) context.getString(R.string.text_error_email_required) else null
|
||||
passwordError =
|
||||
if (password.isEmpty()) context.getString(R.string.text_error_password_required) else null
|
||||
|
||||
// 使用通用密码校验器
|
||||
val passwordValidation = PasswordValidator.validateCurrentPassword(password, context)
|
||||
passwordError = if (!passwordValidation.isValid) passwordValidation.errorMessage else null
|
||||
|
||||
return emailError == null && passwordError == null
|
||||
}
|
||||
|
||||
|
||||
125
app/src/main/java/com/aiosman/ravenow/utils/PasswordValidator.kt
Normal file
125
app/src/main/java/com/aiosman/ravenow/utils/PasswordValidator.kt
Normal file
@@ -0,0 +1,125 @@
|
||||
package com.aiosman.ravenow.utils
|
||||
|
||||
import android.content.Context
|
||||
import com.aiosman.ravenow.R
|
||||
|
||||
/**
|
||||
* 密码校验工具类
|
||||
* 提供统一的密码校验规则和错误信息
|
||||
*/
|
||||
object PasswordValidator {
|
||||
|
||||
/**
|
||||
* 密码最大长度限制
|
||||
*/
|
||||
const val MAX_PASSWORD_LENGTH = 64
|
||||
|
||||
/**
|
||||
* 密码最小长度限制
|
||||
*/
|
||||
const val MIN_PASSWORD_LENGTH = 6
|
||||
|
||||
/**
|
||||
* 密码校验结果
|
||||
*/
|
||||
data class ValidationResult(
|
||||
val isValid: Boolean,
|
||||
val errorMessage: String? = null
|
||||
)
|
||||
|
||||
/**
|
||||
* 校验密码格式
|
||||
* @param password 密码
|
||||
* @param context 上下文,用于获取本地化错误信息
|
||||
* @return 校验结果
|
||||
*/
|
||||
fun validatePassword(password: String, context: Context): ValidationResult {
|
||||
return when {
|
||||
// 检查是否为空
|
||||
password.isEmpty() -> ValidationResult(
|
||||
false,
|
||||
context.getString(R.string.text_error_password_required)
|
||||
)
|
||||
|
||||
// 检查长度不能超过64个字符
|
||||
password.length > MAX_PASSWORD_LENGTH -> ValidationResult(
|
||||
false,
|
||||
context.getString(R.string.text_error_password_too_long, MAX_PASSWORD_LENGTH)
|
||||
)
|
||||
|
||||
// 检查最小长度
|
||||
password.length < MIN_PASSWORD_LENGTH -> ValidationResult(
|
||||
false,
|
||||
context.getString(R.string.text_error_password_format)
|
||||
)
|
||||
|
||||
// 检查是否包含至少一个数字
|
||||
!password.matches(Regex(".*\\d.*")) -> ValidationResult(
|
||||
false,
|
||||
context.getString(R.string.text_error_password_format)
|
||||
)
|
||||
|
||||
// 检查是否包含字母
|
||||
!password.matches(Regex(".*[a-zA-Z].*")) -> ValidationResult(
|
||||
false,
|
||||
context.getString(R.string.text_error_password_format)
|
||||
)
|
||||
|
||||
else -> ValidationResult(true)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验密码确认
|
||||
* @param password 原密码
|
||||
* @param confirmPassword 确认密码
|
||||
* @param context 上下文
|
||||
* @return 校验结果
|
||||
*/
|
||||
fun validatePasswordConfirmation(
|
||||
password: String,
|
||||
confirmPassword: String,
|
||||
context: Context
|
||||
): ValidationResult {
|
||||
return when {
|
||||
confirmPassword.isEmpty() -> ValidationResult(
|
||||
false,
|
||||
context.getString(R.string.text_error_confirm_password_required)
|
||||
)
|
||||
|
||||
confirmPassword.length > MAX_PASSWORD_LENGTH -> ValidationResult(
|
||||
false,
|
||||
context.getString(R.string.text_error_password_too_long, MAX_PASSWORD_LENGTH)
|
||||
)
|
||||
|
||||
password != confirmPassword -> ValidationResult(
|
||||
false,
|
||||
context.getString(R.string.text_error_confirm_password_mismatch)
|
||||
)
|
||||
|
||||
else -> ValidationResult(true)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验当前密码(用于更改密码和删除账户场景)
|
||||
* @param currentPassword 当前密码
|
||||
* @param context 上下文
|
||||
* @return 校验结果
|
||||
*/
|
||||
fun validateCurrentPassword(currentPassword: String, context: Context): ValidationResult {
|
||||
return when {
|
||||
currentPassword.isEmpty() -> ValidationResult(
|
||||
false,
|
||||
"Please enter your current password"
|
||||
)
|
||||
|
||||
currentPassword.length > MAX_PASSWORD_LENGTH -> ValidationResult(
|
||||
false,
|
||||
context.getString(R.string.text_error_password_too_long, MAX_PASSWORD_LENGTH)
|
||||
)
|
||||
|
||||
else -> ValidationResult(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -185,5 +185,6 @@
|
||||
<string name="group_room_enter_fail">加入房间失败</string>
|
||||
<string name="agent_createing">创建中...</string>
|
||||
<string name="agent_find">发现</string>
|
||||
<string name="text_error_password_too_long">Password cannot exceed %1$d characters</string>
|
||||
|
||||
</resources>
|
||||
Reference in New Issue
Block a user