'user_group', 'auth_group_access' => '', 'auth_rule' => 'user_rule', ], $config)); $this->setKeepTime((int)config('buildadmin.user_token_keep_time', 86400)); } public function __get($name): mixed { return $this->model?->$name; } public static function instance(array $options = []): Auth { $request = function_exists('request') ? request() : null; if ($request && !isset($request->userAuth)) { $request->userAuth = new static($options); } return $request && isset($request->userAuth) ? $request->userAuth : new static($options); } public function init($token): bool { $tokenData = Token::get($token); if ($tokenData) { Token::tokenExpirationCheck($tokenData); $userId = $tokenData['user_id']; if ($tokenData['type'] == self::TOKEN_TYPE && $userId > 0) { $this->model = User::where('id', $userId)->find(); if (!$this->model) { $this->setError('Account not exist'); return false; } if ($this->model->status != 'enable') { $this->setError('Account disabled'); return false; } $this->token = $token; $this->loginSuccessful(); return true; } } $this->setError('Token login failed'); $this->reset(); return false; } public function register(string $username, string $password = '', string $mobile = '', string $email = '', int $group = 1, array $extend = []): bool { $request = function_exists('request') ? request() : null; $ip = $request ? $request->getRealIp() : '0.0.0.0'; if ($email && !filter_var($email, FILTER_VALIDATE_EMAIL)) { $this->setError(__('Email')); return false; } if ($username && !preg_match('/^[a-zA-Z][a-zA-Z0-9_]{2,15}$/', $username)) { $this->setError(__('Username')); return false; } if (User::where('email', $email)->find() && $email) { $this->setError(__('Email') . ' ' . __('already exists')); return false; } if (User::where('username', $username)->find()) { $this->setError(__('Username') . ' ' . __('already exists')); return false; } $nickname = preg_replace_callback('/1[3-9]\d{9}/', fn($m) => substr($m[0], 0, 3) . '****' . substr($m[0], 7), $username); $time = time(); $data = [ 'group_id' => $group, 'nickname' => $nickname, 'join_ip' => $ip, 'join_time' => $time, 'last_login_ip' => $ip, 'last_login_time' => $time, 'status' => 'enable', ]; $data = array_merge(compact('username', 'password', 'mobile', 'email'), $data, $extend); Db::startTrans(); try { $this->model = User::create($data); $this->token = Random::uuid(); Token::set($this->token, self::TOKEN_TYPE, $this->model->id, $this->keepTime); Db::commit(); if ($password) { $this->model->resetPassword($this->model->id, $password); } event_trigger('userRegisterSuccess', $this->model); } catch (Throwable $e) { $this->setError($e->getMessage()); Db::rollback(); return false; } return true; } public function login(string $username, string $password, bool $keep): bool { $accountType = false; if (preg_match('/^1[3-9]\d{9}$/', $username)) $accountType = 'mobile'; elseif (filter_var($username, FILTER_VALIDATE_EMAIL)) $accountType = 'email'; elseif (preg_match('/^[a-zA-Z][a-zA-Z0-9_]{2,15}$/', $username)) $accountType = 'username'; if (!$accountType) { $this->setError('Account not exist'); return false; } $this->model = User::where($accountType, $username)->find(); if (!$this->model) { $this->setError('Account not exist'); return false; } if ($this->model->status == 'disable') { $this->setError('Account disabled'); return false; } $userLoginRetry = config('buildadmin.user_login_retry'); if ($userLoginRetry && $this->model->last_login_time) { if ($this->model->login_failure > 0 && time() - strtotime($this->model->last_login_time) >= 86400) { $this->model->login_failure = 0; $this->model->save(); $this->model = User::where($accountType, $username)->find(); } if ($this->model->login_failure >= $userLoginRetry) { $this->setError('Please try again after 1 day'); return false; } } if (!verify_password($password, $this->model->password, ['salt' => $this->model->salt])) { $this->loginFailed(); $this->setError('Password is incorrect'); return false; } if (config('buildadmin.user_sso')) { Token::clear(self::TOKEN_TYPE, $this->model->id); Token::clear(self::TOKEN_TYPE . '-refresh', $this->model->id); } if ($keep) $this->setRefreshToken($this->refreshTokenKeepTime); $this->loginSuccessful(); return true; } public function direct(int $userId): bool { $this->model = User::find($userId); if (!$this->model) return false; if (config('buildadmin.user_sso')) { Token::clear(self::TOKEN_TYPE, $this->model->id); Token::clear(self::TOKEN_TYPE . '-refresh', $this->model->id); } return $this->loginSuccessful(); } public function loginSuccessful(): bool { if (!$this->model) return false; $request = function_exists('request') ? request() : null; $ip = $request ? $request->getRealIp() : '0.0.0.0'; $this->model->startTrans(); try { $this->model->login_failure = 0; $this->model->last_login_time = date('Y-m-d H:i:s'); $this->model->last_login_ip = $ip; $this->model->save(); $this->loginEd = true; if (!$this->token) { $this->token = Random::uuid(); Token::set($this->token, self::TOKEN_TYPE, $this->model->id, $this->keepTime); } $this->model->commit(); } catch (Throwable $e) { $this->model->rollback(); $this->setError($e->getMessage()); return false; } return true; } public function loginFailed(): bool { if (!$this->model) return false; $request = function_exists('request') ? request() : null; $ip = $request ? $request->getRealIp() : '0.0.0.0'; $this->model->startTrans(); try { $this->model->login_failure++; $this->model->last_login_time = date('Y-m-d H:i:s'); $this->model->last_login_ip = $ip; $this->model->save(); $this->model->commit(); } catch (Throwable $e) { $this->model->rollback(); } return $this->reset(); } public function logout(): bool { if (!$this->loginEd) { $this->setError('You are not logged in'); return false; } return $this->reset(); } public function isLogin(): bool { return $this->loginEd; } public function getUser(): User { return $this->model; } public function getToken(): string { return $this->token; } public function setRefreshToken(int $keepTime = 0): void { $this->refreshToken = Random::uuid(); Token::set($this->refreshToken, self::TOKEN_TYPE . '-refresh', $this->model->id, $keepTime); } public function getRefreshToken(): string { return $this->refreshToken; } public function getUserInfo(): array { if (!$this->model) return []; $info = $this->model->toArray(); $info = array_intersect_key($info, array_flip($this->getAllowFields())); $info['token'] = $this->getToken(); $info['refresh_token'] = $this->getRefreshToken(); return $info; } public function getAllowFields(): array { return $this->allowFields; } public function setAllowFields($fields): void { $this->allowFields = $fields; } public function setKeepTime(int $keepTime = 0): void { $this->keepTime = $keepTime; } public function check(string $name, int $uid = 0, string $relation = 'or', string $mode = 'url'): bool { return parent::check($name, $uid ?: $this->id, $relation, $mode); } public function getRuleList(int $uid = 0): array { return parent::getRuleList($uid ?: $this->id); } public function getRuleIds(int $uid = 0): array { return parent::getRuleIds($uid ?: $this->id); } public function getMenus(int $uid = 0): array { return parent::getMenus($uid ?: $this->id); } public function isSuperUser(): bool { return in_array('*', $this->getRuleIds()); } public function setError(string $error): Auth { $this->error = $error; return $this; } public function getError(): string { return $this->error ? __($this->error) : ''; } protected function reset(bool $deleteToken = true): bool { if ($deleteToken && $this->token) { Token::delete($this->token); } $this->token = ''; $this->loginEd = false; $this->model = null; $this->refreshToken = ''; $this->setError(''); $this->setKeepTime((int)config('buildadmin.user_token_keep_time', 86400)); return true; } }