Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 60
0.00% covered (danger)
0.00%
0 / 4
CRAP
0.00% covered (danger)
0.00%
0 / 1
PasswordReminderLogic
0.00% covered (danger)
0.00%
0 / 60
0.00% covered (danger)
0.00%
0 / 4
72
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 / 4
0.00% covered (danger)
0.00%
0 / 1
2
 validateImpl
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
6
 executeImpl
0.00% covered (danger)
0.00%
0 / 49
0.00% covered (danger)
0.00%
0 / 1
20
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\AppMailer;
11use PeServer\App\Models\AppTemplate;
12use PeServer\App\Models\AppUrl;
13use PeServer\App\Models\AuditLog;
14use PeServer\App\Models\Dao\Entities\PluginsEntityDao;
15use PeServer\App\Models\Dao\Entities\UserAuthenticationsEntityDao;
16use PeServer\App\Models\Dao\Entities\UsersEntityDao;
17use PeServer\App\Models\Data\SessionAnonymous;
18use PeServer\App\Models\Domain\Page\PageLogicBase;
19use PeServer\App\Models\Domain\Page\SessionAnonymousTrait;
20use PeServer\App\Models\Domain\UserUtility;
21use PeServer\App\Models\SessionKey;
22use PeServer\Core\Code;
23use PeServer\Core\Collection\Arr;
24use PeServer\Core\Database\IDatabaseContext;
25use PeServer\Core\Http\HttpStatus;
26use PeServer\Core\I18n;
27use PeServer\Core\Mail\EmailAddress;
28use PeServer\Core\Mail\EmailMessage;
29use PeServer\Core\Mvc\LogicCallMode;
30use PeServer\Core\Mvc\LogicParameter;
31use PeServer\Core\Serialization\JsonSerializer;
32use PeServer\Core\Text;
33use PeServer\Core\Utc;
34use PeServer\Core\Web\UrlPath;
35
36class PasswordReminderLogic extends PageLogicBase
37{
38    use SessionAnonymousTrait;
39
40    public function __construct(LogicParameter $parameter, private AppConfiguration $config, private AppCryptography $cryptography, private AppMailer $mailer, private AppTemplate $appTemplate, private AppEmailInformation $appEmailInformation, private AppUrl $appUrl)
41    {
42        parent::__construct($parameter);
43    }
44
45    #region PageLogicBase
46
47    protected function startup(LogicCallMode $callMode): void
48    {
49        $this->setValue('email', $this->appEmailInformation);
50
51        $this->registerParameterKeys([
52            'reminder_login_id',
53        ], false);
54    }
55
56    protected function validateImpl(LogicCallMode $callMode): void
57    {
58        if ($callMode === LogicCallMode::Initialize) {
59            return;
60        }
61
62        $this->throwHttpStatusIfNotPasswordReminder(HttpStatus::NotFound);
63
64        $this->validation('reminder_login_id', function (string $key, string $value) {
65            $this->validator->isNotEmpty($key, $value);
66        });
67    }
68
69    protected function executeImpl(LogicCallMode $callMode): void
70    {
71        if ($callMode === LogicCallMode::Initialize) {
72            $this->setSession(SessionKey::ANONYMOUS, new SessionAnonymous(passwordReminder: true));
73            return;
74        }
75
76        $loginId = $this->getRequest('reminder_login_id');
77
78        $email = Text::EMPTY;
79        $token = UserUtility::generatePasswordReminderToken();
80        $this->result = [
81            'token' => $token,
82        ];
83
84        $database = $this->openDatabase();
85        $result = $database->transaction(function (IDatabaseContext $context) use ($loginId, $token, &$email) {
86            $usersEntityDao = new UsersEntityDao($context);
87            $userAuthenticationsEntityDao = new UserAuthenticationsEntityDao($context);
88
89            $userId = $usersEntityDao->selectUserIdByLoginId($loginId);
90            if ($userId === null) {
91                return false;
92            }
93
94            $userInfo = $usersEntityDao->selectUserInfoData($userId);
95            $email = $userInfo->email;
96
97            $this->writeAuditLogTargetUser($userId, AuditLog::USER_PASSWORD_REMINDER_TOKEN, ['token' => $token], $context);
98
99            $userAuthenticationsEntityDao->updatePasswordReminder($userId, $token);
100
101            return true;
102        });
103
104        if ($result) {
105            $rawEmail = $this->cryptography->decrypt($email);
106
107            $url = $this->appUrl->addPublicUrl(new UrlPath("password/reset/$token"));
108
109            $subject = I18n::message('subject/password_reminder_token');
110            $values = [
111                'login_id' => $loginId,
112                'url' => $url->toString(),
113            ];
114            $html = $this->appTemplate->createMailTemplate('password_reminder_token', $subject, $values);
115
116            $this->mailer->toAddresses = [
117                new EmailAddress($rawEmail),
118            ];
119            $this->mailer->subject = $subject;
120            $this->mailer->setMessage(new EmailMessage(null, $html));
121
122            $this->mailer->send();
123        } else {
124            // 管理側になんかあったよメールの送信
125            $jsonSerializer = new JsonSerializer();
126            $content = $jsonSerializer->save([
127                'login_id' => $loginId,
128                'ip_address' => $this->stores->special->getServer('REMOTE_ADDR'),
129                'user_agent' => $this->stores->special->getServer('HTTP_USER_AGENT'),
130            ]);
131
132            $this->mailer->toAddresses = [
133                new EmailAddress($this->config->setting->config->address->fromEmail->address),
134            ];
135            $this->mailer->subject = '<SPAM-REMINDER>' . I18n::message('subject/password_reminder_token');
136            $this->mailer->setMessage(new EmailMessage('多分期待してないリマインダー' . PHP_EOL . $content));
137
138            $this->mailer->send();
139        }
140    }
141
142    #endregion
143}