Skip to content

Commit b09af3c

Browse files
committed
feat: add update, updatePassword & resetPassword to user object
1 parent 6a895b2 commit b09af3c

File tree

1 file changed

+187
-9
lines changed

1 file changed

+187
-9
lines changed

src/Auth/User.php

Lines changed: 187 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,10 @@
22

33
namespace Leaf\Auth;
44

5-
use Exception;
65
use Firebase\JWT\JWT;
7-
use Leaf\Db;
6+
use Leaf\Date;
7+
use Leaf\Helpers\Password;
88
use Leaf\Http\Session;
9-
use Throwable;
109

1110
/**
1211
* Auth User
@@ -23,7 +22,7 @@ class User
2322

2423
/**
2524
* Internal instance of Leaf database
26-
* @var Db
25+
* @var \Leaf\DB
2726
*/
2827
protected $db;
2928

@@ -43,6 +42,12 @@ class User
4342
*/
4443
protected array $tokens = [];
4544

45+
/**
46+
* All errors caught
47+
* @var array
48+
*/
49+
protected $errorsArray = [];
50+
4651
public function __construct($data, $session = true)
4752
{
4853
$this->data = $data;
@@ -72,7 +77,7 @@ public function __construct($data, $session = true)
7277
$sessionLifetime = strtotime($sessionLifetime);
7378

7479
if (!$sessionLifetime) {
75-
throw new Exception('Invalid session lifetime');
80+
throw new \Exception('Invalid session lifetime');
7681
}
7782
} else {
7883
$sessionLifetime = time() + $sessionLifetime;
@@ -103,6 +108,170 @@ public function id()
103108
return $this->data[Config::get('id.key')] ?? null;
104109
}
105110

