From 1f26750a2ae03ed4e10a4e0702fecc5a548dd889 Mon Sep 17 00:00:00 2001 From: Boy132 Date: Mon, 3 Nov 2025 08:31:07 +0100 Subject: [PATCH] Add api endpoint for updating username (#1826) --- .../Api/Client/AccountController.php | 20 ++++++++++ .../Client/Account/UpdateUsernameRequest.php | 38 +++++++++++++++++++ lang/en/activity.php | 1 + routes/api-client.php | 1 + 4 files changed, 60 insertions(+) create mode 100644 app/Http/Requests/Api/Client/Account/UpdateUsernameRequest.php diff --git a/app/Http/Controllers/Api/Client/AccountController.php b/app/Http/Controllers/Api/Client/AccountController.php index 644b80541..627c493ee 100644 --- a/app/Http/Controllers/Api/Client/AccountController.php +++ b/app/Http/Controllers/Api/Client/AccountController.php @@ -5,6 +5,7 @@ namespace App\Http\Controllers\Api\Client; use App\Facades\Activity; use App\Http\Requests\Api\Client\Account\UpdateEmailRequest; use App\Http\Requests\Api\Client\Account\UpdatePasswordRequest; +use App\Http\Requests\Api\Client\Account\UpdateUsernameRequest; use App\Services\Users\UserUpdateService; use App\Transformers\Api\Client\UserTransformer; use Illuminate\Auth\AuthManager; @@ -36,6 +37,25 @@ class AccountController extends ClientApiController ->toArray(); } + /** + * Update username + * + * Update the authenticated user's username. + */ + public function updateUsername(UpdateUsernameRequest $request): JsonResponse + { + $original = $request->user()->username; + $this->updateService->handle($request->user(), $request->validated()); + + if ($original !== $request->input('username')) { + Activity::event('user:account.username-changed') + ->property(['old' => $original, 'new' => $request->input('username')]) + ->log(); + } + + return new JsonResponse([], Response::HTTP_NO_CONTENT); + } + /** * Update email * diff --git a/app/Http/Requests/Api/Client/Account/UpdateUsernameRequest.php b/app/Http/Requests/Api/Client/Account/UpdateUsernameRequest.php new file mode 100644 index 000000000..430fa3c71 --- /dev/null +++ b/app/Http/Requests/Api/Client/Account/UpdateUsernameRequest.php @@ -0,0 +1,38 @@ +make(Hasher::class); + + // Verify password matches when changing password or email. + if (!$hasher->check($this->input('password'), $this->user()->password)) { + throw new InvalidPasswordProvidedException(trans('validation.internal.invalid_password')); + } + + return true; + } + + public function rules(): array + { + $rules = User::getRulesForUpdate($this->user()); + + return ['username' => $rules['username']]; + } +} diff --git a/lang/en/activity.php b/lang/en/activity.php index 4b3cdb339..464854f00 100644 --- a/lang/en/activity.php +++ b/lang/en/activity.php @@ -21,6 +21,7 @@ return [ ], 'user' => [ 'account' => [ + 'username-changed' => 'Changed username from :old to :new', 'email-changed' => 'Changed email from :old to :new', 'password-changed' => 'Changed password', ], diff --git a/routes/api-client.php b/routes/api-client.php index c3510ec66..9b15a29e6 100644 --- a/routes/api-client.php +++ b/routes/api-client.php @@ -21,6 +21,7 @@ Route::get('/permissions', [Client\ClientController::class, 'permissions']); Route::prefix('/account')->middleware(AccountSubject::class)->group(function () { Route::get('/', [Client\AccountController::class, 'index'])->name('api:client.account'); + Route::put('/username', [Client\AccountController::class, 'updateUsername'])->name('api:client.account.update-username'); Route::put('/email', [Client\AccountController::class, 'updateEmail'])->name('api:client.account.update-email'); Route::put('/password', [Client\AccountController::class, 'updatePassword'])->name('api:client.account.update-password');