HoshiAI-be/app/Http/Controllers/UserController.php

260 lines
8.8 KiB
PHP

<?php
namespace App\Http\Controllers;
use App\Http\Resources\UserResource;
use App\Models\Log;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
class UserController extends Controller
{
private const FIELD_RULES = [
'username' => 'required|max:100|unique:users',
'email' => 'required|max:100|unique:users',
'password' => 'required|min:6|confirmed',
'type' => 'required|in:admin,user,creator,banned',
'email_verified_at' => 'nullable|date'
];
private const PAGINATED_COUNT = 20;
/**
* @OA\Get(
* path="/api/users",
* summary="Get list of users (paginated, only admin)",
* tags={"Users"},
* security={{"bearerAuth": {}}},
* @OA\Response(
* response=200,
* description="List of users retrieved successfully",
* @OA\JsonContent(
* @OA\Property(property="data", type="array",
* @OA\Items(ref="#/components/schemas/UserResource")
* ),
* @OA\Property(property="links", type="object"),
* @OA\Property(property="meta", type="object")
* )
* ),
* @OA\Response(
* response=403,
* description="Forbidden — user is not authorized to view users"
* ),
* @OA\Response(
* response=401,
* description="Unauthenticated"
* )
* )
*/
public function index()
{
$this->authorize('viewAny', User::class);
return UserResource::collection(User::paginate(self::PAGINATED_COUNT));
}
/**
* @OA\Post(
* path="/api/users",
* summary="Create a new user (only admin)",
* tags={"Users"},
* security={{"bearerAuth": {}}},
* @OA\RequestBody(
* required=true,
* @OA\JsonContent(
* required={"username","email","password","type"},
* @OA\Property(property="username", type="string", maxLength=100, example="newuser"),
* @OA\Property(property="email", type="string", format="email", maxLength=100, example="newuser@example.com"),
* @OA\Property(property="password", type="string", format="password", example="secret123"),
* @OA\Property(property="type", type="string", enum={"admin","user"}, example="user")
* )
* ),
* @OA\Response(
* response=201,
* description="User created successfully",
* @OA\JsonContent(ref="#/components/schemas/UserResource")
* ),
* @OA\Response(
* response=422,
* description="Validation error",
* @OA\JsonContent(
* @OA\Property(property="message", type="string", example="The given data was invalid."),
* @OA\Property(
* property="errors",
* type="object",
* example={
* "email": {"The email has already been taken."},
* "password": {"The password must be at least 6 characters."}
* }
* )
* )
* ),
* @OA\Response(
* response=403,
* description="Forbidden — only admins can create users"
* ),
* @OA\Response(
* response=401,
* description="Unauthenticated"
* )
* )
*/
public function store(Request $request)
{
$this->authorize('create', User::class);
$fields = $request->validate(self::FIELD_RULES);
$fields['password'] = Hash::make($fields['password']);
$user = User::create($fields);
Log::writeLog("User '" . $user->username . "' is created by " . $request->user()->username);
return new UserResource($user);
}
/**
* @OA\Get(
* path="/api/users/{id}",
* summary="Get a specific user (only admin)",
* tags={"Users"},
* security={{"bearerAuth": {}}},
* @OA\Parameter(
* name="id",
* in="path",
* required=true,
* description="User ID",
* @OA\Schema(type="integer", example=1)
* ),
* @OA\Response(
* response=200,
* description="User retrieved successfully",
* @OA\JsonContent(ref="#/components/schemas/UserResource")
* ),
* @OA\Response(
* response=404,
* description="User not found"
* ),
* @OA\Response(
* response=403,
* description="Forbidden — user not authorized to view this resource"
* ),
* @OA\Response(
* response=401,
* description="Unauthenticated"
* )
* )
*/
public function show(User $user)
{
$this->authorize('view', $user);
return new UserResource($user);
}
/**
* @OA\Put(
* path="/api/users/{id}",
* summary="Update an existing user (only admin)",
* tags={"Users"},
* security={{"bearerAuth": {}}},
* @OA\Parameter(
* name="id",
* in="path",
* required=true,
* description="User ID",
* @OA\Schema(type="integer", example=1)
* ),
* @OA\RequestBody(
* required=true,
* @OA\JsonContent(
* required={"username","email","password","type"},
* @OA\Property(property="username", type="string", maxLength=100, example="updated_user"),
* @OA\Property(property="email", type="string", format="email", maxLength=100, example="updated_user@example.com"),
* @OA\Property(property="password", type="string", format="password", example="newpassword123"),
* @OA\Property(property="type", type="string", enum={"admin","user"}, example="user")
* )
* ),
* @OA\Response(
* response=200,
* description="User updated successfully",
* @OA\JsonContent(ref="#/components/schemas/UserResource")
* ),
* @OA\Response(
* response=404,
* description="User not found"
* ),
* @OA\Response(
* response=422,
* description="Validation error",
* @OA\JsonContent(
* @OA\Property(property="message", type="string", example="The given data was invalid."),
* @OA\Property(
* property="errors",
* type="object",
* example={
* "email": {"The email has already been taken."},
* "password": {"The password must be at least 6 characters."}
* }
* )
* )
* ),
* @OA\Response(
* response=403,
* description="Forbidden — only admins can update users"
* ),
* @OA\Response(
* response=401,
* description="Unauthenticated"
* )
* )
*/
public function update(Request $request, User $user)
{
$this->authorize('update', $user);
$fields = $request->validate(self::FIELD_RULES);
if(!Hash::check($fields['password'], $user->password)) {
$fields['password'] = Hash::make($fields['password']);
}
$user->update($fields);
Log::writeLog("User '" . $user->username . "' is updated by " . $request->user()->username);
return new UserResource($user);
}
/**
* @OA\Delete(
* path="/api/users/{id}",
* summary="Delete a user (only admin)",
* tags={"Users"},
* security={{"bearerAuth": {}}},
* @OA\Parameter(
* name="id",
* in="path",
* required=true,
* description="User ID",
* @OA\Schema(type="integer", example=1)
* ),
* @OA\Response(
* response=204,
* description="User deleted successfully (no content)"
* ),
* @OA\Response(
* response=404,
* description="User not found"
* ),
* @OA\Response(
* response=403,
* description="Forbidden — only admins can delete users"
* ),
* @OA\Response(
* response=401,
* description="Unauthenticated"
* )
* )
*/
public function destroy(Request $request, User $user)
{
$this->authorize('delete', $user);
$user->delete();
Log::writeLog("User '" . $user->username . "' is deleted by " . $request->user()->username);
}
}