- WIP on authentication portal
This commit is contained in:
		
							parent
							
								
									1559ceb248
								
							
						
					
					
						commit
						7769b1a1ca
					
				@ -7,5 +7,7 @@ use Ulmus\User\Entity\UserInterface;
 | 
			
		||||
 | 
			
		||||
interface AuthorizeMethodInterface
 | 
			
		||||
{
 | 
			
		||||
    public function connect(ServerRequestInterface $request) : UserInterface|false;
 | 
			
		||||
    public function connect(ServerRequestInterface $request, UserInterface $user) : UserInterface|false;
 | 
			
		||||
 | 
			
		||||
    public function catchRequest(ServerRequestInterface $request) : bool;
 | 
			
		||||
}
 | 
			
		||||
@ -1,34 +0,0 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace Ulmus\User\Authorize;
 | 
			
		||||
 | 
			
		||||
use Psr\Http\Message\ServerRequestInterface;
 | 
			
		||||
use Ulmus\User\Entity\UserInterface;
 | 
			
		||||
 | 
			
		||||
class BasicAuthentication implements AuthorizeMethodInterface
 | 
			
		||||
{
 | 
			
		||||
    public function connect(ServerRequestInterface $request): UserInterface|false
 | 
			
		||||
    {
 | 
			
		||||
        if ( null === $auth = $request->getHeader('Authorization') ) {
 | 
			
		||||
            list($method, $userPass) = explode(' ', $auth, 2) + [ null, null ];
 | 
			
		||||
 | 
			
		||||
            if (! $method ) {
 | 
			
		||||
                throw new \InvalidArgumentException("An authentication method must be provided");
 | 
			
		||||
            }
 | 
			
		||||
            elseif (! $userPass ) {
 | 
			
		||||
                throw new \InvalidArgumentException("A base64-encoded 'user:password' value must be provided");
 | 
			
		||||
            }
 | 
			
		||||
            
 | 
			
		||||
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected function basicMethod(string $header) : UserInterface|false
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										65
									
								
								src/Authorize/HeaderAuthentication.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								src/Authorize/HeaderAuthentication.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,65 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace Ulmus\User\Authorize;
 | 
			
		||||
 | 
			
		||||
use Psr\Http\Message\ServerRequestInterface;
 | 
			
		||||
use Ulmus\User\Common\AuthorizeContentTypeEnum;
 | 
			
		||||
use Ulmus\User\Entity\User;
 | 
			
		||||
use Ulmus\User\Entity\UserInterface;
 | 
			
		||||
use Ulmus\User\Lib\Authenticate;
 | 
			
		||||
 | 
			
		||||
class HeaderAuthentication implements AuthorizeMethodInterface
 | 
			
		||||
{
 | 
			
		||||
    public function connect(ServerRequestInterface $request, UserInterface $user): UserInterface|false
 | 
			
		||||
    {
 | 
			
		||||
        if ( null !== ( $auth = $request->getHeaderLine('Authorization') ) ) {
 | 
			
		||||
 | 
			
		||||
            list($method, $userPass) = explode(' ', $auth, 2) + [ null, null ];
 | 
			
		||||
 | 
			
		||||
            switch(strtolower(strtolower($method))) {
 | 
			
		||||
                case "basic":
 | 
			
		||||
                    return $this->basicMethod($userPass);
 | 
			
		||||
 | 
			
		||||
                default:
 | 
			
		||||
                    throw new \InvalidArgumentException("An authentication method must be provided");
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected function basicMethod(string $userPassword) : UserInterface|false
 | 
			
		||||
    {
 | 
			
		||||
        if ( false === $decoded = base64_decode($userPassword) ) {
 | 
			
		||||
            throw new \RuntimeException("Base64 decoding of given username:password failed");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        list($user, $password) = explode(':', $decoded) + [ null, null ];
 | 
			
		||||
 | 
			
		||||
        if ( empty($user) ) {
 | 
			
		||||
            throw new \RuntimeException("A username must be provided");
 | 
			
		||||
        }
 | 
			
		||||
        elseif ( empty($password) ) {
 | 
			
		||||
            throw new \RuntimeException("A password must be provided");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $authenticate = new Authenticate();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function catchRequest(ServerRequestInterface $request) : bool
 | 
			
		||||
    {
 | 
			
		||||
        foreach(array_merge($request->getHeader('Accept'), $request->getHeader('Content-Type')) as $accept) {
 | 
			
		||||
            foreach(explode(',', $accept) as $contentType) {
 | 
			
		||||
                if ( AuthorizeContentTypeEnum::tryFrom(strtolower($contentType)) ) {
 | 
			
		||||
                    return true;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										31
									
								
								src/Authorize/PostRequestAuthentication.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								src/Authorize/PostRequestAuthentication.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,31 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace Ulmus\User\Authorize;
 | 
			
		||||
 | 
			
		||||
use Psr\Http\Message\ServerRequestInterface;
 | 
			
		||||
use Ulmus\User\Entity\UserInterface;
 | 
			
		||||
use Ulmus\User\Lib\Authenticate;
 | 
			
		||||
 | 
			
		||||
class PostRequestAuthentication implements AuthorizeMethodInterface
 | 
			
		||||
{
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        protected Authenticate $authenticate,
 | 
			
		||||
        protected string $fieldUser = "username",
 | 
			
		||||
        protected string $postFieldUser = "username",
 | 
			
		||||
        protected string $postFieldPassword = "password",
 | 
			
		||||
    ) {}
 | 
			
		||||
 | 
			
		||||
    public function connect(ServerRequestInterface $request, UserInterface $user): UserInterface|false
 | 
			
		||||
    {
 | 
			
		||||
        $post = $request->getParsedBody();
 | 
			
		||||
 | 
			
		||||
        return $this->authenticate->authenticate($user::repository(), [ $this->fieldUser => $post[$this->postFieldUser] ], $post[$this->postFieldPassword]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function catchRequest(ServerRequestInterface $request): bool
 | 
			
		||||
    {
 | 
			
		||||
        $post = $request->getParsedBody();
 | 
			
		||||
 | 
			
		||||
        return strtoupper( $request->getMethod() ) === "POST" && isset($post[$this->postFieldUser], $post[$this->postFieldPassword]);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										10
									
								
								src/Common/AuthorizeContentTypeEnum.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								src/Common/AuthorizeContentTypeEnum.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,10 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace Ulmus\User\Common;
 | 
			
		||||
 | 
			
		||||
enum AuthorizeContentTypeEnum: string
 | 
			
		||||
{
 | 
			
		||||
    case ApplicationJson = "application/json";
 | 
			
		||||
    case ApplicationLDJson = "application/+json";
 | 
			
		||||
    case ApplicationVndApiJson = "application/vnd.api+json";
 | 
			
		||||
}
 | 
			
		||||
@ -1,16 +0,0 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace Ulmus\User\Common;
 | 
			
		||||
 | 
			
		||||
enum AuthorizeEnum : string
 | 
			
		||||
{
 | 
			
		||||
    case Basic = "basic";
 | 
			
		||||
    case Token = "token";
 | 
			
		||||
 | 
			
		||||
    #    case Bearer = "bearer";
 | 
			
		||||
#    case Custom = "custom";
 | 
			
		||||
#    case Digest = "digest";
 | 
			
		||||
#    case Key = "key";
 | 
			
		||||
#    case Ntlm = "ntlm";
 | 
			
		||||
#    case Negotiate = "negotiate";
 | 
			
		||||
}
 | 
			
		||||
@ -2,11 +2,12 @@
 | 
			
		||||
 | 
			
		||||
namespace Ulmus\User\Entity;
 | 
			
		||||
 | 
			
		||||
use Ulmus\Entity\EntityInterface;
 | 
			
		||||
use Ulmus\Entity\Field\Datetime;
 | 
			
		||||
 | 
			
		||||
use Ulmus\Attribute\Property\Field;
 | 
			
		||||
 
 | 
			
		||||
class User {
 | 
			
		||||
abstract class User implements UserInterface {
 | 
			
		||||
 | 
			
		||||
    #[Field\Id(readonly: true)]
 | 
			
		||||
    public int $id;
 | 
			
		||||
@ -47,27 +48,27 @@ class User {
 | 
			
		||||
    #[Field]
 | 
			
		||||
    public string $password;
 | 
			
		||||
 | 
			
		||||
    #[Field\UpdatedAt(name: "updated_at")]
 | 
			
		||||
    public readonly ? Datetime $updatedAt;
 | 
			
		||||
    #[Field\UpdatedAt(name: "updated_at", readonly: true)]
 | 
			
		||||
    public ? Datetime $updatedAt;
 | 
			
		||||
 | 
			
		||||
    #[Field\CreatedAt(name: "created_at")]
 | 
			
		||||
    public readonly Datetime $createdAt;
 | 
			
		||||
    #[Field\CreatedAt(name: "created_at", readonly: true)]
 | 
			
		||||
    public Datetime $createdAt;
 | 
			
		||||
 | 
			
		||||
    public bool $logged = false;
 | 
			
		||||
 | 
			
		||||
    public function __toString() : string
 | 
			
		||||
    {
 | 
			
		||||
        return "{$this->firstName} {$this->lastName}";
 | 
			
		||||
        return $this->fullName();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function setPassword($password) : self
 | 
			
		||||
    public function setPassword($password) : static
 | 
			
		||||
    {
 | 
			
		||||
        $this->password = $password;
 | 
			
		||||
 | 
			
		||||
        return $this->hashPassword();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function hashPassword(? string $password = null) : self
 | 
			
		||||
    public function hashPassword(? string $password = null) : static
 | 
			
		||||
    {
 | 
			
		||||
        $this->password = password_hash($password ?: $this->password, PASSWORD_DEFAULT);
 | 
			
		||||
 | 
			
		||||
@ -79,8 +80,13 @@ class User {
 | 
			
		||||
        return password_verify($password, $this->password);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function fullname() : string
 | 
			
		||||
    public function fullName() : string
 | 
			
		||||
    {
 | 
			
		||||
        return trim( ( $this->firstName ?? "" ) . " " . ( $this->lastName ?? "" ) );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function loggedIn(): bool
 | 
			
		||||
    {
 | 
			
		||||
        return $this->logged;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -2,7 +2,13 @@
 | 
			
		||||
 | 
			
		||||
namespace Ulmus\User\Entity;
 | 
			
		||||
 | 
			
		||||
interface UserInterface
 | 
			
		||||
use Ulmus\Entity\EntityInterface;
 | 
			
		||||
 | 
			
		||||
interface UserInterface extends EntityInterface
 | 
			
		||||
{
 | 
			
		||||
    public function __toString() : string;
 | 
			
		||||
    public function loggedIn() : bool;
 | 
			
		||||
    public function verifyPassword(string $password) : bool;
 | 
			
		||||
    public function hashPassword(? string $password = null) : static;
 | 
			
		||||
    public function setPassword($password) : static;
 | 
			
		||||
}
 | 
			
		||||
@ -10,27 +10,18 @@ use Ulmus\User\Entity\User;
 | 
			
		||||
use Ulmus\Exception;
 | 
			
		||||
 | 
			
		||||
class Authenticate {
 | 
			
		||||
 | 
			
		||||
    protected ? Session $session;
 | 
			
		||||
 | 
			
		||||
    protected ? Cookie $cookie;
 | 
			
		||||
 | 
			
		||||
    protected bool $logged = false;
 | 
			
		||||
 | 
			
		||||
    protected Closure $authenticationEvent;
 | 
			
		||||
 | 
			
		||||
    public ? User $user = null;
 | 
			
		||||
 | 
			
		||||
    public string $connection_fields = 'email';
 | 
			
		||||
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        ? Session $session = null,
 | 
			
		||||
        ? Cookie  $cookie = null,
 | 
			
		||||
        protected ? Session $session = null,
 | 
			
		||||
        protected ? Cookie  $cookie = null,
 | 
			
		||||
        ? Closure $authenticationEvent = null
 | 
			
		||||
    ) {
 | 
			
		||||
        $this->session = $session;
 | 
			
		||||
        $this->cookie = $cookie;
 | 
			
		||||
        $this->authenticationEvent = $authenticationEvent ?: function(bool $authenticated, string $message, ? User $user, array $data = []) : ? bool {return null;} ;
 | 
			
		||||
        $this->authenticationEvent = $authenticationEvent ?: fn(bool $authenticated, string $message, ? User $user, array $data = []) : ? bool => null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function rememberMe(\Ulmus\Repository $repository) : ? User
 | 
			
		||||
@ -110,9 +101,6 @@ class Authenticate {
 | 
			
		||||
        return $this->user;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Force user disconnection and handle memory trashing
 | 
			
		||||
     */
 | 
			
		||||
    public function logout() : self
 | 
			
		||||
    {
 | 
			
		||||
        if ( $this->session ) {
 | 
			
		||||
@ -123,7 +111,7 @@ class Authenticate {
 | 
			
		||||
            $this->cookie->delete('user.id');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (isset($this->user)) {
 | 
			
		||||
        if ( isset($this->user) ) {
 | 
			
		||||
            $this->user->logged = false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,29 +0,0 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace Ulmus\User\Middleware;
 | 
			
		||||
 | 
			
		||||
use Psr\Http\{
 | 
			
		||||
    Message\ResponseInterface,
 | 
			
		||||
    Message\ServerRequestInterface,
 | 
			
		||||
    Server\MiddlewareInterface,
 | 
			
		||||
    Server\RequestHandlerInterface
 | 
			
		||||
};
 | 
			
		||||
use Ulmus\User\Authorize\AuthorizeMethodInterface;
 | 
			
		||||
use Ulmus\User\Common\AuthorizeEnum;
 | 
			
		||||
 | 
			
		||||
class AuthorizeMiddleware implements MiddlewareInterface
 | 
			
		||||
{
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        protected AuthorizeMethodInterface $method,
 | 
			
		||||
        protected ResponseInterface $loginFailed,
 | 
			
		||||
    ) { }
 | 
			
		||||
 | 
			
		||||
    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
 | 
			
		||||
    {
 | 
			
		||||
        if ( false ) {
 | 
			
		||||
            return $this->loginFailed;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $handler->handle($request);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -1,26 +0,0 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace Ulmus\User\Middleware;
 | 
			
		||||
 | 
			
		||||
use Psr\Http\{
 | 
			
		||||
    Message\ResponseInterface,
 | 
			
		||||
    Message\ServerRequestInterface,
 | 
			
		||||
    Server\MiddlewareInterface,
 | 
			
		||||
    Server\RequestHandlerInterface
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class AuthorizeMiddleware implements MiddlewareInterface
 | 
			
		||||
{
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        protected ResponseInterface $loginFailed
 | 
			
		||||
    ) { }
 | 
			
		||||
 | 
			
		||||
    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
 | 
			
		||||
    {
 | 
			
		||||
        if ( false ) {
 | 
			
		||||
            return $this->loginFailed;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $handler->handle($request);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										36
									
								
								src/Middleware/HeaderAuthenticationMiddleware.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								src/Middleware/HeaderAuthenticationMiddleware.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,36 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace Ulmus\User\Middleware;
 | 
			
		||||
 | 
			
		||||
use Psr\Http\{
 | 
			
		||||
    Message\ResponseInterface,
 | 
			
		||||
    Message\ServerRequestInterface,
 | 
			
		||||
    Server\MiddlewareInterface,
 | 
			
		||||
    Server\RequestHandlerInterface
 | 
			
		||||
};
 | 
			
		||||
use Ulmus\User\Entity\UserInterface;
 | 
			
		||||
use Ulmus\User\Authorize\HeaderAuthentication;
 | 
			
		||||
 | 
			
		||||
class HeaderAuthenticationMiddleware implements MiddlewareInterface
 | 
			
		||||
{
 | 
			
		||||
    protected HeaderAuthentication $authenticator;
 | 
			
		||||
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        protected UserInterface $entity,
 | 
			
		||||
        protected \Closure $loginFailedResponse,
 | 
			
		||||
        HeaderAuthentication $authenticator = null,
 | 
			
		||||
    ) {
 | 
			
		||||
        $this->authenticator = $authenticator ?: new HeaderAuthentication();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
 | 
			
		||||
    {
 | 
			
		||||
        if ( $this->authenticator->catchRequest($request) ) {
 | 
			
		||||
            if ( ! $this->authenticator->connect($request, $this->entity) ) {
 | 
			
		||||
                return call_user_func($this->loginFailedResponse, [ 'api.process' => "Auth failed" ]);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $handler->handle($request);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										37
									
								
								src/Middleware/PostRequestAuthenticationMiddleware.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								src/Middleware/PostRequestAuthenticationMiddleware.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,37 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace Ulmus\User\Middleware;
 | 
			
		||||
 | 
			
		||||
use Psr\Http\{
 | 
			
		||||
    Message\ResponseInterface,
 | 
			
		||||
    Message\ServerRequestInterface,
 | 
			
		||||
    Server\MiddlewareInterface,
 | 
			
		||||
    Server\RequestHandlerInterface
 | 
			
		||||
};
 | 
			
		||||
use Ulmus\User\Entity\UserInterface;
 | 
			
		||||
use Ulmus\User\Authorize\PostRequestAuthentication;
 | 
			
		||||
use Ulmus\User\Lib\Authenticate;
 | 
			
		||||
 | 
			
		||||
class PostRequestAuthenticationMiddleware implements MiddlewareInterface
 | 
			
		||||
{
 | 
			
		||||
    protected PostRequestAuthentication $authenticator;
 | 
			
		||||
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        protected UserInterface     $entity,
 | 
			
		||||
        protected \Closure          $loginFailedResponse,
 | 
			
		||||
        PostRequestAuthentication   $authenticator = null,
 | 
			
		||||
    ) {
 | 
			
		||||
        $this->authenticator = $authenticator ?: new PostRequestAuthentication(new Authenticate());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
 | 
			
		||||
    {
 | 
			
		||||
        if ( $this->authenticator->catchRequest($request) ) {
 | 
			
		||||
            if ( ! $this->authenticator->connect($request, $this->entity) ) {
 | 
			
		||||
                return call_user_func($this->loginFailedResponse, "Login failed");
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $handler->handle($request);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										5
									
								
								src/Role/RoleAnonymousInterface.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								src/Role/RoleAnonymousInterface.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,5 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace Ulmus\User\Role;
 | 
			
		||||
 | 
			
		||||
interface RoleAnonymousInterface {}
 | 
			
		||||
							
								
								
									
										5
									
								
								src/Role/RoleIdentifiedInterface.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								src/Role/RoleIdentifiedInterface.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,5 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace Ulmus\User\Role;
 | 
			
		||||
 | 
			
		||||
interface RoleIdentifiedInterface {}
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user