diff --git a/src/AuthServiceProvider.php b/src/AuthServiceProvider.php index bad87d2..6d50cab 100644 --- a/src/AuthServiceProvider.php +++ b/src/AuthServiceProvider.php @@ -21,6 +21,7 @@ public function register() $this->app->register(RouteServiceProvider::class); $this->app->register(RepositoryServiceProvider::class); + $this->app->register(EventServiceProvider::class); } /** diff --git a/src/EventServiceProvider.php b/src/EventServiceProvider.php new file mode 100644 index 0000000..2455cd8 --- /dev/null +++ b/src/EventServiceProvider.php @@ -0,0 +1,40 @@ +> + */ + protected $listen = [ + Lockout::class => [ + LockoutEventListener::class, + ], + ]; + + /** + * Register any events for your application. + */ + public function boot(): void + { + // + } + + /** + * Determine if events and listeners should be automatically discovered. + */ + public function shouldDiscoverEvents(): bool + { + return false; + } +} diff --git a/src/Http/Controllers/AuthenticatedSessionController.php b/src/Http/Controllers/AuthenticatedSessionController.php index 8218a45..73959ef 100644 --- a/src/Http/Controllers/AuthenticatedSessionController.php +++ b/src/Http/Controllers/AuthenticatedSessionController.php @@ -3,23 +3,37 @@ namespace Fintech\Auth\Http\Controllers; use Fintech\Auth\Http\Requests\LoginRequest; +use Fintech\Core\Traits\ApiResponseTrait; +use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; use Illuminate\Http\Response; use Illuminate\Routing\Controller; use Illuminate\Support\Facades\Auth; +use Illuminate\Validation\ValidationException; class AuthenticatedSessionController extends Controller { + use ApiResponseTrait; /** * Handle an incoming authentication request. + * @param LoginRequest $request + * @return JsonResponse + * @throws ValidationException */ - public function store(LoginRequest $request): Response + public function store(LoginRequest $request): JsonResponse { - $request->authenticate(); + $request->ensureIsNotRateLimited(); - $request->session()->regenerate(); + if (!Auth::attempt($request->only('login_id', 'password'))) { - return response()->noContent(); + $request->hitRateLimited(); + + return $this->failed(__('auth.failed')); + } + + $request->clearRateLimited(); + + return response()->json(['data' => Auth::guard('api')->user(), 'message' => 'Login Successful.'], Response::HTTP_OK); } /** diff --git a/src/Http/Requests/LoginRequest.php b/src/Http/Requests/LoginRequest.php index 3e40d32..b47fbc5 100644 --- a/src/Http/Requests/LoginRequest.php +++ b/src/Http/Requests/LoginRequest.php @@ -3,11 +3,13 @@ namespace Fintech\Auth\Http\Requests; use Illuminate\Auth\Events\Lockout; +use Illuminate\Contracts\Validation\Rule; use Illuminate\Foundation\Http\FormRequest; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\RateLimiter; use Illuminate\Support\Str; use Illuminate\Validation\ValidationException; +use Symfony\Component\HttpFoundation\Response; class LoginRequest extends FormRequest { @@ -27,31 +29,29 @@ public function authorize(): bool public function rules(): array { return [ - 'email' => ['required', 'string', 'email'], + 'login_id' => ['required', 'string'], 'password' => ['required', 'string'], ]; } /** - * Attempt to authenticate the request's credentials. + * clear the rate limiter if authenticated * - * @throws \Illuminate\Validation\ValidationException */ - public function authenticate(): void + public function clearRateLimited(): void { - $this->ensureIsNotRateLimited(); - - if (! Auth::guard('api')->attempt($this->only('email', 'password'), $this->boolean('remember'))) { - RateLimiter::hit($this->throttleKey()); - - throw ValidationException::withMessages([ - 'email' => __('auth.failed'), - ]); - } - RateLimiter::clear($this->throttleKey()); } + /** + * count the rate limiter if authenticated + * + */ + public function hitRateLimited(): void + { + RateLimiter::hit($this->throttleKey()); + } + /** * Ensure the login request is not rate limited. * @@ -59,7 +59,7 @@ public function authenticate(): void */ public function ensureIsNotRateLimited(): void { - if (! RateLimiter::tooManyAttempts($this->throttleKey(), 5)) { + if (!RateLimiter::tooManyAttempts($this->throttleKey(), 5)) { return; } @@ -67,12 +67,11 @@ public function ensureIsNotRateLimited(): void $seconds = RateLimiter::availableIn($this->throttleKey()); - throw ValidationException::withMessages([ - 'email' => trans('auth.throttle', [ - 'seconds' => $seconds, - 'minutes' => ceil($seconds / 60), - ]), - ]); + abort(Response::HTTP_TOO_MANY_REQUESTS, trans('auth.throttle', [ + 'seconds' => $seconds, + 'minutes' => ceil($seconds / 60), + ])); + } /** @@ -80,6 +79,6 @@ public function ensureIsNotRateLimited(): void */ public function throttleKey(): string { - return Str::transliterate(Str::lower($this->input('email')).'|'.$this->ip()); + return Str::transliterate(Str::lower($this->input('login_id')).'|'.$this->ip()); } } diff --git a/src/Listeners/LockoutEventListener.php b/src/Listeners/LockoutEventListener.php new file mode 100644 index 0000000..1043343 --- /dev/null +++ b/src/Listeners/LockoutEventListener.php @@ -0,0 +1,23 @@ + $seconds, +// 'minutes' => ceil($seconds / 60), +// ])); + } +} diff --git a/src/Listerns/.gitkeep b/src/Listerns/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/src/Models/User.php b/src/Models/User.php index 91603ff..3a5beb3 100644 --- a/src/Models/User.php +++ b/src/Models/User.php @@ -5,13 +5,15 @@ use Fintech\Core\Traits\BlameableTrait; use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Foundation\Auth\User as Authenticatable; +use Laravel\Sanctum\HasApiTokens; use OwenIt\Auditing\Contracts\Auditable; class User extends Authenticatable implements Auditable { use BlameableTrait; use \OwenIt\Auditing\Auditable; -// use SoftDeletes; + use HasApiTokens; + use SoftDeletes; /* |-------------------------------------------------------------------------- diff --git a/src/RouteServiceProvider.php b/src/RouteServiceProvider.php index 7c5ab63..304d26e 100644 --- a/src/RouteServiceProvider.php +++ b/src/RouteServiceProvider.php @@ -25,7 +25,6 @@ public function boot() $this->routes(function () use (&$root_prefix) { Route::prefix("{$root_prefix}api") ->middleware('api') - ->namespace($this->namespace) ->group(__DIR__.'/../routes/api.php'); }); }