Вход Регистрация
Файл: gapps/vendor/cartalyst/sentinel/src/Sentinel.php
Строк: 879
<?php

/**
 * Part of the Sentinel package.
 *
 * NOTICE OF LICENSE
 *
 * Licensed under the 3-clause BSD License.
 *
 * This source file is subject to the 3-clause BSD License that is
 * bundled with this package in the LICENSE file.
 *
 * @package    Sentinel
 * @version    2.0.15
 * @author     Cartalyst LLC
 * @license    BSD License (3-clause)
 * @copyright  (c) 2011-2017, Cartalyst LLC
 * @link       http://cartalyst.com
 */

namespace CartalystSentinel;

use 
BadMethodCallException;
use 
CartalystSentinelActivationsActivationRepositoryInterface;
use 
CartalystSentinelCheckpointsCheckpointInterface;
use 
CartalystSentinelPersistencesPersistenceRepositoryInterface;
use 
CartalystSentinelRemindersReminderRepositoryInterface;
use 
CartalystSentinelRolesRoleRepositoryInterface;
use 
CartalystSentinelThrottlingThrottleRepositoryInterface;
use 
CartalystSentinelUsersUserInterface;
use 
CartalystSentinelUsersUserRepositoryInterface;
use 
CartalystSupportTraitsEventTrait;
use 
Closure;
use 
IlluminateContractsEventsDispatcher;
use 
InvalidArgumentException;
use 
RuntimeException;

