Bitrix-D7 23.9
 
Загрузка...
Поиск...
Не найдено
shortcode.php
1<?php
10
11use Bitrix\Main;
14
16{
18 protected $context;
19 protected $type;
21 protected $code;
22 protected $checkInterval = 300; //seconds, a half of the real time window
23 protected $resendInterval = 60; //seconds
24
31 {
32 $this->context = $context;
33 $this->type = $type;
34
35 if(!$this->load())
36 {
37 throw new Main\ObjectException("User probably not found: ".$context->getUserId());
38 }
39 }
40
45 public function generate()
46 {
47 $totp = new Mfa\TotpAlgorithm();
48 $totp->setInterval($this->checkInterval);
49 $totp->setSecret($this->code->getOtpSecret());
50
51 $timecode = $totp->timecode(time());
52 $shortCode = $totp->generateOTP($timecode);
53
54 return $shortCode;
55 }
56
62 public function verify($code)
63 {
64 $result = new Main\Result();
65
66 $attempts = (int)$this->code->getAttempts();
67
68 if($attempts >= 3)
69 {
70 $result->addError(new Main\Error("Retry count exceeded.", "ERR_RETRY_COUNT"));
71 return $result;
72 }
73
75 $totp->setInterval($this->checkInterval);
76 $totp->setSecret($this->code->getOtpSecret());
77
78 $otpResult = false;
79 try
80 {
81 list($otpResult, ) = $totp->verify($code);
82 }
83 catch(Main\ArgumentException $e)
84 {
85 }
86
87 if($otpResult)
88 {
89 $this->code->setDateSent(null);
90 $this->code->setDateResent(null);
91 }
92 else
93 {
94 $result->addError(new Main\Error("Incorrect code.", "ERR_CONFIRM_CODE"));
95
96 $this->code->setAttempts($attempts + 1);
97 }
98
99 $this->code->save();
100
101 return $result;
102 }
103
108 public function checkDateSent()
109 {
110 $result = new Main\Result();
111
112 $resultData = [
113 "checkInterval" => $this->checkInterval*2,
114 "resendInterval" => $this->resendInterval,
115 ];
116
117 //alowed only once in a interval
118 if($this->code->getDateResent())
119 {
120 $currentDateTime = new Main\Type\DateTime();
121 $interval = $currentDateTime->getTimestamp() - $this->code->getDateResent()->getTimestamp();
122
123 if($interval < $this->resendInterval)
124 {
125 $resultData["secondsLeft"] = $this->resendInterval - $interval;
126 $resultData["secondsPassed"] = $interval;
127 $result->addError(new Main\Error("Timeout not expired yet."));
128 }
129 }
130
131 $result->setData($resultData);
132
133 return $result;
134 }
135
140 public function saveDateSent()
141 {
142 $currentDateTime = new Main\Type\DateTime();
143
144 if($this->code->getDateSent())
145 {
146 if(($currentDateTime->getTimestamp() - $this->code->getDateSent()->getTimestamp()) > $this->checkInterval*2)
147 {
148 //reset attempts only for the new code (when time passes)
149 $this->code->setAttempts(0);
150 $this->code->setDateSent(null);
151 }
152 }
153
154 if(!$this->code->getDateSent())
155 {
156 //first time only
157 $this->code->setDateSent($currentDateTime);
158 }
159 $this->code->setDateResent($currentDateTime);
160
161 $this->code->save();
162
163 return true;
164 }
165
169 public function getUser()
170 {
171 return $this->code->fillUser();
172 }
173
177 public static function deleteByUser($userId)
178 {
179 UserAuthCodeTable::deleteByFilter(["=USER_ID" => $userId]);
180 }
181
182 protected function load()
183 {
184 $userId = $this->context->getUserId();
185 $primaryKey = [
186 "USER_ID" => $userId,
187 "CODE_TYPE" => $this->type,
188 ];
189
190 $code = UserAuthCodeTable::getById($primaryKey)->fetchObject();
191
192 if(!$code)
193 {
194 //first time for the user, should create a record
196 $code->setUserId($userId);
197 $code->setCodeType($this->type);
198
199 $result = $code->save();
200 if(!$result->isSuccess())
201 {
202 return false;
203 }
204 }
205
206 $this->code = $code;
207
208 return true;
209 }
210}
__construct(Context $context, $type=UserAuthCodeTable::TYPE_EMAIL)
Definition shortcode.php:30
static createObject($setDefaultValues=true)