Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 25
0.00% covered (danger)
0.00%
0 / 1
CRAP
0.00% covered (danger)
0.00%
0 / 1
ApiKeyMapper
0.00% covered (danger)
0.00%
0 / 25
0.00% covered (danger)
0.00%
0 / 1
56
0.00% covered (danger)
0.00%
0 / 1
 authenticateApiKey
0.00% covered (danger)
0.00%
0 / 25
0.00% covered (danger)
0.00%
0 / 1
56
1<?php
2/**
3 * Jingga
4 *
5 * PHP Version 8.1
6 *
7 * @package   Modules\Admin\Models
8 * @copyright Dennis Eichhorn
9 * @license   OMS License 2.0
10 * @version   1.0.0
11 * @link      https://jingga.app
12 */
13declare(strict_types=1);
14
15namespace Modules\Admin\Models;
16
17use phpOMS\Account\AccountStatus;
18use phpOMS\Auth\LoginReturnType;
19use phpOMS\DataStorage\Database\Mapper\DataMapperFactory;
20use phpOMS\DataStorage\Database\Query\Builder;
21
22/**
23 * Account mapper class.
24 *
25 * @package Modules\Admin\Models
26 * @license OMS License 2.0
27 * @link    https://jingga.app
28 * @since   1.0.0
29 *
30 * @template T of ApiKey
31 * @extends DataMapperFactory<T>
32 */
33class ApiKeyMapper extends DataMapperFactory
34{
35    /**
36     * Columns.
37     *
38     * @var array<string, array{name:string, type:string, internal:string, autocomplete?:bool, readonly?:bool, writeonly?:bool, annotations?:array}>
39     * @since 1.0.0
40     */
41    public const COLUMNS = [
42        'account_api_id'         => ['name' => 'account_api_id',           'type' => 'int',      'internal' => 'id'],
43        'account_api_key'        => ['name' => 'account_api_key',       'type' => 'string',      'internal' => 'key'],
44        'account_api_status'     => ['name' => 'account_api_status',       'type' => 'int',      'internal' => 'status'],
45        'account_api_account'    => ['name' => 'account_api_account',       'type' => 'int',      'internal' => 'account'],
46        'account_api_created_at' => ['name' => 'account_api_created_at',       'type' => 'DateTime',      'internal' => 'createdAt'],
47    ];
48
49    /**
50     * Model to use by the mapper.
51     *
52     * @var class-string<T>
53     * @since 1.0.0
54     */
55    public const MODEL = ApiKey::class;
56
57    /**
58     * Primary table.
59     *
60     * @var string
61     * @since 1.0.0
62     */
63    public const TABLE = 'account_api';
64
65    /**
66     * Primary field name.
67     *
68     * @var string
69     * @since 1.0.0
70     */
71    public const PRIMARYFIELD = 'account_api_id';
72
73    /**
74     * Created at column
75     *
76     * @var string
77     * @since 1.0.0
78     */
79    public const CREATED_AT = 'account_api_created_at';
80
81    /**
82     * Authenticates a user based on an api key
83     *
84     * @param string $api Api key
85     *
86     * @return int
87     *
88     * @since 1.0.0
89     */
90    public static function authenticateApiKey(string $api) : int
91    {
92        if (empty($api)) {
93            return LoginReturnType::WRONG_PASSWORD;
94        }
95
96        try {
97            $result = null;
98
99            $query  = new Builder(self::$db);
100            $result = $query->select('account.account_id', 'account.account_status')
101                ->from('account')
102                ->innerJoin('account_api')->on('account.account_id', '=', 'account_api.account_api_account')
103                ->where('account_api.account_api_key', '=', $api)
104                ->execute()
105                ?->fetchAll();
106
107            if ($result === null || !isset($result[0])) {
108                return LoginReturnType::WRONG_USERNAME; // wrong api key
109            }
110
111            $result = $result[0];
112
113            if ($result['account_status'] !== AccountStatus::ACTIVE) {
114                return LoginReturnType::INACTIVE;
115            }
116
117            if (empty($result['account_password'])) {
118                return LoginReturnType::EMPTY_PASSWORD;
119            }
120
121            $query->update('account')
122                ->set([
123                    'account_lactive' => new \DateTime('now'),
124                ])
125                ->where('account_id', '=', (int) $result['account_id'])
126                ->execute();
127
128            return (int) $result['account_id'];
129        } catch (\Exception $_) {
130            return LoginReturnType::FAILURE; // @codeCoverageIgnore
131        }
132    }
133}