diff --git a/app/Http/Controllers/Auth/ApiAuthController.php b/app/Http/Controllers/Auth/ApiAuthController.php new file mode 100644 index 0000000..230aef3 --- /dev/null +++ b/app/Http/Controllers/Auth/ApiAuthController.php @@ -0,0 +1,67 @@ +all(), [ + 'name' => 'required|string|max:255', + 'email' => 'required|email|unique:users|max:255', + 'password' => 'required|min:10', + ]); + // Return errors if validation error occur. + if ($validator->fails()) { + $errors = $validator->errors(); + return response()->json([ + 'error' => $errors + ], 400); + } + // Check if validation pass then create user and auth token. Return the auth token + if ($validator->passes()) { + $user = User::create([ + 'name' => $request->name, + 'email' => $request->email, + 'password' => Hash::make($request->password) + ]); + $token = $user->createToken('auth_token')->plainTextToken; + + return response()->json([ + 'access_token' => $token, + 'token_type' => 'Bearer', + ]); + } + } + + public function login(Request $request) + { + if (!Auth::attempt($request->only('email', 'password'))) { + return response()->json([ + 'message' => 'Invalid login details' + ], 401); + } + + $user = User::where('email', $request['email'])->firstOrFail(); + + $token = $user->createToken('auth_token')->plainTextToken; + + return response()->json([ + 'access_token' => $token, + 'token_type' => 'Bearer', + ]); + } + + public function me(Request $request) + { + return $request->user(); + } +} diff --git a/app/Http/Controllers/Auth/RegisteredUserController.php b/app/Http/Controllers/Auth/RegisteredUserController.php index 5313f35..801140f 100644 --- a/app/Http/Controllers/Auth/RegisteredUserController.php +++ b/app/Http/Controllers/Auth/RegisteredUserController.php @@ -46,6 +46,8 @@ class RegisteredUserController extends Controller Auth::login($user); + $user->createToken('auth-token'); + return redirect(RouteServiceProvider::HOME); } } diff --git a/app/Http/Controllers/ProjectController.php b/app/Http/Controllers/ProjectController.php index cf6eefb..2b42e5b 100644 --- a/app/Http/Controllers/ProjectController.php +++ b/app/Http/Controllers/ProjectController.php @@ -16,6 +16,7 @@ use Illuminate\Contracts\View\View; use Illuminate\Http\JsonResponse; use Illuminate\Http\RedirectResponse; use Illuminate\Http\Request; +use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Response; @@ -28,8 +29,7 @@ class ProjectController extends Controller { // Check if API Call, get userID from request if ($request->is('api/*')) { - $user = User::find($request->user_id); - $this->authorize('viewAny', $user); + $user = Auth::user(); $projects = $user->projects()->paginate(4); return new ProjectResource($projects); diff --git a/app/Http/Kernel.php b/app/Http/Kernel.php index 494c050..6b16fb9 100644 --- a/app/Http/Kernel.php +++ b/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, ], diff --git a/app/Models/User.php b/app/Models/User.php index 5d72dfd..cf60e73 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -19,6 +19,7 @@ class User extends Authenticatable use HasApiTokens, HasFactory, Notifiable, UuidTrait; protected $table = 'users'; + public $incrementing = false; /** * The attributes that are mass assignable. @@ -47,6 +48,7 @@ class User extends Authenticatable * @var array */ protected $casts = [ + 'id' => 'string', 'email_verified_at' => 'datetime', 'password' => 'hashed', ]; diff --git a/config/auth.php b/config/auth.php index 9548c15..a87592f 100644 --- a/config/auth.php +++ b/config/auth.php @@ -16,6 +16,7 @@ return [ 'defaults' => [ 'guard' => 'web', 'passwords' => 'users', + ], /* @@ -40,6 +41,11 @@ return [ 'driver' => 'session', 'provider' => 'users', ], + 'api' => [ + 'driver' => 'sanctum', + 'provider' => 'users', + 'hash' => false, + ], ], /* diff --git a/database/migrations/2019_12_14_000001_create_personal_access_tokens_table.php b/database/migrations/2019_12_14_000001_create_personal_access_tokens_table.php index e828ad8..29db28a 100644 --- a/database/migrations/2019_12_14_000001_create_personal_access_tokens_table.php +++ b/database/migrations/2019_12_14_000001_create_personal_access_tokens_table.php @@ -13,7 +13,7 @@ return new class extends Migration { Schema::create('personal_access_tokens', function (Blueprint $table) { $table->id(); - $table->morphs('tokenable'); + $table->uuidMorphs('tokenable'); $table->string('name'); $table->string('token', 64)->unique(); $table->text('abilities')->nullable(); diff --git a/database/migrations/2023_08_11_125730_access_token_uuid.php b/database/migrations/2023_08_11_125730_access_token_uuid.php new file mode 100644 index 0000000..c56ae31 --- /dev/null +++ b/database/migrations/2023_08_11_125730_access_token_uuid.php @@ -0,0 +1,31 @@ +uuid('tokenable_id')->change(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('personal_access_tokens', function (Blueprint $table) { + // Replace tokenable_id to uuid + $table->bigInteger('tokenable_id')->unsigned()->change(); + + }); + } +}; diff --git a/routes/api.php b/routes/api.php index ceb2919..2bcbee6 100644 --- a/routes/api.php +++ b/routes/api.php @@ -1,6 +1,7 @@ get('/user', function (Request $request) { return $request->user(); }); +Route::post('/register', [ApiAuthController::class, 'register']); + +Route::post('/login', [ApiAuthController::class, 'login']); + + // Resources route to /api/projects -Route::apiResource('projects', ProjectController::class); +Route::middleware('auth:sanctum')->group( function () { + Route::get('/me', [ApiAuthController::class, 'me']); + Route::apiResource('projects', ProjectController::class); +});