2024-08-31 01:03:37 +08:00

262 lines
9.4 KiB
PHP
Executable File
Raw Permalink 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
/*
* @link http://kodcloud.com/
* @author warlee | e-mail:kodcloud@qq.com
* @copyright warlee 2014.(Shanghai)Co.,Ltd
* @license http://kodcloud.com/tools/license/license.txt
*/
/**
* 用户角色,全局权限拦截;
*/
class userAuthRole extends Controller {
protected static $authRole;
function __construct() {
parent::__construct();
}
public function authCanSearch(){return $this->authCan('explorer.search');}
public function authCanRead(){return $this->authCan('explorer.view');}
public function authCanEdit(){return $this->authCan('explorer.edit');}
public function authCanDownload(){return $this->authCan('explorer.download');}
public function authCan($action){ // action 区分大小写; 与$config['authRoleAction'] key保持一致;
if(KodUser::isRoot()) return true;
$userRole = $this->userRoleAuth();
return $userRole['roleList'][$action] == 1 ? true : false;
}
// 获取指定用户角色信息;用户被禁用时, 开启了禁用用户时屏蔽该用户分享时则不再可用;
public function userRoleGet($userID){
$user = Model('User')->getInfo($userID);
if(!$user || !$user['roleID']) return false;//用户不存在或角色为空;
if($user['status'] == '0' && Model('SystemOption')->get('shareLinkUserDisableSkip') == '1'){return false;}
$roleInfo = $this->userRoleAuth($user['roleID']);
return $roleInfo ? $roleInfo:false;
}
// 根据用户角色判断用户,是否启用某个动作(后台配置角色的权限点)
public function authCanUser($action,$userID){
$userRole = $this->userRoleGet($userID);
if(!$userRole) return false;
if($userRole['info']['administrator'] == 1){return true;}
return $userRole['roleList'][$action] == 1 ? true : false;
}
// 未登录:允许的 控制器方法;
// 已登录:不允许的 控制器&方法;
// 其他的可以通过内部Action进行方法调用转发
public function autoCheck(){
$theMod = strtolower(MOD);
$theST = strtolower(ST);
$theAction = strtolower(ACTION);
$authNotNeedLogin = $this->config['authNotNeedLogin'];
foreach ($authNotNeedLogin as &$val) {
$val = strtolower($val);
};unset($val);
if(in_array($theAction,$authNotNeedLogin)) return;
foreach ($authNotNeedLogin as $value) {
$item = explode('.',$value); //MOD,ST,ACT
if( count($item) == 2 &&
$item[0] === $theMod && $item[1] === '*'){
return;
}
if( count($item) == 3 &&
$item[0] === $theMod && $item[1] === $theST &&$item[2] === '*'){
return;
}
}
// 排除不需要登录的方法;其他的都需要登录
$user = Session::get("kodUser");
if(!is_array($user)){
if(Session::get('kodUserLogoutTrigger')){
Session::destory();Cookie::remove('kodToken');
show_json(LNG('user.logoutTrigger'),ERROR_CODE_USER_INVALID);
}
show_json(LNG('user.loginFirst'),ERROR_CODE_LOGOUT);
}
$this->authShareLinkUpdate();//分享拆分,老数据迁移;
//系统管理员不受权限限制
if(KodUser::isRoot()) return true;
$userRole = $this->userRoleAuth();
$allowAction = $userRole['allowAction'];
// pr($allowAction[$theAction],$theAction,$user,$userRole);exit;
if(!$allowAction[$theAction]){ //不存在该方法或
show_json(LNG('explorer.noPermissionAction'),false,1004);
}
}
// 用户权限解析处理;处理成最终动作
public function userRoleAuth($roleID=false){
if(!$roleID){
$user = Session::get('kodUser');
if(!$user || !$user['roleID']) return false;
$roleID = $user['roleID'];
}
if(!self::$authRole){self::$authRole = array();}
if(isset(self::$authRole[$roleID])){
return self::$authRole[$roleID];
}
$roleInfo = Model('SystemRole')->listData($roleID);
$userRoleAllow = $this->authCheckAlias($roleInfo['auth']);
$authRoleList = array();$allowAction = array();
foreach ($this->config['authRoleAction'] as $role => $modelActions) {
$enable = intval(in_array($role,$userRoleAllow));
$authRoleList[$role] = $enable;
if(!$modelActions || !is_array($modelActions)) continue;
$actionArray = array();
foreach ($modelActions as $controller => $stActions) {
if(!$stActions) continue;
$stActions = explode(',',trim($stActions,','));
foreach ($stActions as $action) {
$actionArray[] = $controller.'.'.$action;
}
}
foreach ($actionArray as $action) {
$action = strtolower($action);//统一转为小写
if(!isset($allowAction[$action])){
$allowAction[$action] = $enable;
continue;
}
// 重复action点允许true值覆盖的动作,(权限在内部判断)
if(in_array($role,$this->config['authRoleActionKeepTrue'])){
if($enable){$allowAction[$action] = $enable;}
continue;
}
/**
* false可以覆盖true;true不能覆盖false;
* 'explorer.download' => array('explorer.index'=>'zipDownload...')
* 'explorer.zip' => array('explorer.index'=>'zipDownload...')
*/
if($allowAction[$action]){
$allowAction[$action] = $enable;
}
}
}
//不需要检测的动作白名单; 优先级最高;
foreach ($this->config['authAllowAction'] as $action) {
$allowAction[strtolower($action)] = 1;
}
$result = array(
'info' => $roleInfo,
'allowAction' => $allowAction,
'roleList' => $authRoleList
);
self::$authRole[$roleID] = $result;
return $result;
}
// 操作时,再根据用户权限角色判断是否允许;
public function canCheckRole($action){
$actionMap = array(
// 'show' => true, //不判断查看;
'view' => array('explorer.view'),
'download' => array('explorer.download'),
'upload' => array('explorer.upload'),
'edit' => array('explorer.edit'),
'remove' => array('explorer.remove'),
'comment' => array('explorer.edit'),
'event' => array('explorer.edit'),
'root' => array('explorer.edit'),
// 'share' => array('explorer.share','explorer.shareLink'), // 不判定; 在explorer.userShare.checkRoleAuth中判断;
);
if(!isset($actionMap[$action])){return true;}
//动作可对应多个角色权限点; 任意一个满足则满足;
foreach ($actionMap[$action] as $key){
if($this->authCan($key)){return true;}
}
return false;
}
/**
* 角色权限升级,老数据处理(1.44)
* 分享拆分为=内部协作分享+外链分享 原explorer.share 拆分为 explorer.share+explorer.shareLink
* 用户编辑拆分为=用户编辑+用户权限设置; 原admin.member.userEdit 拆分为 admin.member.userEdit+admin.member.userAuth
*/
private function authShareLinkUpdate(){
$model = Model("SystemOption");
$key = 'explorerShareUpate';$type = 'system';
if($model->get($key,$type) == '1.01') return;
$model->remove($key,$type);$model->set($key,'1.01',$type);
$roleList = Model('SystemRole')->listData();
foreach ($roleList as $role){
$auth = $role['auth'];
if(!strstr($role['auth'],'explorer.shareLink')){
$auth = str_replace('explorer.share','explorer.share,explorer.shareLink',$auth);
}
if(!strstr($role['auth'],'admin.member.userAuth')){
$auth = str_replace('admin.member.userEdit','admin.member.userEdit,admin.member.userAuth',$auth);
}
if($auth == $role['auth']) continue;
$role['auth'] = $auth;
Model('SystemRole')->update($role['id'],$role);
}
}
// 处理权限前置依赖;
private function authCheckAlias($auth){
$authList = explode(',',trim($auth,','));
$alias = array(
'explorer.add' => 'explorer.view',
'explorer.download' => 'explorer.view',
'explorer.share' => 'explorer.view,explorer.upload,explorer.add,explorer.download',
'explorer.shareLink' => 'explorer.view,explorer.download',//explorer.upload,explorer.add,
// 'explorer.upload' => 'explorer.add',
'explorer.edit' => 'explorer.add,explorer.view,explorer.upload',
'explorer.remove' => 'explorer.edit',
'explorer.move' => 'explorer.edit',
'explorer.unzip' => 'explorer.edit',
'explorer.zip' => 'explorer.edit',
'explorer.serverDownload' => 'explorer.edit',
'admin.role.edit' => 'admin.role.list',
'admin.job.edit' => 'admin.job.list',
'admin.member.userEdit' => 'admin.member.list',
'admin.member.groupEdit'=> 'admin.member.list',
'admin.auth.edit' => 'admin.auth.list',
'admin.plugin.edit' => 'admin.plugin.list',
'admin.storage.edit' => 'admin.storage.list',
'admin.autoTask.edit' => 'admin.autoTask.list',
// 'a'=>'a','c'=>'d','d'=>'c', // 循环依赖处理;
// 'x1'=>'x2,x3','x3'=>'x1,x2',
);
foreach ($alias as $theKey => $aliasAction){
$alias[$theKey] = explode(',', $aliasAction);
}
$aliasAll = array();//key以来的所有上层key;
foreach ($alias as $theKey => $aliasAction){
$aliasAll[$theKey] = $this->authCheckAliasParent($theKey,$alias);
}
$userRoleAllow = array();
for ($i=0; $i < count($authList); $i++){
$authAction = $authList[$i];
if(!isset($aliasAll[$authAction])){
$userRoleAllow[] = $authList[$i];continue;
}
// 所有依赖都在当前权限中,才算拥有该权限;
$needAuth = $aliasAll[$authAction];$allHave = true;
for ($j=0; $j < count($needAuth); $j++) {
if(!in_array($needAuth[$j],$authList)) {$allHave = false;break;}
}
if($allHave){$userRoleAllow[] = $authList[$i];}
}
return $userRoleAllow;
}
private function authCheckAliasParent($theKey,&$alias,&$result=array()){
$parents = _get($alias, $theKey, '');
if(!$parents) return false;
for ($i=0; $i < count($parents); $i++) {
if(isset($result[$parents[$i]])) continue;
$result[$parents[$i]] = true;
$this->authCheckAliasParent($parents[$i],$alias,$result);
}
return array_keys($result);
}
}