class 
Sentinel
{
    use 
EventTrait;

    
/**
     * The current cached, logged in user.
     *
     * @var CartalystSentinelUsersUserInterface
     */
    
protected $user;

    
/**
     * The Persistence repository.
     *
     * @var CartalystSentinelPersistencesPersistenceRepositoryInterface
     */
    
protected $persistences;

    
/**
     * The User repository.
     *
     * @var CartalystSentinelUsersUserRepositoryInterface
     */
    
protected $users;

    
/**
     * The Role repository.
     *
     * @var CartalystSentinelRolesRoleRepositoryInterface
     */
    
protected $roles;

    
/**
     * The Activations repository.
     *
     * @var CartalystSentinelActivationsActivationRepositoryInterface
     */
    
protected $activations;

    
/**
     * Cached, available methods on the user repository, used for dynamic calls.
     *
     * @var array
     */
    
protected $userMethods = [];

    
/**
     * Array that holds all the enabled checkpoints.
     *
     * @var array
     */
    
protected $checkpoints = [];

    
/**
     * Flag for the checkpoint status.
     *
     * @var bool
     */
    
protected $checkpointsStatus true;

    
/**
     * The Reminders repository.
     *
     * @var CartalystSentinelRemindersReminderRepositoryInterface
     */
    
protected $reminders;

    
/**
     * The closure to retrieve the request credentials.
     *
     * @var Closure
     */
    
protected $requestCredentials;

    
/**
     * The closure used to create a basic response for failed HTTP auth.
     *
     * @var Closure
     */
    
protected $basicResponse;

    
/**
     * The Throttle repository.
     *
     * @var CartalystSentinelThrottlingThrottleRepositoryInterface
     */
    
protected $throttle;

    
/**
     * Create a new Sentinel instance.
     *
     * @param  CartalystSentinelPersistencesPersistenceRepositoryInterface  $persistence
     * @param  CartalystSentinelUsersUserRepositoryInterface  $users
     * @param  CartalystSentinelRolesRoleRepositoryInterface  $roles
     * @param  CartalystSentinelActivationsActivationRepositoryInterface  $activations
     * @param  IlluminateContractsEventsDispatcher  $dispatcher
     * @return void
     */
    
public function __construct(
        
PersistenceRepositoryInterface $persistences,
        
UserRepositoryInterface $users,
        
RoleRepositoryInterface $roles,
        
ActivationRepositoryInterface $activations,
        
Dispatcher $dispatcher
    
) {
        
$this->persistences $persistences;

        
$this->users $users;

        
$this->roles $roles;

        
$this->activations $activations;

        
$this->dispatcher $dispatcher;
    }

    
/**
     * Registers a user. You may provide a callback to occur before the user
     * is saved, or provide a true boolean as a shortcut to activation.
     *
     * @param  array  $credentials
     * @param  Closure|bool  $callback
     * @return CartalystSentinelUsersUserInteface|bool
     * @throws InvalidArgumentException
     */
    
public function register(array $credentials$callback null)
    {
        if (
$callback !== null && ! $callback instanceof Closure && ! is_bool($callback)) {
            throw new 
InvalidArgumentException('You must provide a closure or a boolean.');
        }

        
$this->fireEvent('sentinel.registering'$credentials);

        
$valid $this->users->validForCreation($credentials);

        if (
$valid === false) {
            return 
false;
        }

        
$argument $callback instanceof Closure $callback null;

        
$user $this->users->create($credentials$argument);

        if (
$callback === true) {
            
$this->activate($user);
        }

        
$this->fireEvent('sentinel.registered'$user);

        return 
$user;
    }

    
/**
     * Registers and activates the user.
     *
     * @param  array  $credentials
     * @return CartalystSentinelUsersUserInteface|bool
     */
    
public function registerAndActivate(array $credentials)
    {
        return 
$this->register($credentialstrue);
    }

    
/**
     * Activates the given user.
     *
     * @param  mixed  $user
     * @return bool
     * @throws InvalidArgumentException
     */
    
public function activate($user)
    {
        if (
is_string($user) || is_array($user)) {
            
$users $this->getUserRepository();

            
$method 'findBy'.(is_string($user) ? 'Id' 'Credentials');

            
$user $users->{$method}($user);
        }

        if (! 
$user instanceof UserInterface) {
            throw new 
InvalidArgumentException('No valid user was provided.');
        }

        
$this->fireEvent('sentinel.activating'$user);

        
$activations $this->getActivationRepository();

        
$activation $activations->create($user);

        
$this->fireEvent('sentinel.activated', [ $user$activation ]);

        return 
$activations->complete($user$activation->getCode());
    }

    
/**
     * Checks to see if a user is logged in.
     *
     * @return CartalystSentinelUsersUserInterface|bool
     */
    
public function check()
    {
        if (
$this->user !== null) {
            return 
$this->user;
        }

        if (! 
$code $this->persistences->check()) {
            return 
false;
        }

        if (! 
$user $this->persistences->findUserByPersistenceCode($code)) {
            return 
false;
        }

        if (! 
$this->cycleCheckpoints('check'$user)) {
            return 
false;
        }

        return 
$this->user $user;
    }

    
/**
     * Checks to see if a user is logged in, bypassing checkpoints
     *
     * @return CartalystSentinelUsersUserInterface|bool
     */
    
public function forceCheck()
    {
        return 
$this->bypassCheckpoints(function ($sentinel) {
            return 
$sentinel->check();
        });
    }

    
/**
     * Checks if we are currently a guest.
     *
     * @return bool
     */
    
public function guest()
    {
        return ! 
$this->check();
    }

    
/**
     * Authenticates a user, with "remember" flag.
     *
     * @param  CartalystSentinelUsersUserInterface|array  $credentials
     * @param  bool  $remember
     * @param  bool  $login
     * @return CartalystSentinelUsersUserInterface|bool
     */
    
public function authenticate($credentials$remember false$login true)
    {
        
$response $this->fireEvent('sentinel.authenticating'$credentialstrue);

        if (
$response === false) {
            return 
false;
        }

        if (
$credentials instanceof UserInterface) {
            
$user $credentials;
        } else {
            
$user $this->users->findByCredentials($credentials);

            
$valid $user !== null $this->users->validateCredentials($user$credentials) : false;

            if (
$user === null || $valid === false) {
                
$this->cycleCheckpoints('fail'$userfalse);

                return 
false;
            }
        }

        if (! 
$this->cycleCheckpoints('login'$user)) {
            return 
false;
        }

        if (
$login === true) {
            
$method $remember === true 'loginAndRemember' 'login';

            if (! 
$user $this->{$method}($user)) {
                return 
false;
            }
        }

        
$this->fireEvent('sentinel.authenticated'$user);

        return 
$this->user $user;
    }

    
/**
     * Authenticates a user, with the "remember" flag.
     *
     * @param  CartalystSentinelUsersUserInterface|array  $credentials
     * @return CartalystSentinelUsersUserInterface|bool
     */
    
public function authenticateAndRemember($credentials)
    {
        return 
$this->authenticate($credentialstrue);
    }

    
/**
     * Forces an authentication to bypass checkpoints.
     *
     * @param  CartalystSentinelUsersUserInterface|array  $credentials
     * @param  bool  $remember
     * @return CartalystSentinelUsersUserInterface|bool
     */
    
public function forceAuthenticate($credentials$remember false)
    {
        return 
$this->bypassCheckpoints(function ($sentinel) use ($credentials$remember) {
            return 
$sentinel->authenticate($credentials$remember);
        });
    }

    
/**
     * Forces an authentication to bypass checkpoints, with the "remember" flag.
     *
     * @param  CartalystSentinelUsersUserInterface|array  $credentials
     * @return CartalystSentinelUsersUserInterface|bool
     */
    
public function forceAuthenticateAndRemember($credentials)
    {
        return 
$this->forceAuthenticate($credentialstrue);
    }

    
/**
     * Attempt a stateless authentication.
     *
     * @param  CartalystSentinelUsersUserInterface|array  $credentials
     * @return CartalystSentinelUsersUserInterface|bool
     */
    
public function stateless($credentials)
    {
        return 
$this->authenticate($credentialsfalsefalse);
    }

    
/**
     * Attempt to authenticate using HTTP Basic Auth.
     *
     * @return mixed
     */
    
public function basic()
    {
        
$credentials $this->getRequestCredentials();

        
// We don't really want to add a throttling record for the
        // first failed login attempt, which actually occurs when
        // the user first hits a protected route.
        
if ($credentials === null) {
            return 
$this->getBasicResponse();
        }

        
$user $this->stateless($credentials);

        if (
$user) {
            return;
        }

        return 
$this->getBasicResponse();
    }

    
/**
     * Returns the request credentials.
     *
     * @return array
     */
    
public function getRequestCredentials()
    {
        if (
$this->requestCredentials === null) {
            
$this->requestCredentials = function () {
                
$credentials = [];

                if (isset(
$_SERVER['PHP_AUTH_USER'])) {
                    
$credentials['login'] = $_SERVER['PHP_AUTH_USER'];
                }

                if (isset(
$_SERVER['PHP_AUTH_PW'])) {
                    
$credentials['password'] = $_SERVER['PHP_AUTH_PW'];
                }

                if (
count($credentials) > 0) {
                    return 
$credentials;
                }
            };
        }

        
$credentials $this->requestCredentials;

        return 
$credentials();
    }

    
/**
     * Sets the closure which resolves the request credentials.
     *
     * @param  Closure  $requestCredentials
     * @return void
     */
    
public function setRequestCredentials(Closure $requestCredentials)
    {
        
$this->requestCredentials $requestCredentials;
    }

    
/**
     * Sends a response when HTTP basic authentication fails.
     *
     * @return mixed
     * @throws RuntimeException
     */
    
public function getBasicResponse()
    {
        
// Default the basic response
        
if ($this->basicResponse === null) {
            
$this->basicResponse = function () {
                if (
headers_sent()) {
                    throw new 
RuntimeException('Attempting basic auth after headers have already been sent.');
                }

                
header('WWW-Authenticate: Basic');
                
header('HTTP/1.0 401 Unauthorized');

                echo 
'Invalid credentials.';
                exit;
            };
        }

        
$response $this->basicResponse;

        return 
$response();
    }

    
/**
     * Sets the callback which creates a basic response.
     *
     * @param  Closure  $basicResonse
     * @return void
     */
    
public function creatingBasicResponse(Closure $basicResponse)
    {
        
$this->basicResponse $basicResponse;
    }

    
/**
     * Persists a login for the given user.
     *
     * @param  CartalystSentinelUsersUserInterface  $user
     * @param  bool  $remember
     * @return CartalystSentinelUsersUserInterface|bool
     */
    
public function login(UserInterface $user$remember false)
    {
        
$method $remember === true 'persistAndRemember' 'persist';

        
$this->persistences->{$method}($user);

        
$response $this->users->recordLogin($user);

        if (
$response === false) {
            return 
false;
        }

        return 
$this->user $user;
    }

    
/**
     * Persists a login for the given user, with the "remember" flag.
     *
     * @param  CartalystSentinelUsersUserInterface  $user
     * @return CartalystSentinelUsersUserInterface|bool
     */
    
public function loginAndRemember(UserInterface $user)
    {
        return 
$this->login($usertrue);
    }

    
/**
     * Logs the current user out.
     *
     * @param  CartalystSentinelUsersUserInterface  $user
     * @param  bool  $everywhere
     * @return bool
     */
    
public function logout(UserInterface $user null$everywhere false)
    {
        
$currentUser $this->check();

        if (
$user && $user !== $currentUser) {
            
$this->persistences->flush($userfalse);

            return 
true;
        }

        
$user $user ?: $currentUser;

        if (
$user === false) {
            return 
true;
        }

        
$method $everywhere === true 'flush' 'forget';

        
$this->persistences->{$method}($user);

        
$this->user null;

        return 
$this->users->recordLogout($user);
    }

    
/**
     * Pass a closure to Sentinel to bypass checkpoints.
     *
     * @param  Closure  $callback
     * @param  array  $checkpoints
     * @return mixed
     */
    
public function bypassCheckpoints(Closure $callback$checkpoints = [])
    {
        
$originalCheckpoints $this->checkpoints;

        
$activeCheckpoints = [];

        foreach (
array_keys($originalCheckpoints) as $checkpoint) {
            if (
$checkpoints && ! in_array($checkpoint$checkpoints)) {
                
$activeCheckpoints[$checkpoint] = $originalCheckpoints[$checkpoint];
            }
        }

        
// Temporarily replace the registered checkpoints
        
$this->checkpoints $activeCheckpoints;

        
// Fire the callback
        
$result $callback($this);

        
// Reset checkpoints
        
$this->checkpoints $originalCheckpoints;

        return 
$result;
    }

    
/**
     * Checks if checkpoints are enabled.
     *
     * @return bool
     */
    
public function checkpointsStatus()
    {
        return 
$this->checkpointsStatus;
    }

    
/**
     * Enables checkpoints.
     *
     * @return void
     */
    
public function enableCheckpoints()
    {
        
$this->checkpointsStatus true;
    }

    
/**
     * Disables checkpoints.
     *
     * @return void
     */
    
public function disableCheckpoints()
    {
        
$this->checkpointsStatus false;
    }

    
/**
     * Add a new checkpoint to Sentinel.
     *
     * @param  string  $key
     * @param  CartalystSentinelCheckpointsCheckpointInterface  $checkpoint
     * @return void
     */
    
public function addCheckpoint($keyCheckpointInterface $checkpoint)
    {
        
$this->checkpoints[$key] = $checkpoint;
    }

    
/**
     * Removes a checkpoint.
     *
     * @param  string  $key
     * @return void
     */
    
public function removeCheckpoint($key)
    {
        if (isset(
$this->checkpoints[$key])) {
            unset(
$this->checkpoints[$key]);
        }
    }

    
/**
     * Removes the given checkpoints.
     *
     * @param  array  $checkpoints
     * @return void
     */
    
public function removeCheckpoints(array $checkpoints = [])
    {
        foreach (
$checkpoints as $checkpoint) {
            
$this->removeCheckpoint($checkpoint);
        }
    }

    
/**
     * Cycles through all the registered checkpoints for a user. Checkpoints
     * may throw their own exceptions, however, if just one returns false,
     * the cycle fails.
     *
     * @param  string  $method
     * @param  CartalystSentinelUsersUserInterface  $user
     * @param  bool  $halt
     * @return bool
     */
    
protected function cycleCheckpoints($methodUserInterface $user null$halt true)
    {
        if (! 
$this->checkpointsStatus) {
            return 
true;
        }

        foreach (
$this->checkpoints as $checkpoint) {
            
$response $checkpoint->{$method}($user);

            if (
$response === false && $halt === true) {
                return 
false;
            }
        }

        return 
true;
    }

    
/**
     * Returns the currently logged in user, lazily checking for it.
     *
     * @param  bool  $check
     * @return CartalystSentinelUsersUserInterface
     */
    
public function getUser($check true)
    {
        if (
$check === true && $this->user === null) {
            
$this->check();
        }

        return 
$this->user;
    }

    
/**
     * Sets the user associated with Sentinel (does not log in).
     *
     * @param  CartalystSentinelUsersUserInterface  $user
     * @return void
     */
    
public function setUser(UserInterface $user)
    {
        
$this->user $user;
    }

    
/**
     * Returns the user repository.
     *
     * @return CartalystSentinelUsersUserRepositoryInterface
     */
    
public function getUserRepository()
    {
        return 
$this->users;
    }

    
/**
     * Sets the user repository.
     *
     * @param  CartalystSentinelUsersUserRepositoryInterface  $users
     * @return void
     */
    
public function setUserRepository(UserRepositoryInterface $users)
    {
        
$this->users $users;

        
$this->userMethods = [];
    }

    
/**
     * Returns the role repository.
     *
     * @return CartalystSentinelRolesRoleRepositoryInterface
     */
    
public function getRoleRepository()
    {
        return 
$this->roles;
    }

    
/**
     * Sets the role repository.
     *
     * @param  CartalystSentinelRolesRoleRepositoryInterface  $roles
     * @return void
     */
    
public function setRoleRepository(RoleRepositoryInterface $roles)
    {
        
$this->roles $roles;
    }

    
/**
     * Returns the persistences repository.
     *
     * @return CartalystSentinelPersistencesPersistenceRepositoryInterface
     */
    
public function getPersistenceRepository()
    {
        return 
$this->persistences;
    }

    
/**
     * Sets the persistences repository.
     *
     * @param  CartalystSentinelPersistencesPersistenceRepositoryInterface  $persistences
     * @return void
     */
    
public function setPersistenceRepository(PersistenceRepositoryInterface $persistences)
    {
        
$this->persistences $persistences;
    }

    
/**
     * Returns the activations repository.
     *
     * @return CartalystSentinelActivationsActivationRepositoryInterface
     */
    
public function getActivationRepository()
    {
        return 
$this->activations;
    }

    
/**
     * Sets the activations repository.
     *
     * @param  CartalystSentinelActivationsActivationRepositoryInterface  $activations
     * @return void
     */
    
public function setActivationRepository(ActivationRepositoryInterface $activations)
    {
        
$this->activations $activations;
    }

    
/**
     * Returns the reminders repository.
     *
     * @return CartalystSentinelRemindersReminderRepositoryInterface
     */
    
public function getReminderRepository()
    {
        return 
$this->reminders;
    }

    
/**
     * Sets the reminders repository.
     *
     * @param  CartalystSentinelRemindersReminderRepositoryInterface  $reminders
     * @return void
     */
    
public function setReminderRepository(ReminderRepositoryInterface $reminders)
    {
        
$this->reminders $reminders;
    }

    
/**
     * Returns the throttle repository.
     *
     * @return CartalystSentinelThrottlingThrottleRepositoryInterface
     */
    
public function getThrottleRepository()
    {
        return 
$this->throttle;
    }

    
/**
     * Sets the throttle repository.
     *
     * @param  CartalystSentinelThrottlingThrottleRepositoryInterface  $throttle
     * @return void
     */
    
public function setThrottleRepository(ThrottleRepositoryInterface $throttle)
    {
        
$this->throttle $throttle;
    }

    
/**
     * Returns all accessible methods on the associated user repository.
     *
     * @return array
     */
    
protected function getUserMethods()
    {
        if (empty(
$this->userMethods)) {
            
$users $this->getUserRepository();

            
$methods get_class_methods($users);

            
$this->userMethods array_diff($methods, ['__construct']);
        }

        return 
$this->userMethods;
    }

    
/**
     * Dynamically pass missing methods to Sentinel.
     *
     * @param  string  $method
     * @param  array  $parameters
     * @return mixed
     * @throws BadMethodCallException
     */
    
public function __call($method$parameters)
    {
        
$methods $this->getUserMethods();

        if (
in_array($method$methods)) {
            
$users $this->getUserRepository();

            return 
call_user_func_array([$users$method], $parameters);
        }

        if (
starts_with($method'findUserBy')) {
            
$user $this->getUserRepository();

            
$method 'findBy'.substr($method10);

            return 
call_user_func_array([$user$method], $parameters);
        }

        if (
starts_with($method'findRoleBy')) {
            
$roles $this->getRoleRepository();

            
$method 'findBy'.substr($method10);

            return 
call_user_func_array([$roles$method], $parameters);
        }

        
$methods = ['getRoles''inRole''hasAccess''hasAnyAccess'];

        
$className get_class($this);

        if (
in_array($method$methods)) {
            
$user $this->getUser();

            if (
$user === null) {
                throw new 
BadMethodCallException("Method {$className}::{$method}() can only be called if a user is logged in.");
            }

            return 
call_user_func_array([$user$method], $parameters);
        }

        throw new 
BadMethodCallException("Call to undefined method {$className}::{$method}()");
    }
}
Онлайн: 0
Реклама