From eff19412f3a3cecdb816b39713f1a35e80d94de0 Mon Sep 17 00:00:00 2001 From: ildyria Date: Sun, 1 Jun 2025 22:03:57 +0200 Subject: [PATCH 1/4] Squash --- app/Actions/Oauth/Oauth.php | 4 +- app/Contracts/Http/Requests/HasEmail.php | 17 +++ app/Http/Controllers/ProfileController.php | 25 ++++ .../Requests/Profile/RegistrationRequest.php | 58 ++++++++ app/Http/Requests/Traits/HasEmailTrait.php | 25 ++++ .../Resources/GalleryConfigs/InitConfig.php | 6 + ...05_29_231404_user_registration_enabled.php | 31 +++++ ...1905_rename_oauth_user_create_settings.php | 30 ++++ lang/ar/profile.php | 7 + lang/cz/profile.php | 7 + lang/de/profile.php | 7 + lang/el/profile.php | 8 ++ lang/en/profile.php | 7 + lang/es/profile.php | 8 ++ lang/fr/profile.php | 7 + lang/hu/profile.php | 8 ++ lang/it/profile.php | 8 ++ lang/ja/profile.php | 8 ++ lang/nl/profile.php | 7 + lang/no/profile.php | 8 ++ lang/pl/profile.php | 7 + lang/pt/profile.php | 8 ++ lang/ru/profile.php | 7 + lang/sk/profile.php | 8 ++ lang/sv/profile.php | 8 ++ lang/vi/profile.php | 8 ++ lang/zh_CN/profile.php | 7 + lang/zh_TW/profile.php | 8 ++ .../js/components/headers/AlbumsHeader.vue | 47 ++++++- resources/js/lychee.d.ts | 1 + resources/js/router/routes.ts | 6 + resources/js/services/profile-service.ts | 10 +- resources/js/stores/LycheeState.ts | 5 + resources/js/views/LoginPage.vue | 7 +- resources/js/views/RegisterPage.vue | 128 ++++++++++++++++++ routes/api_v2.php | 1 + routes/web_v2.php | 1 + tests/Feature_v2/User/RegisterTest.php | 87 ++++++++++++ 38 files changed, 629 insertions(+), 11 deletions(-) create mode 100644 app/Contracts/Http/Requests/HasEmail.php create mode 100644 app/Http/Requests/Profile/RegistrationRequest.php create mode 100644 app/Http/Requests/Traits/HasEmailTrait.php create mode 100644 database/migrations/2025_05_29_231404_user_registration_enabled.php create mode 100644 database/migrations/2025_05_29_231905_rename_oauth_user_create_settings.php create mode 100644 resources/js/views/RegisterPage.vue create mode 100644 tests/Feature_v2/User/RegisterTest.php diff --git a/app/Actions/Oauth/Oauth.php b/app/Actions/Oauth/Oauth.php index 354f57917ee..4d940055fcd 100644 --- a/app/Actions/Oauth/Oauth.php +++ b/app/Actions/Oauth/Oauth.php @@ -85,8 +85,8 @@ public function authenticateOrDie(OauthProvidersType $provider): bool username: $user->getName() ?? $user->getEmail() ?? $user->getId(), email: $user->getEmail(), password: strtr(base64_encode(random_bytes(8)), '+/', '-_'), - may_upload: Configs::getValueAsBool('oauth_grant_new_user_upload_rights'), - may_edit_own_settings: Configs::getValueAsBool('oauth_grant_new_user_modification_rights')); + may_upload: Configs::getValueAsBool('grant_new_user_upload_rights'), + may_edit_own_settings: Configs::getValueAsBool('grant_new_user_modification_rights')); Auth::login($new_user); diff --git a/app/Contracts/Http/Requests/HasEmail.php b/app/Contracts/Http/Requests/HasEmail.php new file mode 100644 index 00000000000..0cfa8350b52 --- /dev/null +++ b/app/Contracts/Http/Requests/HasEmail.php @@ -0,0 +1,17 @@ +do( + username: $request->username(), + password: $request->password(), + email: $request->email(), + may_upload: Configs::getValueAsBool('grant_new_user_upload_rights'), + may_edit_own_settings: Configs::getValueAsBool('grant_new_user_modification_rights'), + quota_kb: 0, + ); + + // Log in the user directly after registration + Auth::login($user); + + return response()->json(['message' => 'User registered successfully'], 201); + } + /** * Update the Login information of the current user. */ diff --git a/app/Http/Requests/Profile/RegistrationRequest.php b/app/Http/Requests/Profile/RegistrationRequest.php new file mode 100644 index 00000000000..3850cda40bd --- /dev/null +++ b/app/Http/Requests/Profile/RegistrationRequest.php @@ -0,0 +1,58 @@ + ['required', new UsernameRule()], + RequestAttribute::EMAIL_ATTRIBUTE => ['required', 'string', 'email', 'max:255', 'unique:users'], + RequestAttribute::PASSWORD_ATTRIBUTE => ['required', 'confirmed', new PasswordRule(true)], + ]; + } + + /** + * {@inheritDoc} + */ + protected function processValidatedValues(array $values, array $files): void + { + $this->username = $values[RequestAttribute::USERNAME_ATTRIBUTE]; + $this->password = $values[RequestAttribute::PASSWORD_ATTRIBUTE]; + $this->email = $values[RequestAttribute::EMAIL_ATTRIBUTE]; + } +} diff --git a/app/Http/Requests/Traits/HasEmailTrait.php b/app/Http/Requests/Traits/HasEmailTrait.php new file mode 100644 index 00000000000..d2dd427f612 --- /dev/null +++ b/app/Http/Requests/Traits/HasEmailTrait.php @@ -0,0 +1,25 @@ +email; + } +} diff --git a/app/Http/Resources/GalleryConfigs/InitConfig.php b/app/Http/Resources/GalleryConfigs/InitConfig.php index 9ad4581bdf1..1795c2bf35c 100644 --- a/app/Http/Resources/GalleryConfigs/InitConfig.php +++ b/app/Http/Resources/GalleryConfigs/InitConfig.php @@ -88,6 +88,9 @@ class InitConfig extends Data // Live Metrics settings public bool $is_live_metrics_enabled; + // User registration enabled + public bool $is_registration_enabled; + public function __construct() { // Debug mode @@ -140,6 +143,9 @@ public function __construct() $this->title = Configs::getValueAsString('site_title'); $this->dropbox_api_key = Auth::user()?->may_administrate === true ? Configs::getValueAsString('dropbox_key') : 'disabled'; + // User registration enabled + $this->is_registration_enabled = Configs::getValueAsBool('user_registration_enabled'); + $this->set_supporter_properties(); } diff --git a/database/migrations/2025_05_29_231404_user_registration_enabled.php b/database/migrations/2025_05_29_231404_user_registration_enabled.php new file mode 100644 index 00000000000..a08346d28b8 --- /dev/null +++ b/database/migrations/2025_05_29_231404_user_registration_enabled.php @@ -0,0 +1,31 @@ + 'user_registration_enabled', + 'value' => '0', + 'cat' => self::CAT, + 'type_range' => self::BOOL, + 'description' => 'Enable user registration.', + 'details' => 'If disabled, new users cannot register themselves.', + 'is_expert' => false, + 'is_secret' => true, + 'level' => 0, + 'order' => 1, + ], + ]; + } +}; diff --git a/database/migrations/2025_05_29_231905_rename_oauth_user_create_settings.php b/database/migrations/2025_05_29_231905_rename_oauth_user_create_settings.php new file mode 100644 index 00000000000..1fa5acd06d3 --- /dev/null +++ b/database/migrations/2025_05_29_231905_rename_oauth_user_create_settings.php @@ -0,0 +1,30 @@ +where('key', 'default_user_quota')->update(['order' => 2]); + DB::table('configs')->where('key', 'oauth_grant_new_user_modification_rights')->update(['key' => 'grant_new_user_modification_rights']); + DB::table('configs')->where('key', 'oauth_grant_new_user_upload_rights')->update(['key' => 'grant_new_user_upload_rights']); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + DB::table('configs')->where('key', 'grant_new_user_modification_rights')->update(['key' => 'oauth_grant_new_user_modification_rights']); + DB::table('configs')->where('key', 'grant_new_user_upload_rights')->update(['key' => 'oauth_grant_new_user_upload_rights']); + } +}; diff --git a/lang/ar/profile.php b/lang/ar/profile.php index ac516505d32..79597ff9d34 100644 --- a/lang/ar/profile.php +++ b/lang/ar/profile.php @@ -21,6 +21,13 @@ 'api_token' => 'رمز API …', 'missing_fields' => 'حقول مفقودة', ], + 'register' => [ + 'username_exists' => 'اسم المستخدم موجود بالفعل.', + 'password_mismatch' => 'كلمات المرور غير متطابقة.', + 'signup' => 'إنشاء حساب', + 'error' => 'حدث خطأ أثناء تسجيل حسابك.', + 'success' => 'تم إنشاء حسابك بنجاح.', + ], 'token' => [ 'unavailable' => 'لقد قمت بعرض هذا الرمز مسبقًا.', 'no_data' => 'لم يتم إنشاء أي رموز API.', diff --git a/lang/cz/profile.php b/lang/cz/profile.php index 7639588294e..41e9a86f6de 100644 --- a/lang/cz/profile.php +++ b/lang/cz/profile.php @@ -23,6 +23,13 @@ 'missing_fields' => 'Missing fields', ], + 'register' => [ + 'username_exists' => 'Username already exists.', + 'password_mismatch' => 'The passwords do not match.', + 'signup' => 'Sign Up', + 'error' => 'An error occurred while registering your account.', + 'success' => 'Your account has been successfully created.', + ], 'token' => [ 'unavailable' => 'You have already viewed this token.', diff --git a/lang/de/profile.php b/lang/de/profile.php index cd5d295ce4a..a88c98316fa 100644 --- a/lang/de/profile.php +++ b/lang/de/profile.php @@ -20,6 +20,13 @@ 'api_token' => 'API Token …', 'missing_fields' => 'Fehlende Felder', ], + 'register' => [ + 'username_exists' => 'Benutzername existiert bereits.', + 'password_mismatch' => 'Die Passwörter stimmen nicht überein.', + 'signup' => 'Registrieren', + 'error' => 'Bei der Registrierung Ihres Kontos ist ein Fehler aufgetreten.', + 'success' => 'Ihr Konto wurde erfolgreich erstellt.', + ], 'token' => [ 'unavailable' => 'Sie haben diesen Token bereits gesehen.', 'no_data' => 'Es wurde kein API-Token erzeugt.', diff --git a/lang/el/profile.php b/lang/el/profile.php index 7639588294e..e635110a590 100644 --- a/lang/el/profile.php +++ b/lang/el/profile.php @@ -24,6 +24,14 @@ 'missing_fields' => 'Missing fields', ], + 'register' => [ + 'username_exists' => 'Username already exists.', + 'password_mismatch' => 'The passwords do not match.', + 'signup' => 'Sign Up', + 'error' => 'An error occurred while registering your account.', + 'success' => 'Your account has been successfully created.', + ], + 'token' => [ 'unavailable' => 'You have already viewed this token.', 'no_data' => 'No token API have been generated.', diff --git a/lang/en/profile.php b/lang/en/profile.php index 157ab143374..e1c88769ba7 100644 --- a/lang/en/profile.php +++ b/lang/en/profile.php @@ -21,6 +21,13 @@ 'api_token' => 'API Token …', 'missing_fields' => 'Missing fields', ], + 'register' => [ + 'username_exists' => 'Username already exists.', + 'password_mismatch' => 'The passwords do not match.', + 'signup' => 'Sign Up', + 'error' => 'An error occurred while registering your account.', + 'success' => 'Your account has been successfully created.', + ], 'token' => [ 'unavailable' => 'You have already viewed this token.', 'no_data' => 'No token API have been generated.', diff --git a/lang/es/profile.php b/lang/es/profile.php index 7639588294e..e635110a590 100644 --- a/lang/es/profile.php +++ b/lang/es/profile.php @@ -24,6 +24,14 @@ 'missing_fields' => 'Missing fields', ], + 'register' => [ + 'username_exists' => 'Username already exists.', + 'password_mismatch' => 'The passwords do not match.', + 'signup' => 'Sign Up', + 'error' => 'An error occurred while registering your account.', + 'success' => 'Your account has been successfully created.', + ], + 'token' => [ 'unavailable' => 'You have already viewed this token.', 'no_data' => 'No token API have been generated.', diff --git a/lang/fr/profile.php b/lang/fr/profile.php index b23292f77d8..1c78dd3247e 100644 --- a/lang/fr/profile.php +++ b/lang/fr/profile.php @@ -21,6 +21,13 @@ 'api_token' => 'Jeton API …', 'missing_fields' => 'Champs manquants', ], + 'register' => [ + 'username_exists' => 'Le nom d’utilisateur existe déjà.', + 'password_mismatch' => 'Les mots de passe ne correspondent pas.', + 'signup' => 'S’inscrire', + 'error' => 'Une erreur est survenue lors de l’enregistrement de votre compte.', + 'success' => 'Votre compte a été créé avec succès.', + ], 'token' => [ 'unavailable' => 'Vous avez déjà visualisé ce jeton.', 'no_data' => 'Aucun jeton API n’a été généré.', diff --git a/lang/hu/profile.php b/lang/hu/profile.php index 7639588294e..60b0d1ac5a9 100644 --- a/lang/hu/profile.php +++ b/lang/hu/profile.php @@ -55,4 +55,12 @@ 'credential_registred' => 'Registration successful!', '5_chars' => 'At least 5 chars.', ], + + 'register' => [ + 'username_exists' => 'Username already exists.', + 'password_mismatch' => 'The passwords do not match.', + 'signup' => 'Sign Up', + 'error' => 'An error occurred while registering your account.', + 'success' => 'Your account has been successfully created.', + ], ]; \ No newline at end of file diff --git a/lang/it/profile.php b/lang/it/profile.php index 7639588294e..e635110a590 100644 --- a/lang/it/profile.php +++ b/lang/it/profile.php @@ -24,6 +24,14 @@ 'missing_fields' => 'Missing fields', ], + 'register' => [ + 'username_exists' => 'Username already exists.', + 'password_mismatch' => 'The passwords do not match.', + 'signup' => 'Sign Up', + 'error' => 'An error occurred while registering your account.', + 'success' => 'Your account has been successfully created.', + ], + 'token' => [ 'unavailable' => 'You have already viewed this token.', 'no_data' => 'No token API have been generated.', diff --git a/lang/ja/profile.php b/lang/ja/profile.php index 7639588294e..e635110a590 100644 --- a/lang/ja/profile.php +++ b/lang/ja/profile.php @@ -24,6 +24,14 @@ 'missing_fields' => 'Missing fields', ], + 'register' => [ + 'username_exists' => 'Username already exists.', + 'password_mismatch' => 'The passwords do not match.', + 'signup' => 'Sign Up', + 'error' => 'An error occurred while registering your account.', + 'success' => 'Your account has been successfully created.', + ], + 'token' => [ 'unavailable' => 'You have already viewed this token.', 'no_data' => 'No token API have been generated.', diff --git a/lang/nl/profile.php b/lang/nl/profile.php index f9f8070e9f0..01d3fea5702 100644 --- a/lang/nl/profile.php +++ b/lang/nl/profile.php @@ -20,6 +20,13 @@ 'api_token' => 'API-token …', 'missing_fields' => 'Ontbrekende velden', ], + 'register' => [ + 'username_exists' => 'Gebruikersnaam bestaat al.', + 'password_mismatch' => 'De wachtwoorden komen niet overeen.', + 'signup' => 'Aanmelden', + 'error' => 'Er is een fout opgetreden bij het registreren van uw account.', + 'success' => 'Uw account is succesvol aangemaakt.', + ], 'token' => [ 'unavailable' => 'U heeft dit token al bekeken.', 'no_data' => 'Er zijn geen API-tokens gegenereerd.', diff --git a/lang/no/profile.php b/lang/no/profile.php index 7639588294e..fa92adf3fa5 100644 --- a/lang/no/profile.php +++ b/lang/no/profile.php @@ -24,6 +24,14 @@ 'missing_fields' => 'Missing fields', ], + 'register' => [ + 'username_exists' => 'Username already exists.', + 'password_mismatch' => 'The passwords do not match.', + 'signup' => 'Sign Up', + 'error' => 'An error occurred while registering your account.', + 'success' => 'Your account has been successfully created.', + ], + 'token' => [ 'unavailable' => 'You have already viewed this token.', 'no_data' => 'No token API have been generated.', diff --git a/lang/pl/profile.php b/lang/pl/profile.php index 4ff1faa9327..beb83a6bb12 100644 --- a/lang/pl/profile.php +++ b/lang/pl/profile.php @@ -21,6 +21,13 @@ 'api_token' => 'Token API ...', 'missing_fields' => 'Brakujące pola', ], + 'register' => [ + 'username_exists' => 'Nazwa użytkownika już istnieje.', + 'password_mismatch' => 'Hasła nie pasują do siebie.', + 'signup' => 'Zarejestruj się', + 'error' => 'Wystąpił błąd podczas rejestrowania konta.', + 'success' => 'Twoje konto zostało pomyślnie utworzone.', + ], 'token' => [ 'unavailable' => 'Ten token został już wyświetlony.', 'no_data' => 'Nie wygenerowano tokenu API.', diff --git a/lang/pt/profile.php b/lang/pt/profile.php index 7639588294e..e635110a590 100644 --- a/lang/pt/profile.php +++ b/lang/pt/profile.php @@ -24,6 +24,14 @@ 'missing_fields' => 'Missing fields', ], + 'register' => [ + 'username_exists' => 'Username already exists.', + 'password_mismatch' => 'The passwords do not match.', + 'signup' => 'Sign Up', + 'error' => 'An error occurred while registering your account.', + 'success' => 'Your account has been successfully created.', + ], + 'token' => [ 'unavailable' => 'You have already viewed this token.', 'no_data' => 'No token API have been generated.', diff --git a/lang/ru/profile.php b/lang/ru/profile.php index 795f2d7a482..033b75001c9 100644 --- a/lang/ru/profile.php +++ b/lang/ru/profile.php @@ -21,6 +21,13 @@ 'api_token' => 'API Токен ...', 'missing_fields' => 'Отсутствуют поля', ], + 'register' => [ + 'username_exists' => 'Имя пользователя уже существует.', + 'password_mismatch' => 'Пароли не совпадают.', + 'signup' => 'Зарегистрироваться', + 'error' => 'Произошла ошибка при регистрации вашей учетной записи.', + 'success' => 'Ваша учетная запись была успешно создана.', + ], 'token' => [ 'unavailable' => 'Вы уже просмотрели этот токен.', 'no_data' => 'Токен API не был сгенерирован.', diff --git a/lang/sk/profile.php b/lang/sk/profile.php index 7639588294e..e635110a590 100644 --- a/lang/sk/profile.php +++ b/lang/sk/profile.php @@ -24,6 +24,14 @@ 'missing_fields' => 'Missing fields', ], + 'register' => [ + 'username_exists' => 'Username already exists.', + 'password_mismatch' => 'The passwords do not match.', + 'signup' => 'Sign Up', + 'error' => 'An error occurred while registering your account.', + 'success' => 'Your account has been successfully created.', + ], + 'token' => [ 'unavailable' => 'You have already viewed this token.', 'no_data' => 'No token API have been generated.', diff --git a/lang/sv/profile.php b/lang/sv/profile.php index 7639588294e..e635110a590 100644 --- a/lang/sv/profile.php +++ b/lang/sv/profile.php @@ -24,6 +24,14 @@ 'missing_fields' => 'Missing fields', ], + 'register' => [ + 'username_exists' => 'Username already exists.', + 'password_mismatch' => 'The passwords do not match.', + 'signup' => 'Sign Up', + 'error' => 'An error occurred while registering your account.', + 'success' => 'Your account has been successfully created.', + ], + 'token' => [ 'unavailable' => 'You have already viewed this token.', 'no_data' => 'No token API have been generated.', diff --git a/lang/vi/profile.php b/lang/vi/profile.php index 7639588294e..e635110a590 100644 --- a/lang/vi/profile.php +++ b/lang/vi/profile.php @@ -24,6 +24,14 @@ 'missing_fields' => 'Missing fields', ], + 'register' => [ + 'username_exists' => 'Username already exists.', + 'password_mismatch' => 'The passwords do not match.', + 'signup' => 'Sign Up', + 'error' => 'An error occurred while registering your account.', + 'success' => 'Your account has been successfully created.', + ], + 'token' => [ 'unavailable' => 'You have already viewed this token.', 'no_data' => 'No token API have been generated.', diff --git a/lang/zh_CN/profile.php b/lang/zh_CN/profile.php index a0418076b70..2fa114e80b3 100644 --- a/lang/zh_CN/profile.php +++ b/lang/zh_CN/profile.php @@ -21,6 +21,13 @@ 'api_token' => 'API 令牌...', 'missing_fields' => '缺少必填项', ], + 'register' => [ + 'username_exists' => '用户名已存在。', + 'password_mismatch' => '密码不匹配。', + 'signup' => '注册', + 'error' => '注册账户时发生错误。', + 'success' => '您的账户已成功创建。', + ], 'token' => [ 'unavailable' => '您已查看过此令牌。', 'no_data' => '尚未生成 API 令牌。', diff --git a/lang/zh_TW/profile.php b/lang/zh_TW/profile.php index 7639588294e..fa92adf3fa5 100644 --- a/lang/zh_TW/profile.php +++ b/lang/zh_TW/profile.php @@ -24,6 +24,14 @@ 'missing_fields' => 'Missing fields', ], + 'register' => [ + 'username_exists' => 'Username already exists.', + 'password_mismatch' => 'The passwords do not match.', + 'signup' => 'Sign Up', + 'error' => 'An error occurred while registering your account.', + 'success' => 'Your account has been successfully created.', + ], + 'token' => [ 'unavailable' => 'You have already viewed this token.', 'no_data' => 'No token API have been generated.', diff --git a/resources/js/components/headers/AlbumsHeader.vue b/resources/js/components/headers/AlbumsHeader.vue index 0246f41329f..0aa5db582b2 100644 --- a/resources/js/components/headers/AlbumsHeader.vue +++ b/resources/js/components/headers/AlbumsHeader.vue @@ -31,6 +31,35 @@