Made authorization.

This commit is contained in:
2023-07-06 10:48:32 +06:00
parent 6b2aff910b
commit f481ee765d
17 changed files with 356 additions and 5 deletions

View File

@@ -0,0 +1,10 @@
<?php declare(strict_types=1);
namespace App\Contracts;
use App\Dto\Request\Dto;
interface FormRequestDto
{
public function getDto(): Dto;
}

View File

@@ -0,0 +1,27 @@
<?php declare(strict_types=1);
namespace App\Dto\Request;
final readonly class Authorization extends Dto
{
public function __construct(
private string $email,
private string $password,
private bool $remember = false
) { }
public function getEmail(): string
{
return $this->email;
}
public function getPassword(): string
{
return $this->password;
}
public function getRemember(): bool
{
return $this->remember;
}
}

8
app/Dto/Request/Dto.php Normal file
View File

@@ -0,0 +1,8 @@
<?php declare(strict_types=1);
namespace App\Dto\Request;
abstract readonly class Dto
{
}

View File

@@ -0,0 +1,47 @@
<?php declare(strict_types=1);
namespace App\Http\Controllers;
use App\Http\Requests\AuthorizationRequest;
use App\Services\AuthService;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\Log;
use Illuminate\View\View;
use Illuminate\Http\RedirectResponse;
use Illuminate\Support\Facades\Auth;
final class AuthController extends Controller
{
public function __construct(
private readonly AuthService $authService
) { }
public function login(): View
{
return view('public/login');
}
public function authorization(AuthorizationRequest $request)
{
$authorization = $request->getDto();
$result = $this->authService->authorization($authorization);
if (!$result->isSuccess()) {
if ($result->getCode() === Response::HTTP_UNAUTHORIZED) {
Log::warning('Unauthorized ' . $authorization->getEmail() . ' [' . $request->getClientIp() . ']');
}
return redirect()->route('login')->withInput()->withErrors($result->getMessage());
}
$request->session()->regenerate();
Log::notice('Logged in ' . $authorization->getEmail() . ' [' . $request->getClientIp() . ']');
return redirect()->route('home');
}
public function logout(Request $request): RedirectResponse
{
Auth::logout();
$request->session()->invalidate();
$request->session()->regenerateToken();
return redirect(route('login'));
}
}

View File

@@ -0,0 +1,13 @@
<?php declare(strict_types=1);
namespace App\Http\Controllers;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Routing\Controller as BaseController;
class Controller extends BaseController
{
use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
}

View File

@@ -0,0 +1,23 @@
<?php declare(strict_types=1);
namespace App\Http\Controllers\Private;
use Illuminate\Support\Facades\Auth;
use Illuminate\View\View;
final class ProfileController extends Controller
{
public function profile(): View
{
return view('private/profile/profile', [
'user' => Auth::user()
]);
}
public function settings(): View
{
return view('private/profile/settings', [
'user' => Auth::user()
]);
}
}

View File

@@ -0,0 +1,31 @@
<?php declare(strict_types=1);
namespace App\Http\Requests;
use App\Contracts\FormRequestDto;
use App\Dto\Request\Authorization;
use Illuminate\Foundation\Http\FormRequest;
final class AuthorizationRequest extends FormRequest implements FormRequestDto
{
/**
* Get the validation rules that apply to the request.
*/
public function rules(): array
{
return [
'email' => ['required', 'email', 'max:255'],
'password' => ['required', 'min:3'],
'remember' => ['nullable', 'boolean'],
];
}
public function getDto(): Authorization
{
return new Authorization(
email: $this->input('email'),
password: $this->input('password'),
remember: (bool) $this->input('remember', false)
);
}
}

View File

@@ -0,0 +1,14 @@
<?php declare(strict_types=1);
namespace App\Repositories;
use App\Models\User;
use Illuminate\Support\Str;
final readonly class UserRepository
{
public function getUserByEmail(string $email): ?User
{
return User::query()->where('email', Str::lower($email))->first();
}
}

View File

@@ -0,0 +1,40 @@
<?php declare(strict_types=1);
namespace App\Services;
use App\Dto\Request\Authorization;
use App\Repositories\UserRepository;
use App\ServiceResults\ServiceResultArray;
use App\ServiceResults\ServiceResultError;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
final class AuthService extends Service
{
public function __construct(
private readonly UserRepository $userRepository
) { }
public function authorization(Authorization $authorization): ServiceResultError | ServiceResultArray
{
$user = $this->userRepository->getUserByEmail($authorization->getEmail());
if (is_null($user)) {
return $this->errUnauthorized(__('auth.failed'));
}
if (Hash::check($authorization->getPassword(), $user->password) !== true) {
return $this->errUnauthorized(__('auth.password'));
}
if ($user->is_active === false) {
return $this->errFobidden(__('auth.disabled'));
}
try {
Auth::login($user, $authorization->getRemember());
} catch (\Throwable $e) {
report($e);
return $this->errService(__('Server Error'));
}
return $this->ok(__('auth.success'));
}
}

View File

@@ -5,32 +5,38 @@ namespace App\Services;
use App\ServiceResults\ServiceResultArray;
use App\ServiceResults\ServiceResultError;
use Illuminate\Http\Response;
abstract class Service
{
final protected function errValidate(string $message, array $errors = []): ServiceResultError
{
return $this->error(422, $message, $errors);
return $this->error(Response::HTTP_UNPROCESSABLE_ENTITY, $message, $errors);
}
final protected function errFobidden(string $message): ServiceResultError
{
return $this->error(403, $message);
return $this->error(Response::HTTP_FORBIDDEN, $message);
}
final protected function errNotFound(string $message): ServiceResultError
{
return $this->error(404, $message);
return $this->error(Response::HTTP_NOT_FOUND, $message);
}
final protected function errService(string $message): ServiceResultError
{
return $this->error(500, $message);
return $this->error(Response::HTTP_INTERNAL_SERVER_ERROR, $message);
}
final protected function notAcceptable(string $message): ServiceResultError
{
return $this->error(406, $message);
return $this->error(Response::HTTP_NOT_ACCEPTABLE, $message);
}
final protected function errUnauthorized(string $message): ServiceResultError
{
return $this->error(Response::HTTP_UNAUTHORIZED, $message);
}
final protected function ok(string $message = 'OK'): ServiceResultArray

View File

@@ -0,0 +1,18 @@
<?php declare(strict_types=1);
namespace App\View\Components\Public;
use Illuminate\View\Component;
use Illuminate\View\View;
final class Layout extends Component
{
/**
* @inheritDoc
*/
public function render(): View
{
return view('public.layout.app');
}
}