Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 45
0.00% covered (danger)
0.00%
0 / 5
CRAP
0.00% covered (danger)
0.00%
0 / 1
PasswordResetLogic
0.00% covered (danger)
0.00%
0 / 45
0.00% covered (danger)
0.00%
0 / 5
110
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 startup
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 validateImpl
0.00% covered (danger)
0.00%
0 / 16
0.00% covered (danger)
0.00%
0 / 1
12
 executeImpl
0.00% covered (danger)
0.00%
0 / 25
0.00% covered (danger)
0.00%
0 / 1
20
 cleanup
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3declare(strict_types=1);
4
5namespace PeServer\App\Models\Domain\Page\Password;
6
7use PeServer\App\Models\AppConfiguration;
8use PeServer\App\Models\AppCryptography;
9use PeServer\App\Models\AppEmailInformation;
10use PeServer\App\Models\AuditLog;
11use PeServer\App\Models\Dao\Entities\PluginsEntityDao;
12use PeServer\App\Models\Dao\Entities\UserAuditLogsEntityDao;
13use PeServer\App\Models\Dao\Entities\UserAuthenticationsEntityDao;
14use PeServer\App\Models\Dao\Entities\UsersEntityDao;
15use PeServer\App\Models\Data\SessionAnonymous;
16use PeServer\App\Models\Domain\AccountValidator;
17use PeServer\App\Models\Domain\Page\PageLogicBase;
18use PeServer\App\Models\Domain\Page\SessionAnonymousTrait;
19use PeServer\App\Models\SessionKey;
20use PeServer\Core\Collection\Arr;
21use PeServer\Core\Cryptography;
22use PeServer\Core\Database\IDatabaseContext;
23use PeServer\Core\Http\HttpStatus;
24use PeServer\Core\I18n;
25use PeServer\Core\Mvc\LogicCallMode;
26use PeServer\Core\Mvc\LogicParameter;
27use PeServer\Core\Text;
28
29class PasswordResetLogic extends PageLogicBase
30{
31    use SessionAnonymousTrait;
32
33    public function __construct(
34        LogicParameter $parameter,
35        private AppConfiguration $config,
36        private AppEmailInformation $appEmailInformation
37    ) {
38        parent::__construct($parameter);
39    }
40
41    #region PageLogicBase
42
43    protected function startup(LogicCallMode $callMode): void
44    {
45        $this->setValue('email', $this->appEmailInformation);
46    }
47
48    protected function validateImpl(LogicCallMode $callMode): void
49    {
50        if ($callMode === LogicCallMode::Initialize) {
51            return;
52        }
53
54        $this->throwHttpStatusIfNotPasswordReset(HttpStatus::NotFound);
55
56        $this->validation('reminder_login_id', function (string $key, string $value) {
57            $this->validator->isNotWhiteSpace($key, $value);
58        });
59
60        //TODO: AccountUserPasswordLogic と同じなんよ
61        $this->validation('reminder_password_new', function (string $key, string $value) {
62            $accountValidator = new AccountValidator($this, $this->validator);
63            $accountValidator->isPassword($key, $value);
64        }, ['trim' => false]);
65
66        $this->validation('reminder_password_confirm', function (string $key, string $value) {
67            $this->validator->isNotWhiteSpace($key, $value);
68            $newPassword = $this->getRequest('reminder_password_new', Text::EMPTY, false);
69            if ($value !== $newPassword) {
70                $this->addError($key, I18n::message('error/password_confirm'));
71            }
72        });
73    }
74
75    protected function executeImpl(LogicCallMode $callMode): void
76    {
77        if ($callMode === LogicCallMode::Initialize) {
78            $this->setSession(SessionKey::ANONYMOUS, new SessionAnonymous(passwordReset: true));
79            return;
80        }
81
82        $userId = Text::EMPTY;
83
84        $database = $this->openDatabase();
85        $result = $database->transaction(function (IDatabaseContext $context) use (&$userId) {
86            $usersEntityDao = new UsersEntityDao($context);
87            $userAuthenticationsEntityDao = new UserAuthenticationsEntityDao($context);
88
89            $token = $this->getRequest('token');
90            $loginId = $this->getRequest('reminder_login_id');
91            $rawPassword = $this->getRequest('reminder_password_new', Text::EMPTY, false);
92
93            $userId = $usersEntityDao->selectUserIdByLoginId($loginId);
94            if ($userId === null) {
95                $this->logger->warn('not fount loginId: {}', $userId);
96                return false;
97            }
98
99            if (!$userAuthenticationsEntityDao->selectExistsToken($token, $this->config->setting->config->confirm->passwordReminderEmailMinutes)) {
100                $this->logger->warn('not fount token: {}, userId: {}', $token, $userId);
101                return false;
102            }
103
104            $password = Cryptography::hashPassword($rawPassword);
105            $userAuthenticationsEntityDao->updateResetPassword($userId, $password);
106
107            $this->writeAuditLogTargetUser($userId, AuditLog::USER_PASSWORD_REMINDER_RESET, ['token' => $token], $context);
108
109            return true;
110        });
111
112        $this->addTemporaryMessage('パスワード変更が実施されました');
113        $this->addTemporaryMessage('ログインを実施してください');
114    }
115
116    protected function cleanup(LogicCallMode $callMode): void
117    {
118        $this->setValue('token', $this->getRequest('token'));
119        $this->setValue('reminder_login_id', $this->getRequest('reminder_login_id'));
120    }
121
122    #endregion
123}