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

daycry / auth / 16049672150

03 Jul 2025 11:51AM UTC coverage: 59.854% (+0.06%) from 59.79%
16049672150

push

github

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

Fixes & perfomance

13 of 49 new or added lines in 5 files covered. (26.53%)

2 existing lines in 1 file now uncovered.

1883 of 3146 relevant lines covered (59.85%)

22.26 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\ExceptionInterface;
17
use CodeIgniter\Exceptions\PageNotFoundException;
18
use CodeIgniter\HTTP\RequestInterface;
19
use CodeIgniter\HTTP\ResponseInterface;
20
use CodeIgniter\Router\Router;
21
use Config\Mimes;
22
use Config\Services;
23
use Daycry\Auth\Interfaces\AuthController;
24
use Daycry\Auth\Libraries\Logger;
25
use Daycry\Auth\Libraries\Utils;
26
use Daycry\Auth\Models\AttemptModel;
27
use Daycry\Auth\Validators\AttemptValidator;
28
use Daycry\Encryption\Encryption;
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
    private bool $_isRequestAuthorized = true;
41
    protected array $args;
42
    protected mixed $content = null;
43

44
    protected function earlyChecks(): void
45
    {
46
    }
×
47

48
    public function initController(RequestInterface $request, ResponseInterface $response, LoggerInterface $logger): void
49
    {
50
        helper(['security', 'auth']);
×
51

52
        $this->_logger    = Services::log();
×
53
        $this->router     = Services::router();
×
54
        $this->encryption = new Encryption();
×
55

56
        parent::initController($request, $response, $logger);
×
57

58
        if (method_exists($this, 'setFormat')) {
×
59
            $output = $this->request->negotiate('media', setting('Format.supportedResponseFormats'));
×
60
            $output = Mimes::guessExtensionFromType($output);
×
61
            $this->setFormat($output);
×
62
        }
63

64
        $this->args    = Utils::getAllParams();
×
NEW
65
        $this->content = $this->args['body'] ?? null;
×
66

UNCOV
67
        $this->earlyChecks();
×
68
    }
69

70
    public function __destruct()
71
    {
72
        if ($this->request) {
×
73
            $this->_logRequest();
×
74

75
            if (service('settings')->get('Auth.enableInvalidAttempts') === true) {
×
NEW
76
                $this->handleInvalidAttempts();
×
77
            }
78
        }
79

UNCOV
80
        if ($this->validator) {
×
81
            $this->validator->reset();
×
82
        }
83
    }
84

85
    protected function _logRequest(): void
86
    {
87
        $reflectionClass = new ReflectionClass($this->router->controllerName());
×
88

89
        if ($reflectionClass->implementsInterface(AuthController::class)) {
×
90
            $this->_logger->setLogAuthorized(false);
×
91
        }
92

93
        $this->_logger
×
94
            ->setAuthorized($this->_isRequestAuthorized)
×
95
            ->setResponseCode($this->response->getStatusCode())
×
96
            ->save();
×
97
    }
98

99
    protected function getToken(): array
100
    {
101
        return ['name' => csrf_token(), 'hash' => csrf_hash()];
×
102
    }
103

104
    public function _remap(string $method, ...$params)
105
    {
106
        try {
107
            if (! method_exists($this, $method)) {
×
108
                throw PageNotFoundException::forPageNotFound();
×
109
            }
110

111
            if (service('settings')->get('Auth.enableInvalidAttempts') === true) {
×
112
                AttemptValidator::check($this->response);
×
113
            }
114

115
            $data = $this->{$method}(...$params);
×
116

117
            if ($data instanceof ResponseInterface) {
×
118
                return $data;
×
119
            }
120

121
            if ($this->request->isAJAX() && (is_array($data) || is_object($data))) {
×
122
                return $this->response->setJSON($data);
×
123
            }
124

125
            return $this->response->setBody($data);
×
126
        } catch (ExceptionInterface $ex) {
×
NEW
127
            $this->handleException($ex);
×
128
        }
129
    }
130

131
    private function handleInvalidAttempts(): void
132
    {
NEW
133
        $attemptModel = new AttemptModel();
×
NEW
134
        $attempt      = $attemptModel->where('ip_address', $this->request->getIPAddress())->first();
×
135

NEW
136
        if ($this->_isRequestAuthorized === false) {
×
NEW
137
            if ($attempt === null) {
×
NEW
138
                $attempt = [
×
NEW
139
                    'user_id'      => auth()->user()?->id,
×
NEW
140
                    'ip_address'   => $this->request->getIPAddress(),
×
NEW
141
                    'attempts'     => 1,
×
NEW
142
                    'hour_started' => time(),
×
NEW
143
                ];
×
NEW
144
                $attemptModel->save($attempt);
×
NEW
145
            } elseif ($attempt->attempts < service('settings')->get('Auth.maxAttempts')) {
×
NEW
146
                $attempt->attempts++;
×
NEW
147
                $attemptModel->save($attempt);
×
148
            }
149
        }
150
    }
151

152
    private function handleException(ExceptionInterface $ex)
153
    {
NEW
154
        if (property_exists($ex, 'authorized')) {
×
NEW
155
            $this->_isRequestAuthorized = (new ReflectionProperty($ex, 'authorized'))->getValue();
×
156
        }
157

NEW
158
        $message = $this->validator?->getErrors() ?: $ex->getMessage();
×
NEW
159
        $code    = $ex->getCode() ?: 400;
×
160

NEW
161
        if (method_exists($this, 'fail')) {
×
NEW
162
            return $this->fail($message, $code);
×
163
        }
164

NEW
165
        if ($this->request->isAJAX()) {
×
NEW
166
            return $this->response->setStatusCode($code)->setJSON(
×
NEW
167
                ['status' => false, 'error' => $message, 'token' => $this->getToken()],
×
NEW
168
            );
×
169
        }
170

NEW
171
        throw $ex;
×
172
    }
173
}
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