<commit_before><?php

namespace Beskhue\CookieTokenAuth\Auth;

use Cake\Auth\BaseAuthenticate;
use Cake\Network\Request;
use Cake\Network\Response;
use Cake\Auth\DefaultPasswordHasher;

class CookieTokenAuthenticate extends BaseAuthenticate
{
    public $components = ['Cookie'];

    /**
     * Authenticate a user based on the request information.
     *
     * @param \Cake\Network\Request  $request  Request to get authentication information from.
     * @param \Cake\Network\Response $response A response object that can have headers added.
     *
     * @return mixed Either false on failure, or an array of user data on success.
     */
    public function authenticate(Request $request, Response $response)
    {
        return $this->getUser($request);
    }

    /**
     * Get a user based on information in the request. Primarily used by stateless authentication
     * systems like basic and digest auth.
     *
     * @param \Cake\Network\Request $request Request object.
     *
     * @return mixed Either false or an array of user information
     */
    public function getUser(Request $request)
    {
        return $this->_getUser();
    }

    /**
     * Get a user based on cookie data.
     *
     * @return mixed Either false or an array of user information
     */
    private function _getUser()
    {
        $cookieTokenComponent = $this->_registry->load('Beskhue/CookieTokenAuth.CookieToken');
        $flashComponent = $this->_registry->load('Flash');
        $authTokens = \Cake\ORM\TableRegistry::get('Beskhue/CookieTokenAuth.AuthTokens');

        $authTokens->removeExpired();

        $data = $this->getCookieData();
        if (!$data) {
            return false;
        }

        $series = $data['series'];
        $token = $data['token'];

        $tokenEntity = $authTokens->findBySeries($series)->contain('Users')->first();
        if (!$tokenEntity) {
            // The series was not found. 
            $cookieTokenComponent->removeCookie();

            return false;
        }

        $user = $tokenEntity->user;

        if (!(new DefaultPasswordHasher())->check($token, $tokenEntity->token)) {
            // Tokens don't match. Probably attempted theft!
            $flashComponent->error('A session token mismatch was detected. You have been logged out.');
            $authTokens->deleteAllByUser($user);
            $cookieTokenComponent->removeCookie();

            return false;
        }

        // Generate new token
        $cookieTokenComponent->setCookie($user, $tokenEntity);

        return $this->_findUser($user->username);
    }

    /**
     * Called when the user logs out. Remove the token from the database and 
     * delete the cookie.
     * 
     * @param \Cake\Event\Event $event The logout event.
     * @param array             $user  The user data.
     */
    public function logout(\Cake\Event\Event $event, array $user)
    {
        $cookieTokenComponent = $this->_registry->load('Beskhue/CookieTokenAuth.CookieToken');
        $authTokens = \Cake\ORM\TableRegistry::get('Beskhue/CookieTokenAuth.AuthTokens');

        // Check if cookie is valid
        if ($this->_getUser()) {
            // Remove token from database
            $data = $this->getCookieData();
            if ($data) {
                $series = $data['series'];

                $tokenEntity = $authTokens->findBySeries($series)->first();
                $authTokens->delete($tokenEntity);
            }
        }

        // Remove cookie
        $cookieTokenComponent->removeCookie();
    }

    /**
     * Get and validate the cookie data.
     * 
     * @return mixed Either false or an array of cookie token data.
     */
    private function getCookieData()<commit_msg>Improve coding style.<commit_after><?php

namespace Beskhue\CookieTokenAuth\Auth;

use Cake\Auth\BaseAuthenticate;
use Cake\Network\Request;
use Cake\Network\Response;
use Cake\Auth\DefaultPasswordHasher;

class CookieTokenAuthenticate extends BaseAuthenticate
{
    public $components = ['Cookie'];

    /**
     * Authenticate a user based on the request information.
     *
     * @param \Cake\Network\Request  $request  Request to get authentication information from.
     * @param \Cake\Network\Response $response A response object that can have headers added.
     *
     * @return mixed Either false on failure, or an array of user data on success.
     */
    public function authenticate(Request $request, Response $response)
    {
        return $this->getUser($request);
    }

    /**
     * Get a user based on information in the request. Primarily used by stateless authentication
     * systems like basic and digest auth.
     *
     * @param \Cake\Network\Request $request Request object.
     *
     * @return mixed Either false or an array of user information
     */
    public function getUser(Request $request)
    {
        return $this->getUserFromCookieData();
    }

    /**
     * Get a user based on cookie data.
     *
     * @return mixed Either false or an array of user information
     */
    private function getUserFromCookieData()
    {
        $cookieTokenComponent = $this->_registry->load('Beskhue/CookieTokenAuth.CookieToken');
        $flashComponent = $this->_registry->load('Flash');
        $authTokens = \Cake\ORM\TableRegistry::get('Beskhue/CookieTokenAuth.AuthTokens');

        $authTokens->removeExpired();

        $data = $this->getCookieData();
        if (!$data) {
            return false;
        }

        $series = $data['series'];
        $token = $data['token'];

        $tokenEntity = $authTokens->findBySeries($series)->contain('Users')->first();
        if (!$tokenEntity) {
            // The series was not found. 
            $cookieTokenComponent->removeCookie();

            return false;
        }

        $user = $tokenEntity->user;

        if (!(new DefaultPasswordHasher())->check($token, $tokenEntity->token)) {
            // Tokens don't match. Probably attempted theft!
            $flashComponent->error('A session token mismatch was detected. You have been logged out.');
            $authTokens->deleteAllByUser($user);
            $cookieTokenComponent->removeCookie();

            return false;
        }

        // Generate new token
        $cookieTokenComponent->setCookie($user, $tokenEntity);

        return $this->_findUser($user->username);
    }

    /**
     * Called when the user logs out. Remove the token from the database and 
     * delete the cookie.
     * 
     * @param \Cake\Event\Event $event The logout event.
     * @param array             $user  The user data.
     */
    public function logout(\Cake\Event\Event $event, array $user)
    {
        $cookieTokenComponent = $this->_registry->load('Beskhue/CookieTokenAuth.CookieToken');
        $authTokens = \Cake\ORM\TableRegistry::get('Beskhue/CookieTokenAuth.AuthTokens');

        // Check if cookie is valid
        if ($this->getUserFromCookieData()) {
            // Remove token from database
            $data = $this->getCookieData();
            if ($data) {
                $series = $data['series'];

                $tokenEntity = $authTokens->findBySeries($series)->first();
                $authTokens->delete($tokenEntity);
            }
        }

        // Remove cookie
        $cookieTokenComponent->removeCookie();
    }

    /**
     * Get and validate the cookie data.
     * 
     * @return mixed Either false or an array of cookie token data.
     */
    private function getCookieData()
{'fraction_non_alphanumeric': 0.11546144626448263, 'fraction_numerical': 0.0, 'mean_word_length': 2.3230088495575223, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 61, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5199753', 'n_tokens_mistral': 2019, 'n_tokens_neox': 1973, 'n_words': 547}