Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
29 / 29
100.00% covered (success)
100.00%
5 / 5
CRAP
100.00% covered (success)
100.00%
1 / 1
AbstractTokenRepository
100.00% covered (success)
100.00%
29 / 29
100.00% covered (success)
100.00%
5 / 5
11
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 persistNew
100.00% covered (success)
100.00%
21 / 21
100.00% covered (success)
100.00%
1 / 1
5
 revoke
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 isRevoked
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
2
 getNew
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3/**
4 * OAuth2 token repository base class.
5 *
6 * PHP version 8
7 *
8 * Copyright (C) The National Library of Finland 2022-2024.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2,
12 * as published by the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
22 *
23 * @category VuFind
24 * @package  OAuth2
25 * @author   Ere Maijala <ere.maijala@helsinki.fi>
26 * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
27 * @link     https://vufind.org Main Site
28 */
29
30namespace VuFind\OAuth2\Repository;
31
32use League\OAuth2\Server\Entities\RefreshTokenEntityInterface;
33use VuFind\Auth\InvalidArgumentException;
34use VuFind\Db\Service\AccessTokenServiceInterface;
35use VuFind\Db\Service\UserServiceInterface;
36
37use function is_callable;
38
39/**
40 * OAuth2 token repository base class.
41 *
42 * @category VuFind
43 * @package  OAuth2
44 * @author   Ere Maijala <ere.maijala@helsinki.fi>
45 * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
46 * @link     https://vufind.org Main Site
47 */
48class AbstractTokenRepository
49{
50    /**
51     * Constructor
52     *
53     * @param string                      $tokenType          Token type
54     * @param string                      $entityClass        Entity class name
55     * @param array                       $oauth2Config       OAuth2 configuration
56     * @param AccessTokenServiceInterface $accessTokenService Access token service
57     * @param UserServiceInterface        $userService        User service
58     */
59    public function __construct(
60        protected string $tokenType,
61        protected string $entityClass,
62        protected array $oauth2Config,
63        protected AccessTokenServiceInterface $accessTokenService,
64        protected UserServiceInterface $userService
65    ) {
66    }
67
68    /**
69     * Persist a token in the database
70     *
71     * @param Object $token Token
72     *
73     * @throws InvalidArgumentException
74     * @return void
75     */
76    public function persistNew($token)
77    {
78        if (!is_a($token, $this->entityClass)) {
79            throw new \InvalidArgumentException(
80                $token::class . ' is not ' . $this->entityClass
81            );
82        }
83
84        $row = $this->accessTokenService->getByIdAndType(
85            $token->getIdentifier(),
86            $this->tokenType
87        );
88        $row->setData(json_encode($token));
89        $userIdentifier = null;
90        if ($token instanceof RefreshTokenEntityInterface) {
91            $accessToken = $token->getAccessToken();
92            $userIdentifier = $accessToken->getUserIdentifier();
93        } elseif (is_callable([$token, 'getUserIdentifier'])) {
94            $userIdentifier = $token->getUserIdentifier();
95        }
96        if ($userIdentifier) {
97            // Drop nonce from user id:
98            [$userIdentifier] = explode('|', $userIdentifier);
99        }
100        $userIdentifierField = $this->oauth2Config['Server']['userIdentifierField'] ?? 'id';
101        $user = $this->userService->getUserByField($userIdentifierField, $userIdentifier);
102        $row->setUser($user);
103        $this->accessTokenService->persistEntity($row);
104    }
105
106    /**
107     * Revoke a token
108     *
109     * @param string $tokenId Token ID
110     *
111     * @return void
112     */
113    public function revoke($tokenId)
114    {
115        $token = $this->accessTokenService->getByIdAndType($tokenId, $this->tokenType, false);
116        if ($token) {
117            $token->setRevoked(true);
118            $this->accessTokenService->persistEntity($token);
119        }
120    }
121
122    /**
123     * Check if a token is revoked
124     *
125     * @param string $tokenId Token ID
126     *
127     * @return bool
128     */
129    public function isRevoked($tokenId)
130    {
131        $token = $this->accessTokenService->getByIdAndType($tokenId, $this->tokenType, false);
132        return $token ? $token->isRevoked() : true;
133    }
134
135    /**
136     * Get a new token
137     *
138     * @return Object
139     */
140    public function getNew()
141    {
142        return new $this->entityClass();
143    }
144}