Просмотр исходного кода

Login & logout & data response specifications

moell 1 год назад
Родитель
Сommit
844bf34e73

+ 49 - 0
app/Http/Controllers/API/AuthController.php

@@ -0,0 +1,49 @@
+<?php
+
+namespace App\Http\Controllers\API;
+
+use App\Http\Controllers\Controller;
+use App\Http\Requests\API\User\LoginRequest;
+use App\Models\User;
+use Illuminate\Http\Request;
+use Illuminate\Support\Facades\Auth;
+use Illuminate\Support\Facades\Hash;
+use Illuminate\Validation\ValidationException;
+use Laravel\Sanctum\PersonalAccessToken;
+
+class AuthController extends Controller
+{
+    public function login(LoginRequest $request)
+    {
+        $user = User::query()
+            ->where("username", $request->username)
+            ->orWhere("email", $request->username)
+            ->first();
+
+        if (! $user || ! Hash::check($request->password, $user->password)) {
+            throw ValidationException::withMessages([
+                'username' => ['The provided credentials are incorrect.'],
+            ]);
+        }
+
+        //Duplicate logins are not allowed
+        PersonalAccessToken::query()->where("tokenable_type", User::class)
+            ->where("name", 'user')
+            ->where("tokenable_id", $user->id)
+            ->delete();
+
+        return $this->success([
+            'data' => [
+                'token' => $user->createToken('user')->plainTextToken,
+            ]
+        ]);
+    }
+
+
+    public function logout()
+    {
+        Auth::user()->currentAccessToken()->delete();
+
+        return $this->noContent();
+    }
+}

+ 1 - 1
app/Http/Controllers/Controller.php

@@ -8,5 +8,5 @@ use Illuminate\Routing\Controller as BaseController;
 
 class Controller extends BaseController
 {
-    use AuthorizesRequests, ValidatesRequests;
+    use AuthorizesRequests, ValidatesRequests, JsonResponseHelper;
 }

+ 115 - 0
app/Http/Controllers/JsonResponseHelper.php

@@ -0,0 +1,115 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use Illuminate\Http\JsonResponse;
+use Illuminate\Http\Response;
+
+trait JsonResponseHelper
+{
+    /**
+     * 201
+     *
+     * @param array|string|null $content
+     * @return string
+     */
+    protected function created(array|string $content = null): string
+    {
+        return new Response($content, Response::HTTP_CREATED);
+    }
+
+    /**
+     * 202
+     *
+     * @return Response
+     */
+    protected function accepted(): Response
+    {
+        return new Response('', Response::HTTP_ACCEPTED);
+    }
+
+    /**
+     * 204
+     *
+     * @return Response
+     */
+    protected function noContent(): Response
+    {
+        return new Response('', Response::HTTP_NO_CONTENT);
+    }
+
+    /**
+     * 400
+     *
+     * @param string $message
+     * @param array $headers
+     * @param int $options
+     * @return JsonResponse
+     */
+    protected function badRequest(string $message, array $headers = [], int $options = 0): JsonResponse
+    {
+        return response()->json([
+            'message' => $message
+        ], Response::HTTP_BAD_REQUEST, $headers, $options);
+    }
+
+    /**
+     * 401
+     *
+     * @param string $message
+     * @param array $headers
+     * @param int $options
+     * @return JsonResponse
+     */
+    protected function unauthorized(string $message = '', array $headers = [], int $options = 0): JsonResponse
+    {
+        return response()->json([
+            'message' => $message ? $message : 'Token Signature could not be verified.'
+        ], Response::HTTP_UNAUTHORIZED, $headers, $options);
+    }
+
+    /**
+     * 403
+     *
+     * @param string $message
+     * @param array $headers
+     * @param int $options
+     * @return JsonResponse
+     */
+    protected function forbidden(string $message = '', array $headers = [], int $options = 0): JsonResponse
+    {
+        return response()->json([
+            'message' => $message ? $message : 'Insufficient permissions.'
+        ], Response::HTTP_FORBIDDEN, $headers, $options);
+    }
+
+    /**
+     * 422
+     *
+     * @param array $errors
+     * @param array $headers
+     * @param string $message
+     * @param $options
+     * @return JsonResponse
+     */
+    protected function unprocesableEtity(array $errors = [], array $headers = [], string $message = '', $options = 0)
+    {
+        return response()->json([
+            'message' => $message ? $message : '422 Unprocessable Entity',
+            'errors' => $errors
+        ], Response::HTTP_UNPROCESSABLE_ENTITY, $headers, $options);
+    }
+
+    /**
+     * 200
+     *
+     * @param array $data
+     * @param array $headers
+     * @param $options
+     * @return JsonResponse
+     */
+    protected function success(array $data, array $headers = [], $options = 0): JsonResponse
+    {
+        return response()->json($data, Response::HTTP_OK, $headers, $options);
+    }
+}

+ 1 - 1
app/Http/Kernel.php

@@ -39,7 +39,7 @@ class Kernel extends HttpKernel
         ],
 
         'api' => [
-            // \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
+            \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
             \Illuminate\Routing\Middleware\ThrottleRequests::class.':api',
             \Illuminate\Routing\Middleware\SubstituteBindings::class,
         ],

+ 29 - 0
app/Http/Requests/API/User/LoginRequest.php

@@ -0,0 +1,29 @@
+<?php
+
+namespace App\Http\Requests\API\User;
+
+use Illuminate\Foundation\Http\FormRequest;
+
+class LoginRequest extends FormRequest
+{
+    /**
+     * Determine if the user is authorized to make this request.
+     */
+    public function authorize(): bool
+    {
+        return true;
+    }
+
+    /**
+     * Get the validation rules that apply to the request.
+     *
+     * @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
+     */
+    public function rules(): array
+    {
+        return [
+            'username' => 'required',
+            'password' => 'required',
+        ];
+    }
+}

+ 1 - 1
config/sanctum.php

@@ -46,7 +46,7 @@ return [
     |
     */
 
-    'expiration' => null,
+    'expiration' => env("TOKEN_EXPIRATION", 2 * 30 * 24 * 60),
 
     /*
     |--------------------------------------------------------------------------

+ 28 - 0
database/migrations/2024_01_14_134918_add_username_to_user_table.php

@@ -0,0 +1,28 @@
+<?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
+    {
+        Schema::table('users', function (Blueprint $table) {
+            $table->string("username", 30)->unique();
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     */
+    public function down(): void
+    {
+        Schema::table('users', function (Blueprint $table) {
+            $table->dropColumn("username");
+        });
+    }
+};

+ 6 - 0
routes/api.php

@@ -17,3 +17,9 @@ use Illuminate\Support\Facades\Route;
 Route::middleware('auth:sanctum')->get('/user', function (Request $request) {
     return $request->user();
 });
+
+Route::post("/login", [\App\Http\Controllers\API\AuthController::class, "login"]);
+
+Route::middleware(['auth:sanctum'])->group(function () {
+    Route::post("/logout", [\App\Http\Controllers\API\AuthController::class, "logout"]);
+});