Pārlūkot izejas kodu

stabilize interfaces

michelphp 21 stundas atpakaļ
vecāks
revīzija
ab97f1026c

+ 2 - 2
README.md

@@ -33,13 +33,13 @@ Then, create a provider implementing `Michel\Auth\UserProviderInterface` to fetc
 Set up form authentication for your web application.
 
 ```php
-use Michel\Auth\Handler\FormAuthAuthHandler;
+use Michel\Auth\Handler\FormAuthHandler;
 use Michel\Auth\Middlewares\AuthMiddleware;
 
 // $userProvider = new YourUserProvider();
 // $sessionStorage = new YourSessionStorage();
 
-$formHandler = new FormAuthAuthHandler($userProvider, $sessionStorage, [
+$formHandler = new FormAuthHandler($userProvider, $sessionStorage, [
     'login_path' => '/login',
     'login_key' => 'email',
     'password_key' => 'password',

+ 7 - 0
src/Exception/LogoutException.php

@@ -0,0 +1,7 @@
+<?php
+
+namespace Michel\Auth\Exception;
+
+class LogoutException extends AuthenticationException
+{
+}

+ 19 - 6
src/Handler/FormAuthAuthHandler.php → src/Handler/FormAuthHandler.php

@@ -5,6 +5,7 @@ namespace Michel\Auth\Handler;
 use Michel\Auth\AuthIdentity;
 use Michel\Auth\Exception\AuthenticationException;
 use Michel\Auth\Exception\InvalidCredentialsException;
+use Michel\Auth\Exception\LogoutException;
 use Michel\Auth\Exception\UserNotFoundException;
 use Michel\Auth\PasswordAuthenticatedUserInterface;
 use Michel\Auth\UserInterface;
@@ -16,7 +17,7 @@ use Psr\Http\Message\ResponseFactoryInterface;
 use Psr\Http\Message\ResponseInterface;
 use Psr\Http\Message\ServerRequestInterface;
 
-class FormAuthAuthHandler implements AuthHandlerInterface, StatefulAuthHandlerInterface
+class FormAuthHandler implements AuthHandlerInterface, StatefulAuthHandlerInterface
 {
     public const AUTHENTICATION_ERROR = '_form.last_error';
     public const LAST_USERNAME = '_form.last_username';
@@ -24,6 +25,7 @@ class FormAuthAuthHandler implements AuthHandlerInterface, StatefulAuthHandlerIn
     private UserProviderInterface $userProvider;
     private SessionStorageInterface $sessionStorage;
     private string $loginPath;
+    private string $logoutPath;
     private string $loginKey;
     private string $passwordKey;
     private string $targetPath;
@@ -44,6 +46,7 @@ class FormAuthAuthHandler implements AuthHandlerInterface, StatefulAuthHandlerIn
 
         $optionResolver = new OptionsResolver([
             Option::string('login_path', '/login')->min(1),
+            Option::string('logout_path', '/logout')->min(1),
             Option::string('login_key', 'login')->min(1),
             Option::string('password_key', 'password')->min(1),
             Option::string('target_path', '/')->min(1),
@@ -54,6 +57,7 @@ class FormAuthAuthHandler implements AuthHandlerInterface, StatefulAuthHandlerIn
 
         $options = $optionResolver->resolve($options);
         $this->loginPath = '/'.ltrim($options['login_path'], '/');
+        $this->logoutPath = '/'.ltrim($options['logout_path'], '/');
         $this->loginKey = $options['login_key'];
         $this->passwordKey = $options['password_key'];
         $this->targetPath = '/'.ltrim($options['target_path'], '/');
@@ -67,17 +71,22 @@ class FormAuthAuthHandler implements AuthHandlerInterface, StatefulAuthHandlerIn
      */
     public function authenticate(ServerRequestInterface $request): ?AuthIdentity
     {
+        $path = $request->getUri()->getPath();
+        $method = $request->getMethod();
+
+        if ($path === $this->logoutPath) {
+            $this->sessionStorage->remove('user_identifier');
+            throw new LogoutException('User logged out.');
+        }
+
         if ($this->sessionStorage->has('user_identifier')) {
             $identifier = $this->sessionStorage->get('user_identifier');
             $user = $this->userProvider->findByIdentifier($identifier);
             if ($user instanceof UserInterface) {
-                return new AuthIdentity($user,  false);
+                return new AuthIdentity($user,  $path === $this->loginPath);
             }
         }
 
-        $path = $request->getUri()->getPath();
-        $method = $request->getMethod();
-
         if ($path === $this->loginPath && $method === 'GET') {
             return null;
         }
@@ -124,7 +133,11 @@ class FormAuthAuthHandler implements AuthHandlerInterface, StatefulAuthHandlerIn
 
     public function onFailure(ServerRequestInterface $request, ResponseFactoryInterface $responseFactory, ?AuthenticationException $exception = null): ResponseInterface
     {
-        if ($exception) {
+        if ($exception instanceof LogoutException) {
+            return $responseFactory->createResponse(302)->withHeader('Location', $this->loginPath);
+        }
+
+        if ($exception && !empty($exception->getMessage())) {
             $this->sessionStorage->put(self::AUTHENTICATION_ERROR, $exception->getMessage());
             $request = $request->withAttribute(self::AUTHENTICATION_ERROR, $exception->getMessage());
         }

+ 4 - 4
src/MichelPackage/MichelAuthPackage.php

@@ -3,7 +3,7 @@
 namespace Michel\Auth\MichelPackage;
 
 use Michel\Auth\Command\AuthPasswordHashCommand;
-use Michel\Auth\Handler\FormAuthAuthHandler;
+use Michel\Auth\Handler\FormAuthHandler;
 use Michel\Auth\Middlewares\AuthMiddleware;
 use Michel\Auth\UserProviderInterface;
 use Michel\Package\PackageInterface;
@@ -20,13 +20,13 @@ class MichelAuthPackage implements PackageInterface
         return [
             AuthMiddleware::class => static function (ContainerInterface $container) {
                 return new AuthMiddleware(
-                    $container->get(FormAuthAuthHandler::class),
+                    $container->get(FormAuthHandler::class),
                     $container->get(ResponseFactoryInterface::class),
                     $container->get(LoggerInterface::class)
                 );
             },
-            FormAuthAuthHandler::class => static function (ContainerInterface $container) {
-                return new FormAuthAuthHandler(
+            FormAuthHandler::class => static function (ContainerInterface $container) {
+                return new FormAuthHandler(
                     $container->get(UserProviderInterface::class),
                     $container->get(SessionStorageInterface::class),
                     [

+ 1 - 1
src/PasswordAuthenticatedUserInterface.php

@@ -4,5 +4,5 @@ namespace Michel\Auth;
 
 interface PasswordAuthenticatedUserInterface
 {
-    public function getPassword(): string;
+    public function getPassword(): ?string;
 }