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');