implement user search and admin promote endpoints

GET /users?q=... is public; POST /admin/users/promote is auth
required and admin-checked inside the use case.
This commit is contained in:
Yisroel Baum 2026-05-06 22:36:15 +03:00
parent 56136f8bcf
commit a3f90d1e85
Signed by: yisroelbaum
GPG key ID: 0FA60884F75520A9
2 changed files with 93 additions and 0 deletions

View file

@ -0,0 +1,88 @@
<?php
namespace App\Controllers;
use App\Exceptions\BadRequestException;
use App\Exceptions\ForbiddenException;
use App\User\UseCases\PromoteUserToAdmin\PromoteUserToAdmin;
use App\User\UseCases\PromoteUserToAdmin\PromoteUserToAdminRequest;
use App\User\UseCases\SearchUsers\SearchUsers;
use App\User\UseCases\SearchUsers\SearchUsersRequest;
use App\User\User;
use DomainException;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class UserController
{
public function __construct(
private SearchUsers $searchUsers,
private PromoteUserToAdmin $promoteUserToAdmin,
) {}
public function search(Request $request): JsonResponse
{
$query = $request->query('q');
if (! is_string($query) || trim($query) === '') {
return new JsonResponse(['users' => []], 200);
}
try {
$results = $this->searchUsers->execute(
new SearchUsersRequest(query: $query),
);
} catch (BadRequestException $exception) {
return new JsonResponse(
['error' => $exception->getMessage()], 400,
);
}
return new JsonResponse([
'users' => array_map(
function (User $user) {
return [
'id' => $user->getId(),
'email' => $user->getEmail()->value(),
'displayName' => $user->getDisplayName(),
'isAdmin' => $user->isAdmin(),
];
},
$results,
),
], 200);
}
public function promote(Request $request): JsonResponse
{
/** @var User $requester */
$requester = $request->attributes->get('user');
try {
$promoted = $this->promoteUserToAdmin->execute(
new PromoteUserToAdminRequest(
targetUserId: (int) $request->input('userId'),
requesterIsAdmin: $requester->isAdmin(),
),
);
} catch (BadRequestException $exception) {
return new JsonResponse(
['error' => $exception->getMessage()], 400,
);
} catch (ForbiddenException $exception) {
return new JsonResponse(
['error' => $exception->getMessage()], 403,
);
} catch (DomainException $exception) {
return new JsonResponse(
['error' => $exception->getMessage()], 404,
);
}
return new JsonResponse([
'user' => [
'id' => $promoted->getId(),
'email' => $promoted->getEmail()->value(),
'displayName' => $promoted->getDisplayName(),
'isAdmin' => $promoted->isAdmin(),
],
], 200);
}
}

View file

@ -3,6 +3,7 @@
use App\Controllers\AuthController;
use App\Controllers\CommentController;
use App\Controllers\PostController;
use App\Controllers\UserController;
use App\Http\Middleware\AuthMiddleware;
use Illuminate\Support\Facades\Route;
@ -32,6 +33,10 @@ Route::post('/admin/posts/feature', [PostController::class, 'feature'])
Route::post('/admin/posts/unfeature', [PostController::class, 'unfeature'])
->middleware(AuthMiddleware::class);
Route::get('/users', [UserController::class, 'search']);
Route::post('/admin/users/promote', [UserController::class, 'promote'])
->middleware(AuthMiddleware::class);
Route::get(
'/users/{displayName}/posts',
[PostController::class, 'listByUser'],