HoshiAI-be/app/Http/Controllers/AuthController.php
2025-11-13 12:05:08 +01:00

398 lines
14 KiB
PHP

<?php
namespace App\Http\Controllers;
use App\Http\Resources\UserResource;
use App\Mail\EmailActivation;
use App\Models\Log;
use App\Models\Token;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Mail;
class AuthController extends Controller
{
/**
* @OA\Post(
* path="/api/auth/register",
* summary="Register a new user",
* tags={"Auth"},
* @OA\RequestBody(
* required=true,
* @OA\JsonContent(
* required={"username","email","password","password_confirmation"},
* @OA\Property(property="username", type="string", maxLength=100, example="root"),
* @OA\Property(property="email", type="string", format="email", maxLength=100, example="root@example.com"),
* @OA\Property(property="password", type="string", format="password", example="123456"),
* @OA\Property(property="password_confirmation", type="string", format="password", example="123456")
* )
* ),
* @OA\Response(
* response=200,
* description="User registered successfully. Confirmation email sent.",
* @OA\JsonContent(
* @OA\Property(property="message", type="string", example="You successfully registered! Please, confirm your account using email")
* )
* ),
* @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."}}
* )
* )
* )
* )
*/
public function register(Request $request)
{
$fields = $request->validate([
'username' => 'required|max:100|unique:users',
'email' => 'required|max:100|unique:users',
'password' => 'required|min:6|confirmed'
]);
$fields['password'] = Hash::make($fields['password']);
$user = User::create($fields);
Log::writeLog("User '" . $user->username . "' is registered");
$token = Token::existsToken($user, 'email_verification');
if(!$token) {
$token = Token::createToken($user, 'email_verification');
}
Mail::to($user->email)->send(new EmailActivation($user, $token->token));
return response()->json([
'message' => 'You successfully registered! Please, confirm your account using email'
]);
}
/**
* @OA\Post(
* path="/api/auth/login",
* summary="User login",
* tags={"Auth"},
* @OA\RequestBody(
* required=true,
* @OA\JsonContent(
* required={"email","password"},
* @OA\Property(property="email", type="string", format="email", example="root@example.com"),
* @OA\Property(property="password", type="string", format="password", example="123456")
* )
* ),
* @OA\Response(
* response=200,
* description="Login successful",
* @OA\JsonContent(
* @OA\Property(property="access_token", type="string", example="1|JfjOc5DkOHHTtWnM4SdpLM0BR0YvpycoeNAWanlH1305fab7"),
* @OA\Property(property="token_type", type="string", example="Bearer"),
* @OA\Property(
* property="user",
* ref="#/components/schemas/UserResource"
* )
* )
* ),
* @OA\Response(
* response=401,
* description="Invalid credentials",
* @OA\JsonContent(
* @OA\Property(property="message", type="string", example="Invalid credentials")
* )
* ),
* @OA\Response(
* response=403,
* description="Email not verified",
* @OA\JsonContent(
* @OA\Property(property="message", type="string", example="Please verify your email first")
* )
* )
* )
*/
public function login(Request $request)
{
$fields = $request->validate([
'email' => 'required|email',
'password' => 'required',
]);
$user = User::where('email', $fields['email'])->first();
if (!$user || !Hash::check($fields['password'], $user->password)) {
return response()->json(['message' => 'Invalid credentials'], 401);
}
if (!$user->email_verified_at) {
return response()->json(['message' => 'Please verify your email first'], 403);
}
$token = $user->createToken('auth_token')->plainTextToken;
Log::writeLog("User '" . $user->username . "' is logged into his account");
return response()->json([
'access_token' => $token,
'token_type' => 'Bearer',
'user' => new UserResource($user),
]);
}
/**
* @OA\Post(
* path="/api/auth/logout",
* summary="Logout current user",
* tags={"Auth"},
* security={{"bearerAuth": {}}},
* @OA\Response(
* response=200,
* description="Successfully logged out",
* @OA\JsonContent(
* @OA\Property(property="message", type="string", example="Successfully logged out")
* )
* ),
* @OA\Response(
* response=401,
* description="Unauthenticated",
* @OA\JsonContent(
* @OA\Property(property="message", type="string", example="Unauthenticated")
* )
* )
* )
*/
public function logout(Request $request)
{
$request->user()->currentAccessToken()->delete();
return response()->json([
'message' => 'Successfully logged out'
]);
}
/**
* @OA\Post(
* path="/api/auth/forgot-password",
* summary="Send password reset link to user email",
* tags={"Auth"},
* @OA\RequestBody(
* required=true,
* @OA\JsonContent(
* required={"email"},
* @OA\Property(property="email", type="string", format="email", example="user@example.com")
* )
* ),
* @OA\Response(
* response=200,
* description="Password reset link sent successfully",
* @OA\JsonContent(
* @OA\Property(
* property="message",
* type="string",
* example="Password reset link has been sent to your email. Please check your inbox."
* )
* )
* ),
* @OA\Response(
* response=404,
* description="User not found",
* @OA\JsonContent(
* @OA\Property(
* property="message",
* type="string",
* example="User is 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 must be a valid email address."}}
* )
* )
* )
* )
*/
public function forgotPassword(Request $request)
{
$fields = $request->validate([
'email' => 'required|email',
]);
$user = User::where('email', $fields['email'])->first();
if (!$user) {
return response()->json(['message' => 'User is not found'], 404);
}
$token = Token::existsToken($user, 'password_reset');
if(!$token) {
$token = Token::createToken($user, 'password_reset');
}
Mail::to($user->email)->send(new EmailActivation($user, $token->token));
return response()->json([
'message' => 'Password reset link has been sent to your email. Please check your inbox.'
]);
}
/**
* @OA\Post(
* path="/api/auth/reset-password",
* summary="Reset user password using token",
* tags={"Auth"},
* @OA\RequestBody(
* required=true,
* @OA\JsonContent(
* required={"token","password","password_confirmation"},
* @OA\Property(property="token", type="string", example="abcdef123456"),
* @OA\Property(property="password", type="string", format="password", example="newpassword123"),
* @OA\Property(property="password_confirmation", type="string", format="password", example="newpassword123")
* )
* ),
* @OA\Response(
* response=200,
* description="Password reset successfully",
* @OA\JsonContent(
* @OA\Property(property="message", type="string", example="Your password was successfully changed!")
* )
* ),
* @OA\Response(
* response=401,
* description="Invalid token",
* @OA\JsonContent(
* @OA\Property(property="message", type="string", example="Your token is not valid")
* )
* ),
* @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={
* "password": {"The password must be at least 6 characters."},
* "password_confirmation": {"The password confirmation does not match."}
* }
* )
* )
* )
* )
*/
public function resetPassword(Request $request)
{
$fields = $request->validate([
'token' => 'required',
'password' => 'required|min:6|confirmed'
]);
$token = Token::existsTokenByToken($fields['token'], 'password_reset');
if(!$token) {
return response()->json(['message' => 'Your token is not valid'], 401);
}
$token->delete();
$user = $token->user;
$new_password = Hash::make($fields['password']);
$user->password = $new_password;
$user->save();
Log::writeLog("User '" . $user->username . "' is resetted his password");
return response()->json([
'message' => 'Your password was successfully changed!'
]);
}
/**
* @OA\Post(
* path="/api/auth/activate-account",
* summary="Confirm user account via email verification token",
* tags={"Auth"},
* @OA\RequestBody(
* required=true,
* @OA\JsonContent(
* required={"token"},
* @OA\Property(property="token", type="string", example="abcdef123456")
* )
* ),
* @OA\Response(
* response=200,
* description="Account successfully activated",
* @OA\JsonContent(
* @OA\Property(property="message", type="string", example="Your account was successfully activated")
* )
* ),
* @OA\Response(
* response=404,
* description="Invalid token",
* @OA\JsonContent(
* @OA\Property(property="message", type="string", example="Your token is not valid")
* )
* ),
* @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={"token": {"The token field is required."}}
* )
* )
* )
* )
*/
public function confirmationAccount(Request $request)
{
$fields = $request->validate([
'token' => 'required'
]);
$token = Token::existsTokenByToken($fields['token'], 'email_verification');
if(!$token) {
return response()->json(['message' => 'Your token is not valid'], 404);
}
$user = $token->user;
$token->delete();
if ($user->email_verified_at) {
return response()->json([
'message' => 'Your account has already been verified.'
]);
}
$user->email_verified_at = now();
$user->save();
return response()->json(['message' => 'Your account was successfully activated']);
}
/**
* @OA\Get(
* path="/api/auth/me",
* summary="Get current user info",
* tags={"Auth"},
* security={{"bearerAuth": {}}},
* @OA\Response(
* response=200,
* description="User info",
* @OA\JsonContent(
* @OA\Property(property="user", ref="#/components/schemas/UserResource")
* )
* ),
* @OA\Response(response=401, description="Unauthenticated")
* )
*/
public function me(Request $request)
{
return response()->json([
'user' => new UserResource($request->user())
]);
}
}