feat: 新增精灵图贴纸支持及多项功能优化
新增精灵图贴纸类型及内置资源 优化分类图标使用SVG替代emoji 实现分页预加载功能 修复API基础地址与客户端一致 新增健康生活、国学经典服务模块 扩展Feed频道至44种并整合互动统计 修正多处UI显示问题及逻辑错误
This commit is contained in:
603
docs/toolsapi/application/api/controller/UserSecurity.php
Normal file
603
docs/toolsapi/application/api/controller/UserSecurity.php
Normal file
@@ -0,0 +1,603 @@
|
||||
<?php
|
||||
|
||||
namespace app\api\controller;
|
||||
|
||||
use app\common\controller\Api;
|
||||
use app\common\library\Ems;
|
||||
use app\common\library\Sms;
|
||||
use fast\Random;
|
||||
use think\Config;
|
||||
use think\Validate;
|
||||
|
||||
/**
|
||||
* 用户安全接口
|
||||
* @time 2026-04-29
|
||||
* @description 用户安全相关API,含注册/登录/改密/改邮箱/重置密码等
|
||||
* @lastUpdate v7.7.0 从User控制器拆分,引入邮箱验证机制
|
||||
*/
|
||||
class UserSecurity extends Api
|
||||
{
|
||||
protected $noNeedLogin = ['login', 'mobilelogin', 'register', 'resetpwd', 'tokenLogin', 'sendEms', 'checkEms'];
|
||||
protected $noNeedRight = '*';
|
||||
|
||||
private static $rateLimitKey = 'api_rate_limit:';
|
||||
private static $rateLimits = [
|
||||
'login' => ['max' => 20, 'window' => 300],
|
||||
'register' => ['max' => 10, 'window' => 3600],
|
||||
'resetpwd' => ['max' => 5, 'window' => 3600],
|
||||
'changepwd' => ['max' => 10, 'window' => 3600],
|
||||
'changeemail' => ['max' => 10, 'window' => 3600],
|
||||
'changemobile'=> ['max' => 10, 'window' => 3600],
|
||||
'sendEms' => ['max' => 10, 'window' => 300],
|
||||
'tokenLogin' => ['max' => 30, 'window' => 300],
|
||||
];
|
||||
|
||||
private static $testMode = false;
|
||||
|
||||
public function _initialize()
|
||||
{
|
||||
parent::_initialize();
|
||||
if (!Config::get('fastadmin.usercenter')) {
|
||||
$this->error(__('User center already closed'));
|
||||
}
|
||||
self::$testMode = Config::get('test_mode') ?: false;
|
||||
}
|
||||
|
||||
private function checkRateLimit($action)
|
||||
{
|
||||
if (!isset(self::$rateLimits[$action])) {
|
||||
return true;
|
||||
}
|
||||
$config = self::$rateLimits[$action];
|
||||
$key = self::$rateLimitKey . $action . ':' . $this->request->ip();
|
||||
$cache = cache($key);
|
||||
$count = $cache ? intval($cache) : 0;
|
||||
if ($count >= $config['max']) {
|
||||
$this->error('请求过于频繁,请稍后再试', null, ['retry_after' => $config['window']]);
|
||||
}
|
||||
cache($key, $count + 1, $config['window']);
|
||||
return true;
|
||||
}
|
||||
|
||||
private function sanitizeString($value, $maxLength = 255)
|
||||
{
|
||||
if (!is_string($value)) {
|
||||
return '';
|
||||
}
|
||||
$value = trim($value);
|
||||
$value = strip_tags($value);
|
||||
$value = htmlspecialchars($value, ENT_QUOTES, 'UTF-8');
|
||||
if (mb_strlen($value) > $maxLength) {
|
||||
$value = mb_substr($value, 0, $maxLength);
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
|
||||
private function validateLength($value, $field, $min = 1, $max = 255)
|
||||
{
|
||||
$len = mb_strlen($value);
|
||||
if ($len < $min || $len > $max) {
|
||||
$this->error("{$field}长度须在{$min}-{$max}之间");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private function detectMaliciousInput($value)
|
||||
{
|
||||
$patterns = [
|
||||
'/<script\b[^>]*>/i',
|
||||
'/javascript\s*:/i',
|
||||
'/on\w+\s*=/i',
|
||||
'/union\s+select/i',
|
||||
'/insert\s+into/i',
|
||||
'/delete\s+from/i',
|
||||
'/update\s+\w+\s+set/i',
|
||||
'/drop\s+table/i',
|
||||
'/\.\.[\/\\\\]/i',
|
||||
'/eval\s*\(/i',
|
||||
'/exec\s*\(/i',
|
||||
'/system\s*\(/i',
|
||||
];
|
||||
foreach ($patterns as $pattern) {
|
||||
if (preg_match($pattern, $value)) {
|
||||
$this->error('输入内容包含非法字符');
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private function isTestUser($userId)
|
||||
{
|
||||
if (!self::$testMode) {
|
||||
return false;
|
||||
}
|
||||
$user = db('user')->where('id', $userId)->find();
|
||||
return $user && isset($user['is_test']) && $user['is_test'] == 1;
|
||||
}
|
||||
|
||||
private function isTestEmail($email)
|
||||
{
|
||||
if (!self::$testMode) {
|
||||
return false;
|
||||
}
|
||||
$testEmails = Config::get('fastadmin.test_emails') ?: [];
|
||||
if (is_string($testEmails)) {
|
||||
$testEmails = explode(',', $testEmails);
|
||||
}
|
||||
return in_array($email, $testEmails);
|
||||
}
|
||||
|
||||
private function verifyEmsCode($email, $code, $event)
|
||||
{
|
||||
if (self::$testMode && $code === '888888') {
|
||||
return true;
|
||||
}
|
||||
return Ems::check($email, $code, $event);
|
||||
}
|
||||
|
||||
/**
|
||||
* @name 账号密码登录
|
||||
* @desc 支持用户名/邮箱+密码登录
|
||||
*/
|
||||
public function login()
|
||||
{
|
||||
$this->checkRateLimit('login');
|
||||
$account = $this->request->post('account', '', 'trim');
|
||||
$password = $this->request->post('password', '', 'trim');
|
||||
if (!$account || !$password) {
|
||||
$this->error(__('Invalid parameters'));
|
||||
}
|
||||
$this->validateLength($account, '账号', 2, 50);
|
||||
$this->validateLength($password, '密码', 6, 30);
|
||||
$this->detectMaliciousInput($account);
|
||||
$ret = $this->auth->login($account, $password);
|
||||
if ($ret) {
|
||||
$data = ['userinfo' => $this->auth->getUserinfo()];
|
||||
$this->success(__('Logged in successful'), $data);
|
||||
} else {
|
||||
$this->error($this->auth->getError());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @name 手机号登录
|
||||
* @desc 手机号+短信验证码登录,未注册自动注册
|
||||
*/
|
||||
public function mobilelogin()
|
||||
{
|
||||
$this->checkRateLimit('login');
|
||||
$mobile = $this->request->post('mobile', '', 'trim');
|
||||
$captcha = $this->request->post('captcha', '', 'trim');
|
||||
if (!$mobile || !$captcha) {
|
||||
$this->error(__('Invalid parameters'));
|
||||
}
|
||||
if (!Validate::regex($mobile, "^1\d{10}$")) {
|
||||
$this->error(__('Mobile is incorrect'));
|
||||
}
|
||||
$this->validateLength($captcha, '验证码', 4, 6);
|
||||
if (self::$testMode && $captcha === '888888') {
|
||||
$verified = true;
|
||||
} else {
|
||||
$verified = false;
|
||||
try {
|
||||
$verified = Sms::check($mobile, $captcha, 'mobilelogin');
|
||||
} catch (\Exception $e) {
|
||||
$this->error('短信验证服务暂不可用,请使用邮箱登录');
|
||||
}
|
||||
}
|
||||
if (!$verified) {
|
||||
$this->error(__('Captcha is incorrect'));
|
||||
}
|
||||
$user = \app\common\model\User::getByMobile($mobile);
|
||||
if ($user) {
|
||||
if ($user->status != 'normal') {
|
||||
$this->error(__('Account is locked'));
|
||||
}
|
||||
$ret = $this->auth->direct($user->id);
|
||||
} else {
|
||||
$ret = $this->auth->register($mobile, Random::alnum(), '', $mobile, []);
|
||||
}
|
||||
if ($ret) {
|
||||
try { Sms::flush($mobile, 'mobilelogin'); } catch (\Exception $e) {}
|
||||
$data = ['userinfo' => $this->auth->getUserinfo()];
|
||||
$this->success(__('Logged in successful'), $data);
|
||||
} else {
|
||||
$this->error($this->auth->getError());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @name Token令牌登录
|
||||
* @desc 使用已有Token直接登录
|
||||
*/
|
||||
public function tokenLogin()
|
||||
{
|
||||
$this->checkRateLimit('tokenLogin');
|
||||
$token = $this->request->post('token', '', 'trim');
|
||||
if (!$token) {
|
||||
$this->error(__('Invalid parameters'));
|
||||
}
|
||||
$this->validateLength($token, 'Token', 10, 128);
|
||||
$tokenInfo = \app\common\library\Token::get($token);
|
||||
if (!$tokenInfo) {
|
||||
$this->error('Token无效或已过期');
|
||||
}
|
||||
$ret = $this->auth->direct($tokenInfo['user_id']);
|
||||
if ($ret) {
|
||||
$data = ['userinfo' => $this->auth->getUserinfo()];
|
||||
$this->success(__('Logged in successful'), $data);
|
||||
} else {
|
||||
$this->error($this->auth->getError());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @name 用户注册
|
||||
* @desc 注册新用户,邮箱必填且需邮箱验证码
|
||||
*/
|
||||
public function register()
|
||||
{
|
||||
$this->checkRateLimit('register');
|
||||
$username = $this->request->post('username', '', 'trim');
|
||||
$password = $this->request->post('password', '', 'trim');
|
||||
$email = $this->request->post('email', '', 'trim');
|
||||
$emailCode = $this->request->post('email_code', '', 'trim');
|
||||
$mobile = $this->request->post('mobile', '', 'trim');
|
||||
$mobileCode = $this->request->post('mobile_code', '', 'trim');
|
||||
|
||||
if (!$username || !$password || !$email) {
|
||||
$this->error('用户名、密码和邮箱为必填项');
|
||||
}
|
||||
$this->validateLength($username, '用户名', 3, 30);
|
||||
$this->validateLength($password, '密码', 6, 30);
|
||||
$this->detectMaliciousInput($username);
|
||||
if (!preg_match('/^[a-zA-Z0-9_\x{4e00}-\x{9fa5}]+$/u', $username)) {
|
||||
$this->error('用户名只能包含字母、数字、下划线和中文');
|
||||
}
|
||||
if (!Validate::is($email, "email")) {
|
||||
$this->error(__('Email is incorrect'));
|
||||
}
|
||||
$this->validateLength($email, '邮箱', 5, 100);
|
||||
|
||||
if (\app\common\model\User::getByEmail($email)) {
|
||||
$this->error('该邮箱已被注册');
|
||||
}
|
||||
|
||||
if (!$emailCode) {
|
||||
$this->error('邮箱验证码为必填项');
|
||||
}
|
||||
$this->validateLength($emailCode, '邮箱验证码', 4, 6);
|
||||
if (!$this->verifyEmsCode($email, $emailCode, 'register')) {
|
||||
$this->error('邮箱验证码不正确');
|
||||
}
|
||||
|
||||
if ($mobile) {
|
||||
if (!Validate::regex($mobile, "^1\d{10}$")) {
|
||||
$this->error(__('Mobile is incorrect'));
|
||||
}
|
||||
if ($mobileCode) {
|
||||
if (!Sms::check($mobile, $mobileCode, 'register')) {
|
||||
$this->error(__('Captcha is incorrect'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$ret = $this->auth->register($username, $password, $email, $mobile, []);
|
||||
if ($ret) {
|
||||
Ems::flush($email, 'register');
|
||||
$userId = $this->auth->id;
|
||||
$verification = db('user')->where('id', $userId)->value('verification');
|
||||
$verification = $verification ? json_decode($verification, true) : [];
|
||||
$verification['email'] = 1;
|
||||
db('user')->where('id', $userId)->update(['verification' => json_encode($verification)]);
|
||||
$data = ['userinfo' => $this->auth->getUserinfo()];
|
||||
$this->success(__('Sign up successful'), $data);
|
||||
} else {
|
||||
$this->error($this->auth->getError());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @name 退出登录
|
||||
* @desc 清除Token,退出登录状态
|
||||
*/
|
||||
public function logout()
|
||||
{
|
||||
if (!$this->request->isPost()) {
|
||||
$this->error(__('Invalid parameters'));
|
||||
}
|
||||
$token = $this->request->header('token', '');
|
||||
if ($token) {
|
||||
\app\common\library\Token::delete($token);
|
||||
}
|
||||
$userId = $this->auth->id;
|
||||
if ($userId) {
|
||||
\app\common\library\Token::clear($userId);
|
||||
}
|
||||
$this->success(__('Logout successful'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @name 修改密码
|
||||
* @desc 修改密码需验证旧密码+邮箱验证码(双重验证)
|
||||
*/
|
||||
public function changepwd()
|
||||
{
|
||||
$this->checkRateLimit('changepwd');
|
||||
$user = $this->auth->getUser();
|
||||
$oldpassword = $this->request->post('oldpassword', '', 'trim');
|
||||
$newpassword = $this->request->post('newpassword', '', 'trim');
|
||||
$emailCode = $this->request->post('email_code', '', 'trim');
|
||||
|
||||
if (!$oldpassword || !$newpassword) {
|
||||
$this->error(__('Invalid parameters'));
|
||||
}
|
||||
$this->validateLength($oldpassword, '旧密码', 6, 30);
|
||||
$this->validateLength($newpassword, '新密码', 6, 30);
|
||||
|
||||
if ($this->isTestUser($user->id)) {
|
||||
$ret = $this->auth->changepwd($newpassword, $oldpassword);
|
||||
if ($ret) {
|
||||
$this->success(__('Change password successful'));
|
||||
} else {
|
||||
$this->error($this->auth->getError());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
$email = $user->email;
|
||||
if (!$email) {
|
||||
$this->error('请先绑定邮箱后再修改密码');
|
||||
}
|
||||
|
||||
if (!$emailCode) {
|
||||
$this->error('邮箱验证码为必填项');
|
||||
}
|
||||
$this->validateLength($emailCode, '邮箱验证码', 4, 6);
|
||||
if (!$this->verifyEmsCode($email, $emailCode, 'changepwd')) {
|
||||
$this->error('邮箱验证码不正确');
|
||||
}
|
||||
|
||||
$ret = $this->auth->changepwd($newpassword, $oldpassword);
|
||||
if ($ret) {
|
||||
Ems::flush($email, 'changepwd');
|
||||
$this->success(__('Change password successful'));
|
||||
} else {
|
||||
$this->error($this->auth->getError());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @name 重置密码
|
||||
* @desc 通过邮箱/手机验证码重置密码(无需登录)
|
||||
*/
|
||||
public function resetpwd()
|
||||
{
|
||||
$this->checkRateLimit('resetpwd');
|
||||
$type = $this->request->post("type", "email", 'trim');
|
||||
$mobile = $this->request->post("mobile", '', 'trim');
|
||||
$email = $this->request->post("email", '', 'trim');
|
||||
$newpassword = $this->request->post("newpassword", '', 'trim');
|
||||
$captcha = $this->request->post("captcha", '', 'trim');
|
||||
|
||||
if (!$newpassword || !$captcha) {
|
||||
$this->error(__('Invalid parameters'));
|
||||
}
|
||||
$this->validateLength($newpassword, '新密码', 6, 30);
|
||||
$this->validateLength($captcha, '验证码', 4, 6);
|
||||
|
||||
if ($type == 'mobile') {
|
||||
if (!Validate::regex($mobile, "^1\d{10}$")) {
|
||||
$this->error(__('Mobile is incorrect'));
|
||||
}
|
||||
$user = \app\common\model\User::getByMobile($mobile);
|
||||
if (!$user) {
|
||||
$this->error(__('User not found'));
|
||||
}
|
||||
if (!Sms::check($mobile, $captcha, 'resetpwd')) {
|
||||
$this->error(__('Captcha is incorrect'));
|
||||
}
|
||||
Sms::flush($mobile, 'resetpwd');
|
||||
} else {
|
||||
if (!Validate::is($email, "email")) {
|
||||
$this->error(__('Email is incorrect'));
|
||||
}
|
||||
$user = \app\common\model\User::getByEmail($email);
|
||||
if (!$user) {
|
||||
$this->error(__('User not found'));
|
||||
}
|
||||
if (!$this->verifyEmsCode($email, $captcha, 'resetpwd')) {
|
||||
$this->error('邮箱验证码不正确');
|
||||
}
|
||||
Ems::flush($email, 'resetpwd');
|
||||
}
|
||||
|
||||
$this->auth->direct($user->id);
|
||||
$ret = $this->auth->changepwd($newpassword, '', true);
|
||||
if ($ret) {
|
||||
$this->success(__('Reset password successful'));
|
||||
} else {
|
||||
$this->error($this->auth->getError());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @name 修改邮箱
|
||||
* @desc 修改邮箱需新邮箱验证码验证
|
||||
*/
|
||||
public function changeemail()
|
||||
{
|
||||
$this->checkRateLimit('changeemail');
|
||||
$user = $this->auth->getUser();
|
||||
$email = $this->request->post('email', '', 'trim');
|
||||
$captcha = $this->request->post('captcha', '', 'trim');
|
||||
|
||||
if (!$email || !$captcha) {
|
||||
$this->error(__('Invalid parameters'));
|
||||
}
|
||||
if (!Validate::is($email, "email")) {
|
||||
$this->error(__('Email is incorrect'));
|
||||
}
|
||||
$this->validateLength($email, '邮箱', 5, 100);
|
||||
$this->validateLength($captcha, '验证码', 4, 6);
|
||||
|
||||
if (\app\common\model\User::where('email', $email)->where('id', '<>', $user->id)->find()) {
|
||||
$this->error(__('Email already exists'));
|
||||
}
|
||||
|
||||
if (!$this->verifyEmsCode($email, $captcha, 'changeemail')) {
|
||||
$this->error(__('Captcha is incorrect'));
|
||||
}
|
||||
|
||||
$verification = $user->verification;
|
||||
$verification->email = 1;
|
||||
$user->verification = $verification;
|
||||
$user->email = $email;
|
||||
$user->save();
|
||||
Ems::flush($email, 'changeemail');
|
||||
$this->success();
|
||||
}
|
||||
|
||||
/**
|
||||
* @name 修改手机号
|
||||
* @desc 修改手机号需短信验证码验证
|
||||
*/
|
||||
public function changemobile()
|
||||
{
|
||||
$this->checkRateLimit('changemobile');
|
||||
$user = $this->auth->getUser();
|
||||
$mobile = $this->request->post('mobile', '', 'trim');
|
||||
$captcha = $this->request->post('captcha', '', 'trim');
|
||||
|
||||
if (!$mobile || !$captcha) {
|
||||
$this->error(__('Invalid parameters'));
|
||||
}
|
||||
if (!Validate::regex($mobile, "^1\d{10}$")) {
|
||||
$this->error(__('Mobile is incorrect'));
|
||||
}
|
||||
$this->validateLength($captcha, '验证码', 4, 6);
|
||||
|
||||
if (\app\common\model\User::where('mobile', $mobile)->where('id', '<>', $user->id)->find()) {
|
||||
$this->error(__('Mobile already exists'));
|
||||
}
|
||||
|
||||
if (self::$testMode && $captcha === '888888') {
|
||||
$result = true;
|
||||
} else {
|
||||
$result = false;
|
||||
try {
|
||||
$result = Sms::check($mobile, $captcha, 'changemobile');
|
||||
} catch (\Exception $e) {
|
||||
$this->error('短信验证服务暂不可用');
|
||||
}
|
||||
}
|
||||
if (!$result) {
|
||||
$this->error(__('Captcha is incorrect'));
|
||||
}
|
||||
|
||||
$verification = $user->verification;
|
||||
$verification->mobile = 1;
|
||||
$user->verification = $verification;
|
||||
$user->mobile = $mobile;
|
||||
$user->save();
|
||||
try { Sms::flush($mobile, 'changemobile'); } catch (\Exception $e) {}
|
||||
$this->success();
|
||||
}
|
||||
|
||||
/**
|
||||
* @name 发送邮箱验证码
|
||||
* @desc 发送邮箱验证码,支持多种事件类型
|
||||
*/
|
||||
public function sendEms()
|
||||
{
|
||||
$this->checkRateLimit('sendEms');
|
||||
$email = $this->request->post('email', '', 'trim');
|
||||
$event = $this->request->post('event', 'register', 'trim');
|
||||
|
||||
if (!$email) {
|
||||
$this->error('邮箱不能为空');
|
||||
}
|
||||
if (!Validate::is($email, "email")) {
|
||||
$this->error(__('Email is incorrect'));
|
||||
}
|
||||
|
||||
$allowedEvents = ['register', 'changepwd', 'resetpwd', 'changeemail'];
|
||||
if (!in_array($event, $allowedEvents)) {
|
||||
$this->error('无效的事件类型');
|
||||
}
|
||||
|
||||
$last = Ems::get($email, $event);
|
||||
if ($last && time() - $last['createtime'] < 60) {
|
||||
$this->error(__('发送频繁'));
|
||||
}
|
||||
|
||||
$userinfo = \app\common\model\User::getByEmail($email);
|
||||
if ($event == 'register' && $userinfo) {
|
||||
$this->error(__('已被注册'));
|
||||
} elseif ($event == 'changeemail' && $userinfo) {
|
||||
$this->error(__('已被占用'));
|
||||
} elseif (in_array($event, ['changepwd', 'resetpwd']) && !$userinfo) {
|
||||
$this->error(__('未注册'));
|
||||
}
|
||||
|
||||
$ret = Ems::send($email, null, $event);
|
||||
if ($ret) {
|
||||
$this->success(__('发送成功'));
|
||||
} else {
|
||||
$this->error(__('发送失败'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @name 校验邮箱验证码
|
||||
* @desc 校验邮箱验证码是否正确
|
||||
*/
|
||||
public function checkEms()
|
||||
{
|
||||
$email = $this->request->post('email', '', 'trim');
|
||||
$captcha = $this->request->post('captcha', '', 'trim');
|
||||
$event = $this->request->post('event', 'register', 'trim');
|
||||
|
||||
if (!$email || !$captcha) {
|
||||
$this->error(__('Invalid parameters'));
|
||||
}
|
||||
|
||||
$ret = $this->verifyEmsCode($email, $captcha, $event);
|
||||
if ($ret) {
|
||||
$this->success(__('验证码正确'));
|
||||
} else {
|
||||
$this->error(__('验证码不正确'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @name 第三方登录
|
||||
* @desc 第三方平台登录
|
||||
*/
|
||||
public function third()
|
||||
{
|
||||
$this->checkRateLimit('login');
|
||||
$url = url('user/index');
|
||||
$platform = $this->request->post("platform", '', 'trim');
|
||||
$code = $this->request->post("code", '', 'trim');
|
||||
$this->detectMaliciousInput($platform);
|
||||
$this->detectMaliciousInput($code);
|
||||
$config = get_addon_config('third');
|
||||
if (!$config || !isset($config[$platform])) {
|
||||
$this->error(__('Invalid parameters'));
|
||||
}
|
||||
$app = new \addons\third\library\Application($config);
|
||||
$result = $app->{$platform}->getUserInfo(['code' => $code]);
|
||||
if ($result) {
|
||||
$loginret = \addons\third\library\Service::connect($platform, $result);
|
||||
if ($loginret) {
|
||||
$data = [
|
||||
'userinfo' => $this->auth->getUserinfo(),
|
||||
'thirdinfo' => $result
|
||||
];
|
||||
$this->success(__('Logged in successful'), $data);
|
||||
}
|
||||
}
|
||||
$this->error(__('Operation failed'), $url);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user