authService = $authService; } /** * @OA\Get( * path="/client/me", * operationId="getClientMe", * tags={"Client Authentication"}, * summary="Get current client information", * description="Returns the currently authenticated client's details", * security={{"bearerAuth":{}}}, * @OA\Response( * response=200, * description="Successful operation", * @OA\JsonContent( * @OA\Property(property="customer", type="object", * @OA\Property(property="fullname", type="string", example="Nguyen Van A"), * @OA\Property(property="email", type="string", example="client@example.com"), * @OA\Property(property="phone", type="string", example="0987654321"), * @OA\Property(property="address", type="string", example="123 Street"), * @OA\Property(property="city", type="string", example="Hanoi"), * @OA\Property(property="ward", type="string", example="Ward 1"), * @OA\Property(property="province", type="string", example="Hanoi"), * @OA\Property(property="gender", type="string", example="Nam"), * @OA\Property(property="date", type="string", format="date-time", example="2024-01-01 12:00:00"), * @OA\Property(property="company", type="string", example="Company Ltd"), * @OA\Property(property="avatar", type="string", example="/uploads/avatar.jpg"), * @OA\Property(property="cmnd_after", type="string", example="cmnd_back.jpg"), * @OA\Property(property="cmnd_before", type="string", example="cmnd_front.jpg"), * @OA\Property(property="cmnd", type="string", example="123456789"), * @OA\Property(property="fb_link", type="string", nullable=true), * @OA\Property(property="active_2fa", type="integer", example=0), * @OA\Property(property="off_mail_marketing", type="integer", example=0), * @OA\Property(property="is_recharge_zalo", type="integer", example=0), * @OA\Property(property="is_verify_telegram", type="integer", example=0) * ), * @OA\Property(property="credit", type="object", * @OA\Property(property="credit", type="number", example=1000000), * @OA\Property(property="total", type="number", example=5000000), * @OA\Property(property="point", type="number", example=100), * @OA\Property(property="point_used", type="integer", example=0), * @OA\Property(property="point_total", type="number", example=100) * ), * @OA\Property(property="service", type="object", * @OA\Property(property="vps", type="integer", example=2), * @OA\Property(property="proxy", type="integer", example=0), * @OA\Property(property="server", type="integer", example=0), * @OA\Property(property="hosting", type="integer", example=1), * @OA\Property(property="domain", type="integer", example=3) * ) * ) * ), * @OA\Response( * response=401, * description="Unauthenticated" * ) * ) */ public function me() { return response()->json([ 'error' => false, 'data' => [ 'client' => new ClientResource(auth('client')->user()), ], ]); } /** * @OA\Post( * path="/client/login", * operationId="clientLogin", * tags={"Client Authentication"}, * summary="Client login", * description="Authenticate a client and return access token + refresh token", * @OA\RequestBody( * required=true, * @OA\JsonContent( * required={"email","password"}, * @OA\Property(property="email", type="string", format="email", example="client@example.com"), * @OA\Property(property="password", type="string", format="password", example="password123") * ) * ), * @OA\Response( * response=200, * description="Login successful", * @OA\JsonContent( * @OA\Property(property="error", type="boolean", example=false), * @OA\Property(property="data", type="object", * @OA\Property(property="client", type="object"), * @OA\Property(property="token", type="string", example="eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..."), * @OA\Property(property="refresh_token", type="string", example="random64charstring..."), * @OA\Property(property="expires_in", type="integer", example=900) * ) * ) * ), * @OA\Response( * response=422, * description="Validation error" * ) * ) */ public function login(ClientAuthRequest $request) { $result = $this->authService->authenticateClient($request->validated()); return response()->json([ 'error' => false, 'data' => [ 'client' => new ClientResource($result['client']), 'token' => $result['token'], 'refresh_token' => $result['refresh_token'], 'expires_in' => config('jwt.ttl', 60) * 60, // seconds ], ]); } /** * @OA\Post( * path="/client/register", * operationId="clientRegister", * tags={"Client Authentication"}, * summary="Client registration", * description="Register a new client account", * @OA\RequestBody( * required=true, * @OA\JsonContent( * required={"fullname","phone","email","password","password_confirmation"}, * @OA\Property(property="fullname", type="string", example="Nguyen Van A"), * @OA\Property(property="phone", type="string", example="0987654321"), * @OA\Property(property="email", type="string", format="email", example="client@example.com"), * @OA\Property(property="password", type="string", format="password", example="password123"), * @OA\Property(property="password_confirmation", type="string", format="password", example="password123") * ) * ), * @OA\Response( * response=200, * description="Registration successful", * @OA\JsonContent( * @OA\Property(property="error", type="boolean", example=false), * @OA\Property(property="data", type="object", * @OA\Property(property="client", type="object"), * @OA\Property(property="token", type="string", example="eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..."), * @OA\Property(property="refresh_token", type="string", example="random64charstring..."), * @OA\Property(property="expires_in", type="integer", example=900) * ) * ) * ), * @OA\Response( * response=422, * description="Validation error" * ) * ) */ public function register(ClientRegisterRequest $request) { $result = $this->authService->registerClient($request->validated()); return response()->json([ 'error' => false, 'data' => [ 'client' => new ClientResource($result['client']), 'token' => $result['token'], 'refresh_token' => $result['refresh_token'], 'expires_in' => config('jwt.ttl', 60) * 60, ], ]); } /** * @OA\Post( * path="/client/logout", * operationId="clientLogout", * tags={"Client Authentication"}, * summary="Client logout", * description="Logout the currently authenticated client and revoke refresh token", * security={{"bearerAuth":{}}}, * @OA\RequestBody( * @OA\JsonContent( * @OA\Property(property="refresh_token", type="string", example="random64charstring...") * ) * ), * @OA\Response( * response=200, * description="Logout successful", * @OA\JsonContent( * @OA\Property(property="error", type="boolean", example=false), * @OA\Property(property="message", type="string", example="Đã đăng xuất thành công.") * ) * ), * @OA\Response( * response=401, * description="Unauthenticated" * ) * ) */ public function logout(Request $request) { if ($rawToken = $request->input('refresh_token')) { $this->authService->revokeRefreshToken($rawToken); } auth('client')->logout(); return response()->json([ 'error' => false, 'message' => 'Đã đăng xuất thành công.', ]); } /** * @OA\Post( * path="/client/refresh", * operationId="clientRefresh", * tags={"Client Authentication"}, * summary="Refresh access token", * description="Exchange a valid refresh token for a new access token + rotated refresh token", * @OA\RequestBody( * required=true, * @OA\JsonContent( * required={"refresh_token"}, * @OA\Property(property="refresh_token", type="string", example="random64charstring...") * ) * ), * @OA\Response( * response=200, * description="Token refreshed", * @OA\JsonContent( * @OA\Property(property="error", type="boolean", example=false), * @OA\Property(property="data", type="object", * @OA\Property(property="token", type="string"), * @OA\Property(property="refresh_token", type="string"), * @OA\Property(property="expires_in", type="integer", example=900), * @OA\Property(property="client", type="object") * ) * ) * ), * @OA\Response( * response=401, * description="Invalid or expired refresh token" * ) * ) */ public function refresh(Request $request) { $request->validate([ 'refresh_token' => ['required', 'string'], ]); try { $result = $this->authService->rotateRefreshToken($request->input('refresh_token')); return response()->json([ 'error' => false, 'data' => [ 'token' => $result['token'], 'refresh_token' => $result['refresh_token'], 'expires_in' => config('jwt.ttl', 60) * 60, 'client' => new ClientResource($result['client']), ], ]); } catch (\Illuminate\Validation\ValidationException $e) { return response()->json([ 'error' => true, 'message' => collect($e->errors())->flatten()->first(), ], 401); } } public function update(ClientUpdateRequest $request) { $user = auth('client')->user(); $user->fill($request->validated()); $user->save(); return response()->json([ 'error' => false, 'message' => 'Cập nhật thông tin thành công', 'data' => [ 'client' => new ClientResource($user), ], ]); } }