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

klinge / sl-webapp / 18972011891

31 Oct 2025 12:06PM UTC coverage: 74.73% (+11.1%) from 63.602%
18972011891

push

github

klinge
Fixed phpcs errors

1662 of 2224 relevant lines covered (74.73%)

3.82 hits per line

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

82.0
/App/Services/Auth/UserAuthenticationService.php
1
<?php
2

3
declare(strict_types=1);
4

5
namespace App\Services\Auth;
6

7
use App\Services\Auth\PasswordService;
8
use App\Utils\Sanitizer;
9
use App\Utils\EmailType;
10
use App\Utils\Email;
11
use App\Utils\TokenType;
12
use App\Utils\TokenHandler;
13
use App\Models\MedlemRepository;
14
use App\Models\Medlem;
15
use PDO;
16
use League\Route\Router;
17
use Monolog\Logger;
18

19
class UserAuthenticationService
20
{
21
    private Logger $logger;
22
    private PDO $conn;
23
    private Router $router;
24
    private Email $mailer;
25
    private array $config;
26
    private TokenHandler $tokenHandler;
27
    private MedlemRepository $medlemRepo;
28
    private PasswordService $passwordSvc;
29

30

31
    public function __construct(PDO $conn, Logger $logger, Router $router, Email $mailer, array $config)
32
    {
33
        $this->conn = $conn;
12✔
34
        $this->logger = $logger;
12✔
35
        $this->router = $router;
12✔
36
        $this->mailer = $mailer;
12✔
37
        $this->config = $config;
12✔
38
        $this->tokenHandler = $this->createTokenHandler();
12✔
39
        $this->medlemRepo = new MedlemRepository($this->conn, $this->logger);
12✔
40
        $this->passwordSvc = new PasswordService();
12✔
41
    }
42

43
    public function registerUser(array $formData): array
44
    {
45
        $s = new Sanitizer();
5✔
46
        $rules = ['email' => 'email'];
5✔
47
        $cleanValues = $s->sanitize($formData, $rules);
5✔
48

49
        $email = $cleanValues['email'];
5✔
50
        $password = $formData['password'];
5✔
51
        $repeatPassword = $formData['verifyPassword'];
5✔
52

53
        // Check if user exists
54
        $result = $this->medlemRepo->getMemberByEmail($email);
5✔
55
        if (!$result) {
5✔
56
            $this->logger->info("Register member: Failed to register new member. Email does not exist: " . $email);
1✔
57
            return [
1✔
58
                'success' => false,
1✔
59
                'message' => 'Det finns ingen medlem med den emailadressen. Använd den mailadress du angav när du registrerade dina medlemsuppgifter.'
1✔
60
            ];
1✔
61
        }
62

63
        $medlem = $this->medlemRepo->getById($result['id']);
4✔
64
        if (!$medlem) {
4✔
65
            $this->logger->error("Technical error. Could not get member object for member id: " . $result['id']);
×
66
            return [
×
67
                'success' => false,
×
68
                'message' => 'Tekniskt fel. Försök igen eller kontakta en administratör.'
×
69
            ];
×
70
        }
71

72
        if ($medlem->password) {
4✔
73
            return [
×
74
                'success' => false,
×
75
                'message' => 'Ditt konto är redan redan registrerat. Har du glömt ditt lösenord? Prova att byta lösenord.'
×
76
            ];
×
77
        }
78

79
        if (!$this->passwordSvc->passwordsMatch($password, $repeatPassword)) {
4✔
80
            return [
1✔
81
                'success' => false,
1✔
82
                'message' => 'Lösenorden matchar inte!'
1✔
83
            ];
1✔
84
        }
85

86
        $passwordErrors = $this->passwordSvc->validatePassword($password, $email);
3✔
87
        if (!empty($passwordErrors)) {
3✔
88
            return [
1✔
89
                'success' => false,
1✔
90
                'message' => $this->passwordSvc->formatPasswordErrors($passwordErrors)
1✔
91
            ];
1✔
92
        }
93

94
        $hashedPassword = $this->passwordSvc->hashPassword($password);
2✔
95
        $token = $this->tokenHandler->generateToken();
2✔
96
        if (!$this->tokenHandler->saveToken($token, TokenType::ACTIVATION, $email, $hashedPassword)) {
2✔
97
            return [
×
98
                'success' => false,
×
99
                'message' => 'Något gick fel vid registreringen. Försök igen.'
×
100
            ];
×
101
        }
102

103
        $mailResult = $this->sendActivationEmail($medlem, $email, $token);
2✔
104
        if (!$mailResult) {
2✔
105
            return [
1✔
106
                'success' => false,
1✔
107
                'message' => 'Kunde inte skicka registreringsmail. Försök igen.'
1✔
108
            ];
1✔
109
        }
110
        return ['success' => true];
1✔
111
    }
112

113
    private function sendActivationEmail(Medlem $medlem, string $email, string $token): bool
114
    {
115
        return $this->sendAuthenticationEmail(
2✔
116
            $email,
2✔
117
            $token,
2✔
118
            $medlem->fornamn,
2✔
119
            EmailType::VERIFICATION,
2✔
120
            'register-activate'
2✔
121
        );
2✔
122
    }
123

124
    public function activateAccount(string $token): array
125
    {
126
        $tokenResult = $this->tokenHandler->isValidToken($token, TokenType::ACTIVATION);
2✔
127
        if (!$tokenResult['success']) {
2✔
128
            $this->logger->warning(
1✔
129
                "Activate account: failed to activate account. Token given was" . $token
1✔
130
            );
1✔
131
            return $tokenResult;
1✔
132
        }
133

134
        $member = $this->medlemRepo->getMemberByEmail($tokenResult['email']);
1✔
135
        $this->saveMembersPassword($tokenResult['hashedPassword'], $member['email']);
1✔
136

137
        $this->tokenHandler->deleteToken($token);
1✔
138
        $this->tokenHandler->deleteExpiredTokens();
1✔
139

140
        $this->logger->info("Activated account for member: " . $member['email']);
1✔
141

142
        return [
1✔
143
            'success' => true
1✔
144
        ];
1✔
145
    }
146

147
    public function requestPasswordReset(string $email): array
148
    {
149
        $member = $this->medlemRepo->getMemberByEmail($email);
3✔
150
        if (!$member) {
3✔
151
            $this->logger->info("Reset password called for non-existing user: " . $email);
1✔
152
            //Return true to avoid leaking information about existing users
153
            return ['success' => true];
1✔
154
        }
155

156
        $token = $this->tokenHandler->generateToken();
2✔
157
        if (!$this->tokenHandler->saveToken($token, TokenType::RESET, $email)) {
2✔
158
            return ['success' => false];
×
159
        }
160

161
        $mailResult = $this->sendPasswordResetEmail($member, $email, $token);
2✔
162
        if (!$mailResult) {
2✔
163
            return [
1✔
164
                'success' => false,
1✔
165
                'message' => 'Kunde inte skicka mail för lösenordsåterställning. Försök igen.'
1✔
166
            ];
1✔
167
        }
168
        return ['success' => true];
1✔
169
    }
170

171
    private function sendPasswordResetEmail(array $member, string $email, string $token): bool
172
    {
173
        return $this->sendAuthenticationEmail(
2✔
174
            $email,
2✔
175
            $token,
2✔
176
            $member['fornamn'],
2✔
177
            EmailType::PASSWORD_RESET,
2✔
178
            'show-reset-password'
2✔
179
        );
2✔
180
    }
181

182
    public function validateResetToken(string $token): array
183
    {
184
        return $this->tokenHandler->isValidToken($token, TokenType::RESET);
×
185
    }
186

187
    public function resetPassword(array $formData): array
188
    {
189
        $email = $formData['email'];
2✔
190
        $token = $formData['token'];
2✔
191
        $password = $formData['password'];
2✔
192
        $password2 = $formData['password2'];
2✔
193

194
        if (!$this->passwordSvc->passwordsMatch($password, $password2)) {
2✔
195
            return [
1✔
196
                'success' => false,
1✔
197
                'message' => 'Lösenorden stämmer inte överens. Försök igen'
1✔
198
            ];
1✔
199
        }
200

201
        $passwordErrors = $this->passwordSvc->validatePassword($password, $email);
1✔
202
        if (!empty($passwordErrors)) {
1✔
203
            return [
×
204
                'success' => false,
×
205
                'message' => $this->passwordSvc->formatPasswordErrors($passwordErrors)
×
206
            ];
×
207
        }
208

209
        $member = $this->medlemRepo->getMemberByEmail($email);
1✔
210
        if (!$member) {
1✔
211
            return [
×
212
                'success' => false,
×
213
                'message' => 'OJ! Nu blev det ett tekniskt fel. Användaren finns inte.'
×
214
            ];
×
215
        }
216

217
        $hashedPassword = $this->passwordSvc->hashPassword($password);
1✔
218
        $this->saveMembersPassword($hashedPassword, $email);
1✔
219
        $this->tokenHandler->deleteToken($token);
1✔
220

221
        return ['success' => true];
1✔
222
    }
223

224
    private function saveMembersPassword(string $hashedPassword, string $email): bool
225
    {
226
        $stmt = $this->conn->prepare("UPDATE medlem SET password = :password WHERE email = :email");
2✔
227
        try {
228
            $stmt->bindParam(':password', $hashedPassword);
2✔
229
            $stmt->bindParam(':email', $email);
2✔
230
            $stmt->execute();
2✔
231

232
            $this->logger->info("Password updated for member:" . $email);
2✔
233
            return true;
2✔
234
        } catch (\PDOException $e) {
×
235
            $this->logger->error("Error updating password for member:" . $email .
×
236
                " Error: " . $e->getMessage());
×
237
            return false;
×
238
        }
239
    }
240

241
    private function sendAuthenticationEmail(
242
        string $email,
243
        string $token,
244
        string $firstName,
245
        EmailType $emailType,
246
        string $routeName
247
    ): bool {
248
        $route = $this->router->getNamedRoute($routeName);
4✔
249
        $data = [
4✔
250
            'token' => $token,
4✔
251
            'fornamn' => $firstName,
4✔
252
            'url' => $this->config['SITE_ADDRESS'] . $route->getPath(['token' => $token])
4✔
253
        ];
4✔
254

255
        try {
256
            $this->mailer->send($emailType, $email, data: $data);
4✔
257
            $this->logger->info("Sent {$emailType->value} email to: {$email}");
2✔
258
            return true;
2✔
259
        } catch (\Exception $e) {
2✔
260
            $this->logger->error("Failed to send {$emailType->value} mail to member with email: " . $email);
2✔
261
            $this->logger->error($e->getMessage());
2✔
262
            return false;
2✔
263
        }
264
    }
265

266
    protected function createTokenHandler(): TokenHandler
267
    {
268
        return new TokenHandler($this->conn, $this->logger);
12✔
269
    }
270
}
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