<?php
namespace php4world;
use think\Db;
use think\facade\Config;
use think\facade\Session;
use think\facade\Request;
class Auth
{
protected $_config = [
'auth_on' => true, 'auth_type' => 1, 'auth_group' => 'auth_group', 'auth_group_access' => 'auth_group_access', 'auth_rule' => 'auth_rule', 'auth_user' => 'user', 'auth_user_id_field'=> 'id', 'administrator' => [1], ];
public function __construct()
{
$auth = Config::get('app.auth');
if (!empty($auth)) {
$this->_config = array_merge($this->_config, $auth);
}
}
public function check($name, $uid, $relation = 'or', $mode = 'url')
{
if (!$this->_config['auth_on']) {
return true;
}
if (!empty($this->_config['administrator']) && in_array($uid, $this->_config['administrator'])) {
return true;
}
$authlist = $this->getAuthList($uid);
if (is_string($name)) {
$name = strtolower($name);
if (strpos($name, ',') === false) {
$name = [$name];
} else {
$name = explode(',', $name);
}
}
$list = [];
if ($mode === 'url') {
$REQUEST = unserialize(strtolower(serialize(Request::param())));
}
foreach ($authlist as $auth) {
$query = preg_replace('/^.+\?/U', '', $auth);
if ($mode === 'url' && $query !== $auth) {
parse_str($query, $param);
$intersect = array_intersect_assoc($REQUEST, $param);
$auth = preg_replace('/\?.*$/U', '', $auth);
if (in_array($auth, $name) && $intersect == $param) {
$list[] = $auth;
}
} elseif (in_array($auth, $name)) {
$list[] = $auth;
}
}
if ($relation === 'or' && !empty($list)) {
return true;
}
$diff = array_diff($name, $list);
if ($relation === 'and' && empty($diff)) {
return true;
}
return false;
}
public function getGroups($uid)
{
static $groups = [];
if (isset($groups[$uid])) {
return $groups[$uid];
}
$user_groups = Db::table($this->_config['auth_group_access'])
->alias('a')
->join($this->_config['auth_group'].' g', "a.group_id = g.id")
->field('uid,group_id,title,rules')
->where('a.uid', $uid)
->where('g.status', 1)
->select();
$groups[$uid] = $user_groups ?: [];
return $groups[$uid];
}
protected function getAuthList($uid)
{
static $_authlist = [];
if (isset($_authlist[$uid])) {
return $_authlist[$uid];
}
if ($this->_config['auth_type'] === 2 && Session::has('_auth_list_'.$uid)) {
return Session::get('_auth_list_'.$uid);
}
$groups = $this->getGroups($uid);
$ids = []; foreach ($groups as $g) {
$ids = array_merge($ids, explode(',', trim($g['rules'], ',')));
}
$ids = array_unique($ids);
if (empty($ids)) {
$_authlist[$uid] = [];
return [];
}
$map = [
['id', 'in', $ids],
['status', '=', 1] ];
$rules = Db::table($this->_config['auth_rule'])->where($map)->field('condition,name')->select();
$authlist = [];
foreach ($rules as $rule) {
if (!empty($rule['condition'])) { $user = $this->getUserInfo($uid);
$command = preg_replace('/\{(\w*?)\}/', '$user[\'\\1\']', $rule['condition']);
@(eval('$condition=('.$command.');'));
if ($condition) {
$authlist[] = strtolower($rule['name']);
}
} else {
$authlist[] = strtolower($rule['name']);
}
}
$_authlist[$uid] = $authlist;
if ($this->_config['auth_type'] == 2) {
Session::set('_auth_list_'.$uid, $authlist);
}
return array_unique($authlist);
}
protected function getUserInfo($uid) {
static $userinfo = [];
if (!isset($userinfo[$uid])) {
$userinfo[$uid] = Db::table($this->_config['auth_user'])->where((string)$this->_config['auth_user_id_field'], $uid)->find();
}
return $userinfo[$uid];
}
}