111+
/**
112+
* Update user data
113+
* ---
114+
* Update user data in the database
115+
*
116+
* @param array $userData User data
117+
* @return bool
118+
*/
119+
public function update(array $userData): bool
120+
{
121+
$user = $this->get();
122+
123+
if (!$user) {
124+
return false;
125+
}
126+
127+
$idKey = Config::get('id.key');
128+
$table = Config::get('db.table');
129+
130+
if (Config::get('timestamps')) {
131+
$userData['updated_at'] = (new Date())->tick()->format(Config::get('timestamps.format'));
132+
}
133+
134+
if (isset($userData['email'])) {
135+
$userData['email'] = strtolower($userData['email']);
136+
}
137+
138+
if (\count(Config::get('unique')) > 0) {
139+
foreach (Config::get('unique') as $unique) {
140+
if (!isset($userData[$unique])) {
141+
continue;
142+
}
143+
144+
$data = $this->db->select($table, Config::get('id.key'))->where($unique, $userData[$unique])->first();
145+
146+
if ($data && $data[Config::get('id.key')] !== $this->id()) {
147+
$this->errorsArray[$unique] = "$unique already exists";
148+
}
149+
}
150+
151+
if (\count($this->errorsArray) > 0) {
152+
return false;
153+
}
154+
}
155+
156+
try {
157+
$query = $this->db->update($table)->params($userData)->where($idKey, $this->id())->execute();
158+
159+
if (!$query) {
160+
$this->errorsArray = array_merge($this->errorsArray, $this->db->errors());
161+
return false;
162+
}
163+
} catch (\Throwable $th) {
164+
throw new \Exception($th->getMessage());
165+
}
166+
167+
if (Config::get('session')) {
168+
session_regenerate_id();
169+
}
170+
171+
foreach ($userData as $key => $value) {
172+
$this->data[$key] = $value;
173+
}
174+
175+
return true;
176+
}
177+
178+
/**
179+
* Update user password
180+
* ---
181+
* Update user password in the database
182+
*
183+
* @param string $oldPassword Old password
184+
* @param string $newPassword New password
185+
* @return bool
186+
*/
187+
public function updatePassword(string $oldPassword, string $newPassword): bool
188+
{
189+
$user = $this->get();
190+
191+
if (!$user) {
192+
return false;
193+
}
194+
195+
$passwordKey = Config::get('password.key');
196+
197+
if (Config::get('password.verify') !== false && isset($user[$passwordKey])) {
198+
$passwordIsValid = (is_callable(Config::get('password.verify')))
199+
? call_user_func(Config::get('password.verify'), $oldPassword, $user[$passwordKey])
200+
: Password::verify($oldPassword, $user[$passwordKey]);
201+
202+
if (!$passwordIsValid) {
203+
$this->errorsArray['password'] = Config::get('messages.loginPasswordError');
204+
return false;
205+
}
206+
}
207+
208+
$newPassword = (Config::get('password.encode') !== false)
209+
? ((is_callable(Config::get('password.encode')))
210+
? call_user_func(Config::get('password.encode'), $newPassword)
211+
: Password::hash($newPassword))
212+
: $newPassword;
213+
214+
try {
215+
$query = $this->db->update(Config::get('db.table'))
216+
->params([$passwordKey => $newPassword])
217+
->where(Config::get('id.key'), $this->id())
218+
->execute();
219+
220+
if (!$query) {
221+
$this->errorsArray = array_merge($this->errorsArray, $this->db->errors());
222+
return false;
223+
}
224+
} catch (\Throwable $th) {
225+
throw new \Exception($th->getMessage());
226+
}
227+
228+
$this->data[$passwordKey] = $newPassword;
229+
230+
return true;
231+
}
232+
233+
/**
234+
* Reset user password
235+
* ---
236+
* Reset user password in the database
237+
*
238+
* @param string $newPassword New password
239+
* @return bool
240+
*/
241+
public function resetPassword(string $newPassword): bool
242+
{
243+
$user = $this->get();
244+
245+
if (!$user) {
246+
return false;
247+
}
248+
249+
$passwordKey = Config::get('password.key');
250+
$newPassword = (Config::get('password.encode') !== false)
251+
? ((is_callable(Config::get('password.encode')))
252+
? call_user_func(Config::get('password.encode'), $newPassword)
253+
: Password::hash($newPassword))
254+
: $newPassword;
255+
256+
try {
257+
$query = $this->db->update(Config::get('db.table'))
258+
->params([$passwordKey => $newPassword])
259+
->where(Config::get('id.key'), $this->id())
260+
->execute();
261+
262+
if (!$query) {
263+
$this->errorsArray = array_merge($this->errorsArray, $this->db->errors());
264+
return false;
265+
}
266+
} catch (\Throwable $th) {
267+
throw new \Exception($th->getMessage());
268+
}
269+
270+
$this->data[$passwordKey] = $newPassword;
271+
272+
return true;
273+
}
274+
106275
/**
107276
* Get auth information to be sent to the client
108277
* @return object
@@ -212,7 +381,7 @@ public function verifyEmail(): bool
212381
->execute();
213382

214383
return true;
215-
} catch (Throwable $th) {
384+
} catch (\Throwable $th) {
216385
return false;
217386
}
218387
}
@@ -246,7 +415,7 @@ public function get()
246415

247416
/**
248417
* Set user db instance
249-
* @param Db $db
418+
* @param \Leaf\Db $db
250419
* @return User
251420
*/
252421
public function setDb($db)
@@ -256,6 +425,15 @@ public function setDb($db)
256425
return $this;
257426
}
258427

428+
/**
429+
* Get user errors
430+
* @return array
431+
*/
432+
public function errors()
433+
{
434+
return $this->errorsArray;
435+
}
436+
259437
public function __toString()
260438
{
261439
return json_encode($this->get());
@@ -296,14 +474,14 @@ public function __unset($name)
296474
*
297475
* @param mixed $method The table to relate to
298476
* @param mixed $args
299-
* @throws Exception
477+
* @throws \Exception
300478
*
301479
* @return Model
302480
*/
303481
public function __call($method, $args)
304482
{
305483
if (!class_exists('Leaf\App')) {
306-
throw new Exception('Relations are only available in Leaf apps.');
484+
throw new \Exception('Relations are only available in Leaf apps.');
307485
}
308486

309487
return (new Model([

0 commit comments

Comments
 (0)