• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

daycry / auth / 10060982055

23 Jul 2024 02:35PM UTC coverage: 59.361% (+0.09%) from 59.271%
10060982055

push

github

web-flow
Merge pull request #17 from daycry/development

Fixes

33 of 86 new or added lines in 29 files covered. (38.37%)

2 existing lines in 2 files now uncovered.

1858 of 3130 relevant lines covered (59.36%)

22.22 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/Traits/BaseControllerTrait.php
1
<?php
2

3
declare(strict_types=1);
4

5
/**
6
 * This file is part of Daycry Auth.
7
 *
8
 * (c) Daycry <daycry9@proton.me>
9
 *
10
 * For the full copyright and license information, please view
11
 * the LICENSE file that was distributed with this source code.
12
 */
13

14
namespace Daycry\Auth\Traits;
15

16
use CodeIgniter\Exceptions\PageNotFoundException;
17
use CodeIgniter\HTTP\RequestInterface;
18
use CodeIgniter\HTTP\ResponseInterface;
19
use CodeIgniter\Router\Router;
20
use Config\Mimes;
21
use Config\Services;
22
use Daycry\Auth\Interfaces\AuthController;
23
use Daycry\Auth\Libraries\Logger;
24
use Daycry\Auth\Libraries\Utils;
25
use Daycry\Auth\Models\AttemptModel;
26
use Daycry\Auth\Validators\AttemptValidator;
27
use Daycry\Encryption\Encryption;
28
use Daycry\Exceptions\Interfaces\BaseExceptionInterface;
29
use Psr\Log\LoggerInterface;
30
use ReflectionClass;
31
use ReflectionProperty;
32

33
trait BaseControllerTrait
34
{
35
    use Validation;
36

37
    protected Router $router;
38
    protected ?Logger $_logger = null;
39
    protected Encryption $encryption;
40

41
    /**
42
     * The authorization Request
43
     */
44
    private bool $_isRequestAuthorized = true;
45

46
    protected array $args;
47
    protected mixed $content = null;
48

49
    /**
50
     * Extend this function to apply additional checking early on in the process.
51
     */
52
    protected function earlyChecks(): void
53
    {
54
    }
×
55

56
    public function initController(RequestInterface $request, ResponseInterface $response, LoggerInterface $logger): void
57
    {
58
        helper(['security', 'auth']);
×
59

60
        $this->_logger    = Services::log();
×
61
        $this->router     = Services::router();
×
62
        $this->encryption = new Encryption();
×
63

64
        parent::initController($request, $response, $logger);
×
65

66
        if (method_exists($this, 'setFormat')) {
×
67
            $output = $this->request->negotiate('media', setting('Format.supportedResponseFormats'));
×
68
            $output = Mimes::guessExtensionFromType($output);
×
69
            $this->setFormat($output);
×
70
        }
71

72
        $this->args    = Utils::getAllParams();
×
73
        $this->content = (! empty($this->args['body'])) ? $this->args['body'] : null;
×
74

75
        // Extend this function to apply additional checking early on in the process
76
        $this->earlyChecks();
×
77
    }
78

79
    /**
80
     * De-constructor.
81
     *
82
     * @return void
83
     */
84
    public function __destruct()
85
    {
86
        if ($this->request) {
×
87
            $this->_logRequest();
×
88

89
            if (service('settings')->get('Auth.enableInvalidAttempts') === true) {
×
90
                $attemptModel = new AttemptModel();
×
91
                $attempt      = $attemptModel->where('ip_address', $this->request->getIPAddress())->first();
×
92

93
                if ($this->_isRequestAuthorized === false) {
×
94
                    if ($attempt === null) {
×
95
                        $attempt = [
×
NEW
96
                            'user_id'      => (auth()->user() !== null) ? auth()->user()->id : null,
×
97
                            'ip_address'   => $this->request->getIPAddress(),
×
98
                            'attempts'     => 1,
×
99
                            'hour_started' => time(),
×
100
                        ];
×
UNCOV
101
                        $attemptModel->save($attempt);
×
NEW
102
                    } elseif ($attempt->attempts < service('settings')->get('Auth.maxAttempts')) {
×
NEW
103
                        $attempt->attempts++;
×
NEW
104
                        $attemptModel->save($attempt);
×
105
                    }
106
                }
107
            }
108
        }
109

110
        // reset previous validation at end
111
        if ($this->validator) {
×
112
            $this->validator->reset();
×
113
        }
114
    }
115

116
    /**
117
     * Add the request to the log table.
118
     */
119
    protected function _logRequest(): void
120
    {
121
        $reflectionClass = new ReflectionClass($this->router->controllerName());
×
122

123
        if ($reflectionClass->implementsInterface(AuthController::class)) {
×
124
            $this->_logger->setLogAuthorized(false);
×
125
        }
126

127
        $this->_logger
×
128
            ->setAuthorized($this->_isRequestAuthorized)
×
129
            ->setResponseCode($this->response->getStatusCode())
×
130
            ->save();
×
131
    }
132

133
    protected function getToken(): array
134
    {
135
        return ['name' => csrf_token(), 'hash' => csrf_hash()];
×
136
    }
137

138
    /**
139
     * Requests are not made to methods directly, the request will be for
140
     * an "object". This simply maps the object and method to the correct
141
     * Controller method.
142
     *
143
     * @param array $params The params passed to the controller method
144
     *
145
     * @throws BaseExceptionInterface
146
     */
147
    public function _remap(string $method, ...$params)
148
    {
149
        try {
150
            if (! method_exists($this, $method)) {
×
151
                throw PageNotFoundException::forPageNotFound();
×
152
            }
153

154
            if (service('settings')->get('Auth.enableInvalidAttempts') === true) {
×
155
                AttemptValidator::check($this->response);
×
156
            }
157

158
            $data = $this->{$method}(...$params);
×
159

160
            if ($data instanceof ResponseInterface) {
×
161
                return $data;
×
162
            }
163

164
            if ($this->request->isAJAX() && (is_array($data) || is_object($data))) {
×
165
                return $this->response->setJSON($data);
×
166
            }
167

168
            return $this->response->setBody($data);
×
169
        } catch (BaseExceptionInterface $ex) {
×
170
            if (property_exists($ex, 'authorized')) {
×
171
                $this->_isRequestAuthorized = (new ReflectionProperty($ex, 'authorized'))->getValue();
×
172
            }
173

174
            $message = ($this->validator && $this->validator->getErrors()) ? $this->validator->getErrors() : $ex->getMessage();
×
175
            $code    = ($ex->getCode()) ?: 400;
×
176

177
            if (method_exists($this, 'fail')) {
×
178
                return $this->fail($message, $code);
×
179
            }
180

181
            if ($this->request->isAJAX()) {
×
182
                return $this->response->setStatusCode($code)->setJSON(
×
183
                    ['status' => false, 'error' => $message, 'token' => $this->getToken()]
×
184
                );
×
185
            }
186

187
            throw $ex;
×
188
        }
189
    }
190
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc