mirror of
https://github.com/rustmailer/bichon.git
synced 2026-08-03 07:48:34 +02:00
feat: increase password max to 256, fix i18n, and force re-login #83
- Raise password maximum length from 32 to 256 characters - fix profileSchema to accept `t` for proper internationalization - Invalidate user's WebUI token on password change, requiring re-login
This commit is contained in:
@@ -16,7 +16,6 @@
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
use crate::modules::account::migration::{AccountModel, AccountType};
|
||||
use crate::modules::cache::imap::mailbox::{Attribute, AttributeEnum, MailBox};
|
||||
use crate::modules::context::executors::MAIL_CONTEXT;
|
||||
@@ -64,8 +63,15 @@ pub async fn convert_names_to_mailboxes(
|
||||
for name in names.into_iter() {
|
||||
// Convert the name into a MailBox structure
|
||||
let mailbox_name = name.name().to_string();
|
||||
|
||||
let mut mailbox: MailBox = name.into();
|
||||
|
||||
tracing::debug!(
|
||||
raw = &mailbox_name,
|
||||
decoded = &mailbox.name,
|
||||
"mailbox name comparison"
|
||||
);
|
||||
|
||||
if contains_no_select(&mailbox.attributes) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -444,6 +444,7 @@ impl BichonUser {
|
||||
|
||||
pub async fn update(id: u64, request: UserUpdateRequest) -> BichonResult<()> {
|
||||
let _ = &request.validate().await?;
|
||||
let password_changed = request.password.is_some();
|
||||
|
||||
if DEFAULT_ADMIN_USER_ID == id && request.global_roles.is_some() {
|
||||
return Err(raise_error!(
|
||||
@@ -537,6 +538,11 @@ impl BichonUser {
|
||||
},
|
||||
)
|
||||
.await?;
|
||||
|
||||
if password_changed {
|
||||
AccessTokenModel::reset_webui_token(id).await?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
@@ -204,9 +204,9 @@ impl UserCreateRequest {
|
||||
ErrorCode::InvalidParameter
|
||||
));
|
||||
}
|
||||
if password_len > 32 {
|
||||
if password_len > 256 {
|
||||
return Err(raise_error!(
|
||||
"Password cannot exceed 32 characters.".into(),
|
||||
"Password cannot exceed 256 characters.".into(),
|
||||
ErrorCode::InvalidParameter
|
||||
));
|
||||
}
|
||||
@@ -317,9 +317,9 @@ impl UserUpdateRequest {
|
||||
|
||||
if let Some(password) = &self.password {
|
||||
let len = password.len();
|
||||
if len < 8 || len > 32 {
|
||||
if len < 8 || len > 256 {
|
||||
return Err(raise_error!(
|
||||
"Password must be 8-32 characters.".into(),
|
||||
"Password must be 8-256 characters.".into(),
|
||||
ErrorCode::InvalidParameter
|
||||
));
|
||||
}
|
||||
|
||||
@@ -47,40 +47,40 @@ import AvatarUpload from './avatar-upload'
|
||||
import useMinimalAccountList from '@/hooks/use-minimal-account-list'
|
||||
import { PermissionsDialog } from './permissions-dialog'
|
||||
|
||||
const profileSchema = z.object({
|
||||
const profileSchema = (t: (key: string) => string) => z.object({
|
||||
username: z
|
||||
.string({
|
||||
required_error: 'settings.profile.validation.username.required',
|
||||
required_error: t('settings.profile.validation.username.required'),
|
||||
})
|
||||
.min(5, {
|
||||
message: 'settings.profile.validation.username.min',
|
||||
message: t('settings.profile.validation.username.min'),
|
||||
})
|
||||
.max(32, {
|
||||
message: 'settings.profile.validation.username.max',
|
||||
message: t('settings.profile.validation.username.max'),
|
||||
}),
|
||||
|
||||
email: z
|
||||
.string({
|
||||
required_error: 'settings.profile.validation.email.required',
|
||||
required_error: t('settings.profile.validation.email.required'),
|
||||
})
|
||||
.email({
|
||||
message: 'settings.profile.validation.email.invalid',
|
||||
message: t('settings.profile.validation.email.invalid'),
|
||||
}),
|
||||
|
||||
password: z
|
||||
.string()
|
||||
.min(8, {
|
||||
message: 'settings.profile.validation.password.min',
|
||||
message: t('settings.profile.validation.password.min'),
|
||||
})
|
||||
.max(32, {
|
||||
message: 'settings.profile.validation.password.max',
|
||||
.max(256, {
|
||||
message: t('settings.profile.validation.password.max'),
|
||||
})
|
||||
.or(z.literal(''))
|
||||
.optional()
|
||||
.transform((v) => (v ? v : undefined)),
|
||||
})
|
||||
|
||||
export type ProfileFormValues = z.infer<typeof profileSchema>
|
||||
export type ProfileFormValues = z.infer<ReturnType<typeof profileSchema>>
|
||||
|
||||
function fileToBase64(file: File): Promise<string> {
|
||||
return new Promise((resolve, reject) => {
|
||||
@@ -110,7 +110,7 @@ export function UserProfileForm({ user }: UserProfileFormProps) {
|
||||
useState<number | undefined>(undefined)
|
||||
|
||||
const form = useForm<ProfileFormValues>({
|
||||
resolver: zodResolver(profileSchema),
|
||||
resolver: zodResolver(profileSchema(t)),
|
||||
mode: 'onChange',
|
||||
defaultValues: {
|
||||
username: user.username,
|
||||
|
||||
@@ -111,14 +111,14 @@ const createUserSchema = (t: any) => z.object({
|
||||
password: z.string()
|
||||
.min(1, t('users.actions.schema.password_required'))
|
||||
.min(8, t('users.actions.schema.password_min'))
|
||||
.max(32, t('users.actions.schema.password_max')),
|
||||
.max(256, t('users.actions.schema.password_max')),
|
||||
});
|
||||
|
||||
const updateUserSchema = (t: any) => z.object({
|
||||
...baseUserSchema(t),
|
||||
password: z.string()
|
||||
.min(8, t('users.actions.schema.password_min'))
|
||||
.max(32, t('users.actions.schema.password_max'))
|
||||
.max(256, t('users.actions.schema.password_max'))
|
||||
.or(z.literal(''))
|
||||
.optional()
|
||||
.transform(v => v || undefined),
|
||||
|
||||
@@ -829,7 +829,7 @@
|
||||
},
|
||||
"password": {
|
||||
"min": "يجب أن تكون كلمة المرور 8 أحرف على الأقل",
|
||||
"max": "يجب ألا تزيد كلمة المرور عن 32 حرفًا"
|
||||
"max": "يجب ألا تزيد كلمة المرور عن 256 حرفًا"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1238,7 +1238,7 @@
|
||||
"ip_invalid": "تم اكتشاف عنوان IP غير صالح",
|
||||
"password_required": "كلمة المرور مطلوبة",
|
||||
"password_min": "8 أحرف على الأقل",
|
||||
"password_max": "32 حرفاً كحد أقصى"
|
||||
"password_max": "256 حرفاً كحد أقصى"
|
||||
},
|
||||
"toast": {
|
||||
"updated": "تم تحديث المستخدم",
|
||||
|
||||
@@ -829,7 +829,7 @@
|
||||
},
|
||||
"password": {
|
||||
"min": "Adgangskoden skal være mindst 8 tegn",
|
||||
"max": "Adgangskoden må højst være 32 tegn"
|
||||
"max": "Adgangskoden må højst være 256 tegn"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1238,7 +1238,7 @@
|
||||
"ip_invalid": "Ugyldig IP-adresse",
|
||||
"password_required": "Adgangskode er påkrævet",
|
||||
"password_min": "Mindst 8 tegn",
|
||||
"password_max": "Højst 32 tegn"
|
||||
"password_max": "Højst 256 tegn"
|
||||
},
|
||||
"toast": {
|
||||
"updated": "Bruger opdateret",
|
||||
|
||||
@@ -829,7 +829,7 @@
|
||||
},
|
||||
"password": {
|
||||
"min": "Das Passwort muss mindestens 8 Zeichen lang sein",
|
||||
"max": "Das Passwort darf höchstens 32 Zeichen lang sein"
|
||||
"max": "Das Passwort darf höchstens 256 Zeichen lang sein"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1238,7 +1238,7 @@
|
||||
"ip_invalid": "Ungültige IP-Adresse erkannt",
|
||||
"password_required": "Passwort ist erforderlich",
|
||||
"password_min": "Passwort muss mindestens 8 Zeichen lang sein",
|
||||
"password_max": "Passwort darf maximal 32 Zeichen lang sein"
|
||||
"password_max": "Passwort darf maximal 256 Zeichen lang sein"
|
||||
},
|
||||
"toast": {
|
||||
"updated": "Benutzer aktualisiert",
|
||||
|
||||
@@ -829,7 +829,7 @@
|
||||
},
|
||||
"password": {
|
||||
"min": "Password must be at least 8 characters",
|
||||
"max": "Password must be at most 32 characters"
|
||||
"max": "Password must be at most 256 characters"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1238,7 +1238,7 @@
|
||||
"ip_invalid": "Invalid IP address detected",
|
||||
"password_required": "Password is required",
|
||||
"password_min": "Password must be at least 8 characters",
|
||||
"password_max": "Password cannot exceed 32 characters"
|
||||
"password_max": "Password cannot exceed 256 characters"
|
||||
},
|
||||
"toast": {
|
||||
"updated": "User updated",
|
||||
|
||||
@@ -829,7 +829,7 @@
|
||||
},
|
||||
"password": {
|
||||
"min": "La contraseña debe tener al menos 8 caracteres",
|
||||
"max": "La contraseña debe tener como máximo 32 caracteres"
|
||||
"max": "La contraseña debe tener como máximo 256 caracteres"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1238,7 +1238,7 @@
|
||||
"ip_invalid": "Dirección IP inválida",
|
||||
"password_required": "La contraseña es obligatoria",
|
||||
"password_min": "Mínimo 8 caracteres",
|
||||
"password_max": "Máximo 32 caracteres"
|
||||
"password_max": "Máximo 256 caracteres"
|
||||
},
|
||||
"toast": {
|
||||
"updated": "Usuario actualizado",
|
||||
|
||||
@@ -829,7 +829,7 @@
|
||||
},
|
||||
"password": {
|
||||
"min": "Salasanan on oltava vähintään 8 merkkiä",
|
||||
"max": "Salasana voi olla enintään 32 merkkiä"
|
||||
"max": "Salasana voi olla enintään 256 merkkiä"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1238,7 +1238,7 @@
|
||||
"ip_invalid": "Virheellinen IP-osoite",
|
||||
"password_required": "Salasana on pakollinen",
|
||||
"password_min": "Vähintään 8 merkkiä",
|
||||
"password_max": "Enintään 32 merkkiä"
|
||||
"password_max": "Enintään 256 merkkiä"
|
||||
},
|
||||
"toast": {
|
||||
"updated": "Käyttäjä päivitetty",
|
||||
|
||||
@@ -829,7 +829,7 @@
|
||||
},
|
||||
"password": {
|
||||
"min": "Le mot de passe doit contenir au moins 8 caractères",
|
||||
"max": "Le mot de passe doit contenir au maximum 32 caractères"
|
||||
"max": "Le mot de passe doit contenir au maximum 256 caractères"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1238,7 +1238,7 @@
|
||||
"ip_invalid": "Adresse IP invalide détectée",
|
||||
"password_required": "Le mot de passe est requis",
|
||||
"password_min": "Le mot de passe doit contenir au moins 8 caractères",
|
||||
"password_max": "Le mot de passe ne peut pas dépasser 32 caractères"
|
||||
"password_max": "Le mot de passe ne peut pas dépasser 256 caractères"
|
||||
},
|
||||
"toast": {
|
||||
"updated": "Utilisateur mis à jour",
|
||||
|
||||
@@ -829,7 +829,7 @@
|
||||
},
|
||||
"password": {
|
||||
"min": "La password deve contenere almeno 8 caratteri",
|
||||
"max": "La password deve contenere al massimo 32 caratteri"
|
||||
"max": "La password deve contenere al massimo 256 caratteri"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1238,7 +1238,7 @@
|
||||
"ip_invalid": "Indirizzo IP non valido",
|
||||
"password_required": "La password è obbligatoria",
|
||||
"password_min": "Minimo 8 caratteri",
|
||||
"password_max": "Massimo 32 caratteri"
|
||||
"password_max": "Massimo 256 caratteri"
|
||||
},
|
||||
"toast": {
|
||||
"updated": "Utente aggiornato",
|
||||
|
||||
@@ -829,7 +829,7 @@
|
||||
},
|
||||
"password": {
|
||||
"min": "パスワードは8文字以上である必要があります",
|
||||
"max": "パスワードは32文字以内である必要があります"
|
||||
"max": "パスワードは256文字以内である必要があります"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1238,7 +1238,7 @@
|
||||
"ip_invalid": "無効な IP アドレスが検出されました",
|
||||
"password_required": "パスワードは必須です",
|
||||
"password_min": "パスワードは 8 文字以上である必要があります",
|
||||
"password_max": "パスワードは 32 文字以内である必要があります"
|
||||
"password_max": "パスワードは 256 文字以内である必要があります"
|
||||
},
|
||||
"toast": {
|
||||
"updated": "ユーザーを更新しました",
|
||||
|
||||
@@ -829,7 +829,7 @@
|
||||
},
|
||||
"password": {
|
||||
"min": "비밀번호는 최소 8자 이상이어야 합니다",
|
||||
"max": "비밀번호는 최대 32자까지 가능합니다"
|
||||
"max": "비밀번호는 최대 256자까지 가능합니다"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1238,7 +1238,7 @@
|
||||
"ip_invalid": "유효하지 않은 IP 주소가 감지되었습니다",
|
||||
"password_required": "비밀번호는 필수입니다",
|
||||
"password_min": "비밀번호는 8자 이상이어야 합니다",
|
||||
"password_max": "비밀번호는 32자를 초과할 수 없습니다"
|
||||
"password_max": "비밀번호는 256자를 초과할 수 없습니다"
|
||||
},
|
||||
"toast": {
|
||||
"updated": "사용자 업데이트됨",
|
||||
|
||||
@@ -829,7 +829,7 @@
|
||||
},
|
||||
"password": {
|
||||
"min": "Wachtwoord moet minimaal 8 tekens bevatten",
|
||||
"max": "Wachtwoord mag maximaal 32 tekens bevatten"
|
||||
"max": "Wachtwoord mag maximaal 256 tekens bevatten"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1238,7 +1238,7 @@
|
||||
"ip_invalid": "Ongeldig IP-adres gedetecteerd",
|
||||
"password_required": "Wachtwoord is verplicht",
|
||||
"password_min": "Minimaal 8 tekens",
|
||||
"password_max": "Maximaal 32 tekens"
|
||||
"password_max": "Maximaal 256 tekens"
|
||||
},
|
||||
"toast": {
|
||||
"updated": "Gebruiker bijgewerkt",
|
||||
|
||||
@@ -829,7 +829,7 @@
|
||||
},
|
||||
"password": {
|
||||
"min": "Passordet må være minst 8 tegn",
|
||||
"max": "Passordet kan være maks 32 tegn"
|
||||
"max": "Passordet kan være maks 256 tegn"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1238,7 +1238,7 @@
|
||||
"ip_invalid": "Ugyldig IP-adresse",
|
||||
"password_required": "Passord er påkrevd",
|
||||
"password_min": "Minst 8 tegn",
|
||||
"password_max": "Maks 32 tegn"
|
||||
"password_max": "Maks 256 tegn"
|
||||
},
|
||||
"toast": {
|
||||
"updated": "Bruker oppdatert",
|
||||
|
||||
@@ -829,7 +829,7 @@
|
||||
},
|
||||
"password": {
|
||||
"min": "Hasło musi mieć co najmniej 8 znaków",
|
||||
"max": "Hasło może mieć maksymalnie 32 znaki"
|
||||
"max": "Hasło może mieć maksymalnie 256 znaki"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1238,7 +1238,7 @@
|
||||
"ip_invalid": "Wykryto niepoprawny adres IP",
|
||||
"password_required": "Hasło jest wymagane",
|
||||
"password_min": "Min. 8 znaków",
|
||||
"password_max": "Maks. 32 znaki"
|
||||
"password_max": "Maks. 256 znaki"
|
||||
},
|
||||
"toast": {
|
||||
"updated": "Użytkownik zaktualizowany",
|
||||
|
||||
@@ -829,7 +829,7 @@
|
||||
},
|
||||
"password": {
|
||||
"min": "A senha deve ter pelo menos 8 caracteres",
|
||||
"max": "A senha deve ter no máximo 32 caracteres"
|
||||
"max": "A senha deve ter no máximo 256 caracteres"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1238,7 +1238,7 @@
|
||||
"ip_invalid": "IP inválido detectado",
|
||||
"password_required": "Senha é obrigatória",
|
||||
"password_min": "Mínimo 8 caracteres",
|
||||
"password_max": "Máximo 32 caracteres"
|
||||
"password_max": "Máximo 256 caracteres"
|
||||
},
|
||||
"toast": {
|
||||
"updated": "Usuário atualizado",
|
||||
|
||||
@@ -829,7 +829,7 @@
|
||||
},
|
||||
"password": {
|
||||
"min": "Пароль должен содержать не менее 8 символов",
|
||||
"max": "Пароль должен содержать не более 32 символов"
|
||||
"max": "Пароль должен содержать не более 256 символов"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1238,7 +1238,7 @@
|
||||
"ip_invalid": "Неверный IP-адрес",
|
||||
"password_required": "Пароль обязателен",
|
||||
"password_min": "Минимум 8 символов",
|
||||
"password_max": "Максимум 32 символа"
|
||||
"password_max": "Максимум 256 символа"
|
||||
},
|
||||
"toast": {
|
||||
"updated": "Пользователь обновлен",
|
||||
|
||||
@@ -829,7 +829,7 @@
|
||||
},
|
||||
"password": {
|
||||
"min": "Lösenordet måste vara minst 8 tecken",
|
||||
"max": "Lösenordet får vara högst 32 tecken"
|
||||
"max": "Lösenordet får vara högst 256 tecken"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1238,7 +1238,7 @@
|
||||
"ip_invalid": "Ogiltig IP-adress upptäckt",
|
||||
"password_required": "Lösenord krävs",
|
||||
"password_min": "Lösenordet måste vara minst 8 tecken",
|
||||
"password_max": "Lösenordet får vara max 32 tecken"
|
||||
"password_max": "Lösenordet får vara max 256 tecken"
|
||||
},
|
||||
"toast": {
|
||||
"updated": "Användaren uppdaterad",
|
||||
|
||||
@@ -822,7 +822,7 @@
|
||||
},
|
||||
"password": {
|
||||
"min": "密碼至少需要 8 個字元",
|
||||
"max": "密碼最多 32 個字元"
|
||||
"max": "密碼最多 256 個字元"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1231,7 +1231,7 @@
|
||||
"ip_invalid": "發現無效的 IP 地址",
|
||||
"password_required": "密碼不能為空",
|
||||
"password_min": "密碼長度至少為 8 個字元",
|
||||
"password_max": "密碼長度不能超過 32 個字元"
|
||||
"password_max": "密碼長度不能超過 256 個字元"
|
||||
},
|
||||
"toast": {
|
||||
"updated": "使用者已更新",
|
||||
|
||||
@@ -829,7 +829,7 @@
|
||||
},
|
||||
"password": {
|
||||
"min": "密码长度至少为 8 个字符",
|
||||
"max": "密码长度不能超过 32 个字符"
|
||||
"max": "密码长度不能超过 256 个字符"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1238,7 +1238,7 @@
|
||||
"ip_invalid": "发现无效的 IP 地址",
|
||||
"password_required": "密码不能为空",
|
||||
"password_min": "密码长度至少为 8 个字符",
|
||||
"password_max": "密码长度不能超过 32 个字符"
|
||||
"password_max": "密码长度不能超过 256 个字符"
|
||||
},
|
||||
"toast": {
|
||||
"updated": "用户已更新",
|
||||
|
||||
Reference in New Issue
Block a user