diff --git a/app/Http/Controllers/UsersController.php b/app/Http/Controllers/UsersController.php index 7118261..cd02d81 100644 --- a/app/Http/Controllers/UsersController.php +++ b/app/Http/Controllers/UsersController.php @@ -15,8 +15,6 @@ public function index() return User::all(); } - - /** * Show the form for creating a new resource. */ @@ -58,14 +56,14 @@ public function update(Request $request, string $id) $user = User::findOrFail($id); - if ($request->has('is_admin') && !auth()->user()->is_admin) { + if ($request->has('is_admin') && ! auth()->user()->is_admin) { return response()->json(['error' => 'Apenas administradores podem alterar o campo is_admin'], 403); } $data = $request->only(['name', 'email', 'cellphone', 'password', 'bearer_apibrasil']); // Se veio senha, criptografa - if (!empty($data['password'])) { + if (! empty($data['password'])) { $data['password'] = bcrypt($data['password']); } else { unset($data['password']); @@ -76,16 +74,48 @@ public function update(Request $request, string $id) return response()->json([ 'message' => 'Usuário atualizado com sucesso', - 'user' => $user->makeHidden(['password']) + 'user' => $user->makeHidden(['password']), ]); } catch (\Throwable $th) { return response()->json([ 'message' => 'Error ao atualizar úsuario', - 'error' => $th->getMessage() + 'error' => $th->getMessage(), ]); } } + public function makeAdmin(Request $request, string $id) + { + if (! auth()->user()->is_admin) { + return response()->json([ + 'message' => 'Apenas administradores podem realizar essa ação', + ], 403); + } + + $user = User::find($id); + + if (! $user) { + return response()->json([ + 'message' => 'Usuário não encontrado', + ], 404); + } + + if ($user->is_admin) { + return response()->json([ + 'message' => 'Usuário já é administrador', + ], 400); + } + + $user->is_admin = true; + $user->save(); + $user->refresh(); + + return response()->json([ + 'message' => 'Usuário promovido a administrador com sucesso', + 'user' => $user->makeHidden(['password']), + ]); + } + /** * Remove the specified resource from storage. */ diff --git a/routes/api.php b/routes/api.php index 7e42356..65bf294 100644 --- a/routes/api.php +++ b/routes/api.php @@ -1,12 +1,12 @@ group(function () { // informações do usuário logado - Route::get('/user', fn(Request $request) => $request->user()); + Route::get('/user', fn (Request $request) => $request->user()); Route::get('/profile', [AuthController::class, 'profile']); Route::post('/logout', [AuthController::class, 'logout']); // atualizar usuário Route::put('/users/{id}', [UsersController::class, 'update']); + Route::post('/users/{id}/make-admin', [UsersController::class, 'makeAdmin']); // transações e saldo Route::get('/transactions', [TransactionsController::class, 'index']); Route::post('/add-balance', [TransactionsController::class, 'addBalance']); Route::post('/users/{id}/add-balance', [TransactionsController::class, 'addBalanceToUser']); - // preços Route::apiResource('prices', PricesController::class); @@ -39,36 +39,31 @@ Route::any('/consult/{name}', 'default')->name('request_default'); Route::prefix('whatsapp')->group(function () { - Route::post('{action}', fn(Request $req, $action) => app(RequestsController::class)->default($req, "whatsapp/$action")); + Route::post('{action}', fn (Request $req, $action) => app(RequestsController::class)->default($req, "whatsapp/$action")); }); Route::post('/correios/{name}', 'default'); Route::prefix('geolocation')->group(function () { - Route::post('{action}', fn(Request $req, $action) => app(RequestsController::class)->default($req, "geolocation/$action")); + Route::post('{action}', fn (Request $req, $action) => app(RequestsController::class)->default($req, "geolocation/$action")); }); Route::prefix('weather')->group(function () { - Route::post('{action}', fn(Request $req, $action) => app(RequestsController::class)->default($req, "weather/$action")); + Route::post('{action}', fn (Request $req, $action) => app(RequestsController::class)->default($req, "weather/$action")); }); - Route::any('/cep/{action?}', fn(Request $req, $action = null) => - app(RequestsController::class)->default($req, $action ? "cep/" . trim($action, '/') : "cep") + Route::any('/cep/{action?}', fn (Request $req, $action = null) => app(RequestsController::class)->default($req, $action ? 'cep/'.trim($action, '/') : 'cep') )->where('action', '.*'); - Route::post('/geomatrix', fn(Request $req) => app(RequestsController::class)->default($req, 'geomatrix/distance')); + Route::post('/geomatrix', fn (Request $req) => app(RequestsController::class)->default($req, 'geomatrix/distance')); - Route::any('/translate/{action?}', fn(Request $req, $action = null) => - app(RequestsController::class)->default($req, $action ? "translate/" . trim($action, '/') : "translate") + Route::any('/translate/{action?}', fn (Request $req, $action = null) => app(RequestsController::class)->default($req, $action ? 'translate/'.trim($action, '/') : 'translate') )->where('action', '.*'); - Route::any('/ddd/{action?}', fn(Request $req, $action = null) => - app(RequestsController::class)->default($req, $action ? "ddd/" . trim($action, '/') : "ddd") + Route::any('/ddd/{action?}', fn (Request $req, $action = null) => app(RequestsController::class)->default($req, $action ? 'ddd/'.trim($action, '/') : 'ddd') )->where('action', '.*'); - Route::any('/database/{action?}', fn(Request $req, $action = null) => - app(RequestsController::class)->default($req, $action ? "database/" . trim($action, '/') : "database") + Route::any('/database/{action?}', fn (Request $req, $action = null) => app(RequestsController::class)->default($req, $action ? 'database/'.trim($action, '/') : 'database') )->where('action', '.*'); }); }); - diff --git a/tests/Feature/AdminPromoteUserTest.php b/tests/Feature/AdminPromoteUserTest.php new file mode 100644 index 0000000..39714b8 --- /dev/null +++ b/tests/Feature/AdminPromoteUserTest.php @@ -0,0 +1,81 @@ + 'Admin', + 'email' => 'admin@example.com', + 'password' => bcrypt('password'), + 'cellphone' => '123456789', + 'balance' => 0, + ]); + + $user = User::create([ + 'name' => 'User', + 'email' => 'user@example.com', + 'password' => bcrypt('password'), + 'cellphone' => '987654321', + 'balance' => 0, + ]); + + $response = $this->actingAs($admin, 'sanctum') + ->postJson('/api/users/'.$user->id.'/make-admin'); + + $response->assertStatus(200) + ->assertJson([ + 'message' => 'Usuário promovido a administrador com sucesso', + ]); + + $this->assertDatabaseHas('users', [ + 'id' => $user->id, + 'is_admin' => true, + ]); + } + + public function test_non_admin_cannot_promote_user_to_admin(): void + { + $admin = User::create([ + 'name' => 'Admin', + 'email' => 'admin2@example.com', + 'password' => bcrypt('password'), + 'cellphone' => '111111111', + 'balance' => 0, + ]); + + $nonAdmin = User::create([ + 'name' => 'NonAdmin', + 'email' => 'nonadmin@example.com', + 'password' => bcrypt('password'), + 'cellphone' => '222222222', + 'balance' => 0, + ]); + + $target = User::create([ + 'name' => 'Target', + 'email' => 'target@example.com', + 'password' => bcrypt('password'), + 'cellphone' => '333333333', + 'balance' => 0, + ]); + + $response = $this->actingAs($nonAdmin, 'sanctum') + ->postJson('/api/users/'.$target->id.'/make-admin'); + + $response->assertStatus(403); + + $this->assertDatabaseHas('users', [ + 'id' => $target->id, + 'is_admin' => false, + ]); + } +}