DiverseYouthNightSchool/application/manystoreapi/library/Auth.php

858 lines
26 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace app\manystoreapi\library;
use app\common\library\Token;
use app\common\model\User;
use app\common\model\UserRule;
use app\manystore\model\Manystore;
use fast\Random;
use fast\Tree;
use think\Config;
use think\Cookie;
use think\Db;
use think\Exception;
use think\Hook;
use think\Request;
use think\Session;
use think\Validate;
class Auth extends ManystoreAuth
{
protected static $instance = null;
protected $_error = '';
protected $_logined = false;
protected $_user = null;
protected $_token = '';
//Token默认有效时长
protected $keeptime = 2592000;
protected $requestUri = '';
protected $rules = [];
// //默认配置
// protected $config = [];
protected $options = [];
protected $allowFields = ['id','username', 'nickname', 'avatar','user_id', 'email',"shop_id"];
protected $breadcrumb = [];
protected $init_data = [
'table' => 'manystore_token',
'type' => 'Mysql',
'userprefix' => 'shopup:',
'tokenprefix' => 'shoptp:',
];
// protected $config = [
// 'auth_on' => 1, // 权限开关
// 'auth_type' => 1, // 认证方式1为实时认证2为登录认证。
// 'auth_group' => 'manystore_api_auth_group', // 用户组数据表名
// 'auth_group_access' => 'manystore_api_auth_group_access', // 用户-用户组关系表
// 'auth_rule' => 'manystore_api_auth_rule', // 权限规则表
// 'auth_user' => 'user', // 用户信息表
// ];
// public function __construct(Request $request = null)
// {
//
// // 控制器初始化
// $this->_initialize();
//
// // 前置操作方法
// if ($this->beforeActionList) {
// foreach ($this->beforeActionList as $method => $options) {
// is_numeric($method) ?
// $this->beforeAction($options) :
// $this->beforeAction($method, $options);
// }
// }
// }
/**
*
* @param array $options 参数
* @return \app\common\library\Auth
*/
public static function instance($options = [])
{
if (is_null(self::$instance)) {
self::$instance = new static($options);
}
return self::$instance;
}
/**
* 获取User模型
* @return User
*/
public function getUser()
{
return $this->_user;
}
/**
* 兼容调用user模型的属性
*
* @param string $name
* @return mixed
*/
public function __get($name)
{
$res = Session::get('manystoreapi.' . $name);
if($res)return $res;
return $this->_user ? $this->_user->$name : null;
}
/**
* 兼容调用user模型的属性
*/
public function __isset($name)
{
return isset($this->_user) ? isset($this->_user->$name) : false;
}
/**
* 根据Token初始化
*
* @param string $token Token
* @return boolean
*/
public function init($token)
{
if ($this->_logined) {
return true;
}
if ($this->_error) {
return false;
}
$data = Token::init($this->init_data)->get($token) ?:false;
if(!$data){
$manystoreapi = Session::get('manystoreapi');
if($manystoreapi){
$data["user_id"] = $manystoreapi['id'];
}
}
if (!$data) {
return false;
}
$user_id = intval($data['user_id']);
if ($user_id > 0) {
$user = Manystore::get($user_id);
if (!$user) {
$this->setError('Account not exist');
return false;
}
if ($user['status'] != 'normal') {
$this->setError('Account is locked');
return false;
}
$this->_user = $user;
$this->_logined = true;
$this->_token = $token;
//初始化成功的事件
Hook::listen("manystore_init_successed", $this->_user);
return true;
} else {
$this->setError('You are not logged in');
return false;
}
}
/**
* 管理员登录
*
* @param string $username 用户名
* @param string $password 密码
* @param int $keeptime 有效时长
* @return boolean
*/
public function login($username, $password, $keeptime = 0)
{
$manystore = Manystore::get(['username' => $username]);
if (!$manystore) {
$user = User::where("mobile",$username)->find();
if($user){
$manystore = Manystore::get(['user_id' => $user["id"]]);
}
}
if (!$manystore) {
$this->setError('Username is incorrect');
return false;
}
if ($manystore['status'] == 'hidden') {
$this->setError('Admin is forbidden');
return false;
}
if (Config::get('fastadmin.login_failure_retry') && $manystore->loginfailure >= 10 && time() - $manystore->updatetime < 86400) {
$this->setError('Please try again after 1 day');
return false;
}
if ($manystore->password != md5(md5($password) . $manystore->salt)) {
$manystore->loginfailure++;
$manystore->save();
$this->setError('Password is incorrect');
return false;
}
$this->direct($manystore->id);
return true;
}
/**
* 退出
*
* @return boolean
*/
public function logout()
{
if (!$this->_logined) {
$this->setError('You are not logged in');
return false;
}
//设置登录标识
$this->_logined = false;
//删除Token
Token::init($this->init_data)->delete($this->_token) ?:false;
Session::delete("manystoreapi");
Cookie::delete("keeplogin");
//退出成功的事件
Hook::listen("manystore_logout_successed", $this->_user);
return true;
}
/**
* 修改密码
* @param string $newpassword 新密码
* @param string $oldpassword 旧密码
* @param bool $ignoreoldpassword 忽略旧密码
* @return boolean
*/
public function changepwd($newpassword, $oldpassword = '', $ignoreoldpassword = false)
{
if (!$this->_logined) {
$this->setError('You are not logged in');
return false;
}
//判断旧密码是否正确
if ($this->_user->password == $this->getEncryptPassword($oldpassword, $this->_user->salt) || $ignoreoldpassword) {
Db::startTrans();
try {
$salt = Random::alnum();
$newpassword = $this->getEncryptPassword($newpassword, $salt);
$this->_user->save(['loginfailure' => 0, 'password' => $newpassword, 'salt' => $salt]);
// Token::delete($this->_token);
Token::init($this->init_data)->delete($this->_token) ?:false;
//修改密码成功的事件
Hook::listen("manystore_changepwd_successed", $this->_user);
Db::commit();
} catch (Exception $e) {
Db::rollback();
$this->setError($e->getMessage());
return false;
}
return true;
} else {
$this->setError('Password is incorrect');
return false;
}
}
/**
* 直接登录账号
* @param int $user_id
* @return boolean
*/
public function direct($user_id)
{
$manystore = Manystore::get($user_id);
if ($manystore) {
Db::startTrans();
try {
$ip = request()->ip();
$time = time();
$manystore->loginfailure = 0;
$manystore->logintime = time();
$manystore->loginip = request()->ip();
$manystore->token = Random::uuid();
$manystore->save();
$this->_user = $manystore;
$this->_token = Random::uuid();
// Token::set($this->_token, $user->id, $this->keeptime);
Token::init($this->init_data)->set($this->_token, $manystore->id, $this->keeptime);
$this->_logined = true;
//登录成功的事件
Hook::listen("manystore_login_successed", $this->_user);
Session::set("manystoreapi", $manystore->toArray());
Db::commit();
} catch (Exception $e) {
Db::rollback();
$this->setError($e->getMessage());
return false;
}
return true;
} else {
return false;
}
}
/**
* 判断是否登录
* @return boolean
*/
public function isLogin()
{
if ($this->_logined) {
return true;
}
return false;
}
public function check($name, $uid = '', $relation = 'or', $mode = 'url')
{
$uid = $uid ? $uid : $this->id;
return parent::check($name, $uid, $relation, $mode);
}
/**
* 获取当前Token
* @return string
*/
public function getToken()
{
return $this->_token;
}
/**
* 获取会员基本信息
*/
public function getUserinfo()
{
$data = $this->_user->toArray();
$allowFields = $this->getAllowFields();
$userinfo = array_intersect_key($data, array_flip($allowFields));
$userinfo = array_merge($userinfo, Token::init($this->init_data)->get($this->_token));
return $userinfo;
}
/**
* 获取当前请求的URI
* @return string
*/
public function getRequestUri()
{
return $this->requestUri;
}
/**
* 设置当前请求的URI
* @param string $uri
*/
public function setRequestUri($uri)
{
$this->requestUri = $uri;
}
/**
* 获取允许输出的字段
* @return array
*/
public function getAllowFields()
{
return $this->allowFields;
}
/**
* 设置允许输出的字段
* @param array $fields
*/
public function setAllowFields($fields)
{
$this->allowFields = $fields;
}
/**
* 删除一个指定会员
* @param int $user_id 会员ID
* @return boolean
*/
public function delete($user_id)
{
$user = Manystore::get($user_id);
if (!$user) {
return false;
}
Db::startTrans();
try {
// 删除会员
Manystore::destroy($user_id);
// 删除会员指定的所有Token
// Token::clear($user_id);
Token::init($this->init_data)->clear($user_id);
Hook::listen("manystore_delete_successed", $user);
Db::commit();
} catch (Exception $e) {
Db::rollback();
$this->setError($e->getMessage());
return false;
}
return true;
}
/**
* 获取密码加密后的字符串
* @param string $password 密码
* @param string $salt 密码盐
* @return string
*/
public function getEncryptPassword($password, $salt = '')
{
return md5(md5($password) . $salt);
}
/**
* 检测当前控制器和方法是否匹配传递的数组
*
* @param array $arr 需要验证权限的数组
* @return boolean
*/
public function match($arr = [])
{
$request = Request::instance();
$arr = is_array($arr) ? $arr : explode(',', $arr);
if (!$arr) {
return false;
}
$arr = array_map('strtolower', $arr);
// 是否存在
if (in_array(strtolower($request->action()), $arr) || in_array('*', $arr)) {
return true;
}
// 没找到匹配
return false;
}
// /**
// * 检测是否登录
// *
// * @return boolean
// */
// public function isLogin()
// {
// if ($this->logined) {
// return true;
// }
// $manystore = Session::get('manystore');
// if (!$manystore) {
// return false;
// }
// //判断是否同一时间同一账号只能在一个地方登录
// if (Config::get('fastadmin.login_unique')) {
// $my = Manystore::get($manystore['id']);
// if (!$my || $my['token'] != $manystore['token']) {
// $this->logout();
// return false;
// }
// }
// //判断管理员IP是否变动
// if (Config::get('fastadmin.loginip_check')) {
// if (!isset($manystore['loginip']) || $manystore['loginip'] != request()->ip()) {
// $this->logout();
// return false;
// }
// }
// $this->logined = true;
// return true;
// }
/**
* 设置会话有效时间
* @param int $keeptime 默认为永久
*/
public function keeptime($keeptime = 0)
{
$this->keeptime = $keeptime;
}
/**
* 渲染用户数据
* @param array $datalist 二维数组
* @param mixed $fields 加载的字段列表
* @param string $fieldkey 渲染的字段
* @param string $renderkey 结果字段
* @return array
*/
public function render(&$datalist, $fields = [], $fieldkey = 'user_id', $renderkey = 'userinfo')
{
$fields = !$fields ? ['id', 'nickname', 'username', 'avatar'] : (is_array($fields) ? $fields : explode(',', $fields));
$ids = [];
foreach ($datalist as $k => $v) {
if (!isset($v[$fieldkey])) {
continue;
}
$ids[] = $v[$fieldkey];
}
$list = [];
if ($ids) {
if (!in_array('id', $fields)) {
$fields[] = 'id';
}
$ids = array_unique($ids);
$selectlist = Manystore::where('id', 'in', $ids)->column($fields);
foreach ($selectlist as $k => $v) {
$list[$v['id']] = $v;
}
}
foreach ($datalist as $k => &$v) {
$v[$renderkey] = $list[$v[$fieldkey]] ?? null;
}
unset($v);
return $datalist;
}
public function getGroups($uid = null)
{
$uid = is_null($uid) ? $this->id : $uid;
return parent::getGroups($uid);
}
public function getRuleList($uid = null)
{
$uid = is_null($uid) ? $this->id : $uid;
return parent::getRuleList($uid);
}
// public function getUserInfo($uid = null)
// {
// $uid = is_null($uid) ? $this->id : $uid;
//
// return $uid != $this->id ? Manystore::get(intval($uid)) : Session::get('manystore');
// }
public function getRuleIds($uid = null)
{
$uid = is_null($uid) ? $this->id : $uid;
return parent::getRuleIds($uid);
}
public function isSuperAdmin()
{
return in_array('*', $this->getRuleIds()) ? true : false;
}
/**
* 获取管理员所属于的分组ID
* @param int $uid
* @return array
*/
public function getGroupIds($uid = null)
{
$groups = $this->getGroups($uid);
$groupIds = [];
foreach ($groups as $K => $v) {
$groupIds[] = (int)$v['group_id'];
}
return $groupIds;
}
/**
* 取出当前管理员所拥有权限的分组
* @param boolean $withself 是否包含当前所在的分组
* @return array
*/
public function getChildrenGroupIds($withself = false)
{
//取出当前管理员所有的分组
$groups = $this->getGroups();
$groupIds = [];
foreach ($groups as $k => $v) {
$groupIds[] = $v['id'];
}
$originGroupIds = $groupIds;
foreach ($groups as $k => $v) {
if (in_array($v['pid'], $originGroupIds)) {
$groupIds = array_diff($groupIds, [$v['id']]);
unset($groups[$k]);
}
}
// 取出所有分组
$groupList = \app\manystore\model\ManystoreAuthGroup::where(['shop_id'=>SHOP_ID,'status' => 'normal'])->select();
$objList = [];
foreach ($groups as $k => $v) {
if ($v['rules'] === '*') {
$objList = $groupList;
break;
}
// 取出包含自己的所有子节点
$childrenList = Tree::instance()->init($groupList)->getChildren($v['id'], true);
$obj = Tree::instance()->init($childrenList)->getTreeArray($v['pid']);
$objList = array_merge($objList, Tree::instance()->getTreeList($obj));
}
$childrenGroupIds = [];
foreach ($objList as $k => $v) {
$childrenGroupIds[] = $v['id'];
}
if (!$withself) {
$childrenGroupIds = array_diff($childrenGroupIds, $groupIds);
}
return $childrenGroupIds;
}
/**
* 取出当前管理员所拥有权限的管理员
* @param boolean $withself 是否包含自身
* @return array
*/
public function getChildrenAdminIds($withself = false)
{
$childrenAdminIds = [];
if (!$this->isSuperAdmin()) {
$groupIds = $this->getChildrenGroupIds(false);
$authGroupList = \app\manystore\model\ManystoreAuthGroupAccess::
field('uid,group_id')
->where('group_id', 'in', $groupIds)
->select();
foreach ($authGroupList as $k => $v) {
$childrenAdminIds[] = $v['uid'];
}
} else {
//超级管理员拥有所有人的权限
$where = [];
$where['shop_id'] = SHOP_ID;
if($this->getUserInfo()['is_main'] == 0){
$where['is_main'] = 0;
}
$childrenAdminIds = Manystore::where($where)->column('id');
}
if ($withself) {
if (!in_array($this->id, $childrenAdminIds)) {
$childrenAdminIds[] = $this->id;
}
} else {
$childrenAdminIds = array_diff($childrenAdminIds, [$this->id]);
}
return $childrenAdminIds;
}
/**
* 获得面包屑导航
* @param string $path
* @return array
*/
public function getBreadCrumb($path = '')
{
// var_dump($this->breadcrumb);
if ($this->breadcrumb || !$path) {
// var_dump($path);die;
return $this->breadcrumb;
}
$path_rule_id = 0;
// var_dump($this->rules);die;
foreach ($this->rules as $rule) {
$path_rule_id = $rule['name'] == $path ? $rule['id'] : $path_rule_id;
}
if ($path_rule_id) {
$this->breadcrumb = Tree::instance()->init($this->rules)->getParents($path_rule_id, true);
foreach ($this->breadcrumb as $k => &$v) {
$v['url'] = url($v['name']);
$v['title'] = __($v['title']);
}
}
return $this->breadcrumb;
}
/**
* 获取左侧和顶部菜单栏
*
* @param array $params URL对应的badge数据
* @param string $fixedPage 默认页
* @return array
*/
public function getSidebar($params = [], $fixedPage = 'dashboard')
{
// 边栏开始
Hook::listen("admin_sidebar_begin", $params);
$colorArr = ['red', 'green', 'yellow', 'blue', 'teal', 'orange', 'purple'];
$colorNums = count($colorArr);
$badgeList = [];
$module = request()->module();
// 生成菜单的badge
foreach ($params as $k => $v) {
$url = $k;
if (is_array($v)) {
$nums = isset($v[0]) ? $v[0] : 0;
$color = isset($v[1]) ? $v[1] : $colorArr[(is_numeric($nums) ? $nums : strlen($nums)) % $colorNums];
$class = isset($v[2]) ? $v[2] : 'label';
} else {
$nums = $v;
$color = $colorArr[(is_numeric($nums) ? $nums : strlen($nums)) % $colorNums];
$class = 'label';
}
//必须nums大于0才显示
if ($nums) {
$badgeList[$url] = '<small class="' . $class . ' pull-right bg-' . $color . '">' . $nums . '</small>';
}
}
// 读取管理员当前拥有的权限节点
$userRule = $this->getRuleList();
$selected = $referer = [];
$refererUrl = Session::get('referer');
$pinyin = new \Overtrue\Pinyin\Pinyin('Overtrue\Pinyin\MemoryFileDictLoader');
// 必须将结果集转换为数组
$ruleList = collection(\app\manystore\model\ManystoreApiAuthRule::where('status', 'normal')
->where('ismenu', 1)
->order('weigh', 'desc')
->cache("__manystore_api_menu__")
->select())->toArray();
$indexRuleList = \app\manystore\model\ManystoreApiAuthRule::where('status', 'normal')
->where('ismenu', 0)
->where('name', 'like', '%/index')
->column('name,pid');
// var_dump($ruleList);
$pidArr = array_filter(array_unique(array_map(function ($item) {
return $item['pid'];
}, $ruleList)));
foreach ($ruleList as $k => &$v) {
if (!in_array($v['name'], $userRule)) {
unset($ruleList[$k]);
continue;
}
$indexRuleName = $v['name'] . '/index';
if (isset($indexRuleList[$indexRuleName]) && !in_array($indexRuleName, $userRule)) {
unset($ruleList[$k]);
continue;
}
$v['icon'] = $v['icon'] . ' fa-fw';
$v['url'] = '/' . $module . '/' . $v['name'];
$v['badge'] = isset($badgeList[$v['name']]) ? $badgeList[$v['name']] : '';
$v['py'] = $pinyin->abbr($v['title'], '');
$v['pinyin'] = $pinyin->permalink($v['title'], '');
$v['title'] = __($v['title']);
$selected = $v['name'] == $fixedPage ? $v : $selected;
$referer = url($v['url']) == $refererUrl ? $v : $referer;
}
$lastArr = array_diff($pidArr, array_filter(array_unique(array_map(function ($item) {
return $item['pid'];
}, $ruleList))));
foreach ($ruleList as $index => $item) {
if (in_array($item['id'], $lastArr)) {
unset($ruleList[$index]);
}
}
if ($selected == $referer) {
$referer = [];
}
$selected && $selected['url'] = url($selected['url']);
$referer && $referer['url'] = url($referer['url']);
$select_id = $selected ? $selected['id'] : 0;
$menu = $nav = '';
$menu = $ruleList;
return [$menu, $nav, $selected, $referer];
if (Config::get('fastadmin.multiplenav')) {
$topList = [];
foreach ($ruleList as $index => $item) {
if (!$item['pid']) {
$topList[] = $item;
}
}
$selectParentIds = [];
$tree = Tree::instance();
$tree->init($ruleList);
if ($select_id) {
$selectParentIds = $tree->getParentsIds($select_id, true);
}
foreach ($topList as $index => $item) {
$childList = Tree::instance()->getTreeMenu(
$item['id'],
'<li class="@class" pid="@pid"><a href="@url@addtabs" addtabs="@id" url="@url" py="@py" pinyin="@pinyin"><i class="@icon"></i> <span>@title</span> <span class="pull-right-container">@caret @badge</span></a> @childlist</li>',
$select_id,
'',
'ul',
'class="treeview-menu"'
);
$current = in_array($item['id'], $selectParentIds);
$url = $childList ? 'javascript:;' : url($item['url']);
$addtabs = $childList || !$url ? "" : (stripos($url, "?") !== false ? "&" : "?") . "ref=addtabs";
$childList = str_replace(
'" pid="' . $item['id'] . '"',
' treeview ' . ($current ? '' : 'hidden') . '" pid="' . $item['id'] . '"',
$childList
);
$nav .= '<li class="' . ($current ? 'active' : '') . '"><a href="' . $url . $addtabs . '" addtabs="' . $item['id'] . '" url="' . $url . '"><i class="' . $item['icon'] . '"></i> <span>' . $item['title'] . '</span> <span class="pull-right-container"> </span></a> </li>';
$menu .= $childList;
}
} else {
// 构造菜单数据
Tree::instance()->init($ruleList);
$menu = Tree::instance()->getTreeMenu(
0,
'<li class="@class"><a href="@url@addtabs" addtabs="@id" url="@url" py="@py" pinyin="@pinyin"><i class="@icon"></i> <span>@title</span> <span class="pull-right-container">@caret @badge</span></a> @childlist</li>',
$select_id,
'',
'ul',
'class="treeview-menu"'
);
if ($selected) {
$nav .= '<li role="presentation" id="tab_' . $selected['id'] . '" class="' . ($referer ? '' : 'active') . '"><a href="#con_' . $selected['id'] . '" node-id="' . $selected['id'] . '" aria-controls="' . $selected['id'] . '" role="tab" data-toggle="tab"><i class="' . $selected['icon'] . ' fa-fw"></i> <span>' . $selected['title'] . '</span> </a></li>';
}
if ($referer) {
$nav .= '<li role="presentation" id="tab_' . $referer['id'] . '" class="active"><a href="#con_' . $referer['id'] . '" node-id="' . $referer['id'] . '" aria-controls="' . $referer['id'] . '" role="tab" data-toggle="tab"><i class="' . $referer['icon'] . ' fa-fw"></i> <span>' . $referer['title'] . '</span> </a> <i class="close-tab fa fa-remove"></i></li>';
}
}
return [$menu, $nav, $selected, $referer];
}
/**
* 设置错误信息
*
* @param string $error 错误信息
* @return Auth
*/
public function setError($error)
{
$this->_error = $error;
return $this;
}
/**
* 获取错误信息
* @return string
*/
public function getError()
{
return $this->_error ? __($this->_error) : '';
}
}