Feature/AUTH
This commit is contained in:
parent
48ac6365a5
commit
6fa1e4797b
128
thanasoft-back/app/Http/Controllers/Api/AuthController.php
Normal file
128
thanasoft-back/app/Http/Controllers/Api/AuthController.php
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Api;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Models\User;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Http\JsonResponse;
|
||||||
|
use Illuminate\Support\Facades\Hash;
|
||||||
|
use Illuminate\Validation\Rules\Password;
|
||||||
|
use App\Http\Controllers\Api\BaseController as BaseController;
|
||||||
|
use Illuminate\Validation\ValidationException;
|
||||||
|
|
||||||
|
class AuthController extends BaseController
|
||||||
|
{
|
||||||
|
public function register(Request $request): JsonResponse
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$data = $request->validate([
|
||||||
|
'name' => ['required', 'string', 'max:255'],
|
||||||
|
'email' => ['required', 'string', 'email', 'max:255', 'unique:users,email'],
|
||||||
|
'password' => ['required', Password::min(8)],
|
||||||
|
|
||||||
|
]);
|
||||||
|
|
||||||
|
$user = User::create([
|
||||||
|
'name' => $data['name'],
|
||||||
|
'email' => $data['email'],
|
||||||
|
'password' => $data['password'], // hashed via User model cast
|
||||||
|
]);
|
||||||
|
|
||||||
|
$token = $user->createToken('api')->plainTextToken;
|
||||||
|
|
||||||
|
return $this->sendResponse([
|
||||||
|
'user' => $user,
|
||||||
|
'token' => $token,
|
||||||
|
], 'User registered successfully.');
|
||||||
|
|
||||||
|
} catch (ValidationException $e) {
|
||||||
|
return $this->sendError('Validation Error.', $e->errors(), 422);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return $this->sendError('Registration failed.', ['error' => $e->getMessage()], 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function login(Request $request): JsonResponse
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$credentials = $request->validate([
|
||||||
|
'email' => ['required', 'email'],
|
||||||
|
'password' => ['required', 'string'],
|
||||||
|
]);
|
||||||
|
|
||||||
|
/** @var User|null $user */
|
||||||
|
$user = User::where('email', $credentials['email'])->first();
|
||||||
|
|
||||||
|
if (! $user || ! Hash::check($credentials['password'], $user->password)) {
|
||||||
|
return $this->sendError('Invalid credentials.', ['email' => ['The provided credentials are incorrect.']], 401);
|
||||||
|
}
|
||||||
|
|
||||||
|
$token = $user->createToken('api')->plainTextToken;
|
||||||
|
|
||||||
|
return $this->sendResponse([
|
||||||
|
'user' => $user,
|
||||||
|
'token' => $token,
|
||||||
|
], 'Login successful.');
|
||||||
|
|
||||||
|
} catch (ValidationException $e) {
|
||||||
|
return $this->sendError('Validation Error.', $e->errors(), 422);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return $this->sendError('Login failed.', ['error' => $e->getMessage()], 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function me(Request $request): JsonResponse
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$user = $request->user();
|
||||||
|
|
||||||
|
if (!$user) {
|
||||||
|
return $this->sendError('Unauthenticated.', [], 401);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->sendResponse($user, 'User retrieved successfully.');
|
||||||
|
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return $this->sendError('Failed to retrieve user.', ['error' => $e->getMessage()], 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function logout(Request $request): JsonResponse
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$user = $request->user();
|
||||||
|
|
||||||
|
if (!$user) {
|
||||||
|
return $this->sendError('Unauthenticated.', [], 401);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($user->currentAccessToken()) {
|
||||||
|
$user->currentAccessToken()->delete();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->sendResponse([], 'Logged out successfully.');
|
||||||
|
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return $this->sendError('Logout failed.', ['error' => $e->getMessage()], 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function logoutAll(Request $request): JsonResponse
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$user = $request->user();
|
||||||
|
|
||||||
|
if (!$user) {
|
||||||
|
return $this->sendError('Unauthenticated.', [], 401);
|
||||||
|
}
|
||||||
|
|
||||||
|
$user->tokens()->delete();
|
||||||
|
|
||||||
|
return $this->sendResponse([], 'Logged out from all devices successfully.');
|
||||||
|
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return $this->sendError('Logout failed.', ['error' => $e->getMessage()], 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
44
thanasoft-back/app/Http/Controllers/Api/BaseController.php
Normal file
44
thanasoft-back/app/Http/Controllers/Api/BaseController.php
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\API;
|
||||||
|
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use App\Http\Controllers\Controller as Controller;
|
||||||
|
|
||||||
|
class BaseController extends Controller
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* success response method.
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function sendResponse($result, $message)
|
||||||
|
{
|
||||||
|
$response = [
|
||||||
|
'success' => true,
|
||||||
|
'data' => $result,
|
||||||
|
'message' => $message,
|
||||||
|
];
|
||||||
|
|
||||||
|
return response()->json($response, 200);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* return error response.
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function sendError($error, $errorMessages = [], $code = 404)
|
||||||
|
{
|
||||||
|
$response = [
|
||||||
|
'success' => false,
|
||||||
|
'message' => $error,
|
||||||
|
];
|
||||||
|
|
||||||
|
if(!empty($errorMessages)){
|
||||||
|
$response['data'] = $errorMessages;
|
||||||
|
}
|
||||||
|
|
||||||
|
return response()->json($response, $code);
|
||||||
|
}
|
||||||
|
}
|
||||||
84
thanasoft-back/config/sanctum.php
Normal file
84
thanasoft-back/config/sanctum.php
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Laravel\Sanctum\Sanctum;
|
||||||
|
|
||||||
|
return [
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Stateful Domains
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Requests from the following domains / hosts will receive stateful API
|
||||||
|
| authentication cookies. Typically, these should include your local
|
||||||
|
| and production domains which access your API via a frontend SPA.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', sprintf(
|
||||||
|
'%s%s',
|
||||||
|
'localhost,localhost:3000,127.0.0.1,127.0.0.1:8000,::1',
|
||||||
|
Sanctum::currentApplicationUrlWithPort(),
|
||||||
|
// Sanctum::currentRequestHost(),
|
||||||
|
))),
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Sanctum Guards
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| This array contains the authentication guards that will be checked when
|
||||||
|
| Sanctum is trying to authenticate a request. If none of these guards
|
||||||
|
| are able to authenticate the request, Sanctum will use the bearer
|
||||||
|
| token that's present on an incoming request for authentication.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'guard' => ['web'],
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Expiration Minutes
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| This value controls the number of minutes until an issued token will be
|
||||||
|
| considered expired. This will override any values set in the token's
|
||||||
|
| "expires_at" attribute, but first-party sessions are not affected.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'expiration' => null,
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Token Prefix
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Sanctum can prefix new tokens in order to take advantage of numerous
|
||||||
|
| security scanning initiatives maintained by open source platforms
|
||||||
|
| that notify developers if they commit tokens into repositories.
|
||||||
|
|
|
||||||
|
| See: https://docs.github.com/en/code-security/secret-scanning/about-secret-scanning
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'token_prefix' => env('SANCTUM_TOKEN_PREFIX', ''),
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Sanctum Middleware
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| When authenticating your first-party SPA with Sanctum you may need to
|
||||||
|
| customize some of the middleware Sanctum uses while processing the
|
||||||
|
| request. You may change the middleware listed below as required.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'middleware' => [
|
||||||
|
'authenticate_session' => Laravel\Sanctum\Http\Middleware\AuthenticateSession::class,
|
||||||
|
'encrypt_cookies' => Illuminate\Cookie\Middleware\EncryptCookies::class,
|
||||||
|
'validate_csrf_token' => Illuminate\Foundation\Http\Middleware\ValidateCsrfToken::class,
|
||||||
|
],
|
||||||
|
|
||||||
|
];
|
||||||
@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
if (! Schema::hasTable('personal_access_tokens')) {
|
||||||
|
Schema::create('personal_access_tokens', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->morphs('tokenable');
|
||||||
|
$table->text('name');
|
||||||
|
$table->string('token', 64)->unique();
|
||||||
|
$table->text('abilities')->nullable();
|
||||||
|
$table->timestamp('last_used_at')->nullable();
|
||||||
|
$table->timestamp('expires_at')->nullable()->index();
|
||||||
|
$table->timestamps();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('personal_access_tokens');
|
||||||
|
}
|
||||||
|
};
|
||||||
25
thanasoft-back/routes/api.php
Normal file
25
thanasoft-back/routes/api.php
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Support\Facades\Route;
|
||||||
|
use App\Http\Controllers\Api\AuthController;
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| API Routes
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| These routes are loaded with the "api" middleware group and are prefixed
|
||||||
|
| with /api automatically via bootstrap/app.php.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
Route::prefix('auth')->group(function () {
|
||||||
|
Route::post('/register', [AuthController::class, 'register']);
|
||||||
|
Route::post('/login', [AuthController::class, 'login']);
|
||||||
|
|
||||||
|
Route::middleware('auth:sanctum')->group(function () {
|
||||||
|
Route::get('/me', [AuthController::class, 'me']);
|
||||||
|
Route::post('/logout', [AuthController::class, 'logout']);
|
||||||
|
Route::post('/logout-all', [AuthController::class, 'logoutAll']);
|
||||||
|
});
|
||||||
|
});
|
||||||
8
thanasoft-front/src/types/user.ts
Normal file
8
thanasoft-front/src/types/user.ts
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
export interface User {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
email: string;
|
||||||
|
email_verified_at?: string | null;
|
||||||
|
created_at?: string;
|
||||||
|
updated_at?: string;
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user