536 lines
18 KiB
PHP
Raw Permalink Normal View History

2024-08-31 01:03:37 +08:00
<?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
*/
//用户管理【管理员配置用户or用户空间大小变更】
class adminMember extends Controller{
private $model;
function __construct() {
parent::__construct();
$this->model = Model('User');
$this->authCheck();
}
public function authCheck(){
if(KodUser::isRoot()) return;
if(MOD == 'install') return;
$data = Input::getArray(array(
"userID" => array("default"=>null),
"roleID" => array("default"=>2),
));
if(isset($data['userID']) && $data['userID'] == '1') {
show_json(LNG('admin.member.editNoAuth'), false);
}
$roleInfo = Model('SystemRole')->listData($data['roleID']);
if(!in_array(ACTION, array('admin.member.add', 'admin.member.edit'))) return;
if($roleInfo['administrator'] != 1) return; // 1为系统管理员
show_json(LNG('admin.member.editNoAuth'), false);
}
/**
* 根据所在部门获取用户列表
*/
public function get() {
$data = Input::getArray(array(
"groupID" => array("check"=>"require",'default'=>0),
"fields" => array("check"=>"require",'default'=>''),
"status" => array("default"=>null)
));
if(!$data['groupID']){show_json(array(),true);}
if($data['groupID'] == 1) $data['groupID'] = 0; // 根部门id=1获取全部用户
$result = $this->model->listByGroup($data['groupID'], $data);
$this->showUserfilterAllow($result['list']);
show_json($result,true);
}
/**
* 根据用户id获取信息
*/
public function getByID() {
$id = Input::get('id','[\d,]*');
$result = $this->model->listByID(explode(',',$id));
$this->showUserfilterAllow($result);
show_json($result,true);
}
/**
* 搜索用户
*/
public function search() {
$data = Input::getArray(array(
"words" => array("check"=>"require"),
"status" => array("default"=>null),
"parentGroup" => array("check"=>"require",'default'=>false),// 支持多个父部门,多个逗号隔开;
));
if(!$data['parentGroup']){
$result = $this->model->listSearch($data);
}else{
$groupArr = explode(',',$data['parentGroup']);$result = false;
foreach ($groupArr as $groupID) {
$data['parentGroup'] = intval($groupID);
$listSearch = $this->model->listSearch($data);
if(!$result){$result = $listSearch;continue;}
$result['list'] = array_merge($result['list'],$listSearch['list']);
}
if(is_array($result) && is_array($result['list'])){
$result = array_page_split(array_unique($result['list']),$result['pageInfo']['page'],$result['pageInfo']['pageNum']);
}
}
$this->showUserfilterAllow($result['list']);
show_json($result,true);
}
// 过滤不允许的用户信息(根据当前用户可见部门筛选)
private function showUserfilterAllow($list){
$userGroupRootShow = Action("filter.userGroup")->userGroupRootShow(); // 用户所在跟部门;可见范围
$userGroupAdmin = Action("filter.userGroup")->userGroupAdmin();// 用户所在部门为管理员的部门;
if(!$userGroupRootShow || !$list){return $list;}
// 获取完整用户信息, 有部门管理权限且该参数为full才返回用户完整信息,否则精简用户信息(去除邮箱,手机号等敏感信息)
$userAllow = array();
$requestAdmin = isset($this->in['requestFromType']) && $this->in['requestFromType'] == 'admin'; // 后端用户列表;
foreach ($list as $user){
$groupParentAll = array();
foreach ($user['groupInfo'] as $groupInfo){
$parents = Model('Group')->parentLevelArray($groupInfo['parentLevel']);
$groupParentAll = array_merge($parents,$groupParentAll,array($groupInfo['groupID']));
}
$groupParentAll = array_unique($groupParentAll);
$allowShow = array_intersect($groupParentAll,$userGroupRootShow) ? true : false; //是否有交集
$allowFull = array_intersect($groupParentAll,$userGroupAdmin) ? true : false;
if(KodUser::isRoot()){$allowFull = true;$allowShow = true;}//超级管理员(不受权限限制)
if(!$allowShow){continue;}
if($allowFull && $requestAdmin){$userAllow[] = $user;continue;}
$userItem = array();
$allowField = explode(',','userID,avatar,name,nickName,groupInfo');
foreach ($allowField as $key) {
$userItem[$key] = $user[$key];
}
$userAllow[] = $userItem;
}
// pr($userAllow,$list,$userGroupRootShow,$userGroupAdmin);exit;
return $userAllow;
}
/**
* 添加用户
*/
public function add() {
$this->import();
$data = Input::getArray(array(
"userID" => array("default"=>null),
"name" => array("check"=>"require"),
"sizeMax" => array("check"=>"float","default"=>1024*1024*100),
"roleID" => array("check"=>"int"),
"password" => array("check"=>"require"),
"email" => array("check"=>"email", "default"=>""),
"phone" => array("check"=>"phone", "default"=>""),
"nickName" => array("check"=>"require","default"=>""),
"avatar" => array("check"=>"require","default"=>""),
"sex" => array("check"=>"require","default"=>1),//0女1男
"status" => array("default"=>1),
));
if( !ActionCall('filter.userCheck.password',$data['password']) ){
return ActionCall('filter.userCheck.passwordTips');
}
// 1.添加用户
$res = $userID = $this->model->userAdd($data);
if($res <= 0) return show_json($this->model->errorLang($res),false);
// 初始化数据,不记录操作日志;
Model('SourceEvent')->recodeStop();
$groupInfo = json_decode($this->in['groupInfo'],true);
if(is_array($groupInfo)){
$this->model->userGroupSet($userID,$groupInfo,true);
}
// 2.添加用户默认配置
$userInfo = $this->model->getInfo($userID);
$this->settingDefault($userID);
// 3.添加用户默认目录
$sourceID = $userInfo['sourceInfo']['sourceID'];
$this->folderDefault($sourceID);
// 4.添加用户默认轻应用
$desktopID = $userInfo['sourceInfo']['desktop'];
$this->lightAppDefault($desktopID);
Model('SourceEvent')->recodeStart();
return show_json(LNG('explorer.success'), true, $userID);
}
/**
* 用户默认设置——主题、壁纸、界面样式选择等
*/
public function settingDefault($userID){
$default = $this->config['settingDefault'];
$insert = array();
foreach($default as $key => $value){
$insert[] = array(
'type' => '',
'userID' => $userID,
'key' => $key,
'value' => $value
);
}
Model('user_option')->addAll($insert);
}
/**
* 用户默认目录
*/
public function folderDefault($parentID){
$folderDefault = Model('SystemOption')->get('newUserFolder');
$folderList = explode(',', $folderDefault);
foreach($folderList as $name){
$path = "{source:{$parentID}}/" . $name;
IO::mkdir($path);
}
}
/**
* 添加用户轻应用
*/
public function lightAppDefault($desktop){
$list = Model('SystemLightApp')->listData();
$appList = array_to_keyvalue($list, 'name');
$appListID = array_to_keyvalue($list, 'id');
$defaultApp = Model('SystemOption')->get('newUserApp');
$defAppList = explode(',', $defaultApp);
foreach($defAppList as $name){
$app = _get($appListID,$name,_get($appList,$name));
if(!$app) continue;
// [user]/desktop/appName.oexe
$path = "{source:{$desktop}}/" . $app['name'] . '.oexe';
IO::mkfile($path, json_encode_force($app['content']));
}
}
/**
* 编辑
*/
public function edit() {
$data = Input::getArray(array(
"userID" => array("check"=>"int"), // userID=1可以编辑
"name" => array("check"=>"require","default"=>null),
"sizeMax" => array("check"=>"float", "default"=>null),
"roleID" => array("check"=>"int", "default"=>null),
"password" => array("check"=>"require","default"=>''),
"email" => array("check"=>"email", "default"=>null),
"phone" => array("check"=>"phone", "default"=>null),
"nickName" => array("check"=>"require","default"=>null),
"avatar" => array("check"=>"require","default"=>null),
"sex" => array("check"=>"require","default"=>null),//0女1男
"status" => array("check"=>"require","default"=>null),//0-未启用 1-启用
));
// 后台删除这些字段值时为空default=null时data不包含导致没有更新
foreach (array('email','phone','nickName') as $key) {
if (!isset($data[$key]) && isset($this->in[$key])) {
$data[$key] = '';
}
}
if( $data['password'] &&
!ActionCall('filter.userCheck.password',$data['password']) ){
return ActionCall('filter.userCheck.passwordTips');
}
// 不支持修改自己的权限角色;避免误操作;
if($data['userID'] == USER_ID && isset($data['roleID'])){
$user = Session::get('kodUser');
if($user['roleID'] != $data['roleID']){
return show_json(LNG('admin.member.errEditSelfRole'),false);
}
}
// 禁止修改超管角色
$userInfo = $this->model->getInfo($data['userID']);
if ($data['userID'] == '1' && $data['userID'] != USER_ID) {
if(isset($data['roleID']) && $data['roleID'] != $userInfo['roleID']){
return show_json(LNG('admin.member.errEditSelfRole'),false);
}
}
$dataSave = array();$groupSave = false; // 仅处理变化的内容;
foreach($data as $key => $value) {
if($key == 'userID') continue;
if($value == $userInfo[$key]) continue;
$dataSave[$key] = $value;
}
if($dataSave){$res = $this->model->userEdit($data['userID'],$dataSave);}
$groupInfo = json_decode($this->in['groupInfo'],true);
if(isset($this->in['groupInfo'])){
// 编辑用户,必须有至少一个默认部门; 即便是没有权限;
$groupInfo = is_array($groupInfo) ? $groupInfo : array();
$userGroup = array_to_keyvalue($userInfo['groupInfo'],'groupID','auth.id',true);
// 添加到指定部门时;保持原来所在部门权限不变;
$isGroupAppend = isset($this->in['groupInfoAppend']) && $this->in['groupInfoAppend'] == '1';
// 仅添加时,用户所在部门不在设置范围内则自动加入;
foreach ($userGroup as $groupID => $auth){
if($isGroupAppend && !isset($groupInfo[$groupID])){$groupInfo[$groupID] = $auth;}
}
if($userGroup != $groupInfo){
$groupSave = true;$res = 1;
$this->model->userGroupSet($data['userID'],$groupInfo,true);
}
}
$this->in['_change'] = $dataSave;
if($groupSave){$this->in['_change']['groupInfo'] = $_REQUEST['groupInfo'];}
if(!$dataSave && !$groupSave){$res = 1;}
$msg = $res > 0 ? LNG('explorer.success') : $this->model->errorLang($res);
return show_json($msg,($res>0),$data['userID']);
}
/**
* 添加到部门
*/
public function addGroup() {
$data = Input::getArray(array(
"userID" => array("check"=>"int"),
"groupInfo" => array("check"=>"json"),
));
$res = $this->model->userGroupAdd($data['userID'],$data['groupInfo']);
$msg = $res ? LNG('explorer.success') : LNG('explorer.error');
show_json($msg,!!$res);
}
/**
* 从部门删除
*/
public function removeGroup() {
$data = Input::getArray(array(
"userID" => array("check"=>"int"),
"groupID" => array("check"=>"int"),
));
$res = $this->model->userGroupRemove($data['userID'],$data['groupID']);
$msg = $res ? LNG('explorer.success') : LNG('explorer.error');
show_json($msg,!!$res);
}
/**
* 部门迁移
*/
public function switchGroup(){
$data = Input::getArray(array(
"userID" => array("check"=>"int"),
"from" => array("check"=>"int"),
"to" => array("check"=>"int"),
));
$userInfo = $this->model->getInfo($data['userID']);
if(!$userInfo) show_json(LNG('ERROR_USER_NOT_EXISTS'), false);
$authID = 0;
// 删除来源部门,新增到新部门
$groupInfo = !empty($userInfo['groupInfo']) ? $userInfo['groupInfo'] : array();
foreach($groupInfo as $item) {
if($item['groupID'] != $data['from']) continue;
if(isset($item['auth']['id'])) {
$authID = $item['auth']['id'];
}
$this->model->userGroupRemove($data['userID'],$item['groupID']);
break;
}
// 权限无效(无来源部门)时,取权限列表中第一个显示项
if (!$authID) {
$list = Model('Auth')->listData();
foreach ($list as $item) {
if ($item['display'] != '0') {
$authID = $item['id'];
break;
}
}
}
$groupInfo = array($data['to'] => $authID);
$res = $this->model->userGroupAdd($data['userID'],$groupInfo);
$msg = $res ? LNG('explorer.success') : LNG('explorer.error');
show_json($msg,!!$res);
}
/**
* 更新用户状态
*/
public function status(){
$data = Input::getArray(array(
"userID" => array("check"=>"int"),
"status" => array("check"=>"in", "param" => array(0, 1)),
));
$res = $this->model->userStatus($data['userID'], $data['status']);
$msg = $res ? LNG('explorer.success') : LNG('explorer.error');
show_json($msg,!!$res);
}
/**
* 删除
*/
public function remove() {
$id = Input::get('userID','bigger',null,1);
$res = $this->model->userRemove($id);
$msg = $res ? LNG('explorer.success') : LNG('explorer.error');
show_json($msg,!!$res);
}
/**
* 批量导入用户
* @return void
*/
private function import(){
if(!isset($this->in['isImport'])) return;
// 1.上传
if(empty($this->in['filePath'])) {
// 1.1 上传文件——返回前端:>100kb上传分多次请求无法直接获取结果
if (empty($this->in['path'])) {
$path = IO::mkdir(TEMP_FILES . 'import_' . time());
$this->in['path'] = $path;
Action('explorer.upload')->fileUpload();
}
// 1.2 获取上传文件内容
$file = $this->in['path'];
$data = $this->getImport($file);
del_file($file);
if(empty($data['list'])) show_json(LNG('admin.member.uploadInvalid'), false);
$filename = get_path_this($file);
Cache::set(md5('memberImport'.$filename), $data);
show_json('success', true, $filename);
}
$filename = Input::get('filePath','require');
// 获取新增用户进度
$taskId = md5('import-user-'.$filename);
if (isset($this->in['process'])) {
$cache = Cache::get($taskId);
if ($cache) {
Cache::remove($taskId);
show_json($cache,true,1);
}
$data = Task::get($taskId);
show_json($data);
}
Cache::remove($taskId);
// 2.读取数据并新增
$fileData = Cache::get(md5('memberImport'.$filename));
Cache::remove(md5('memberImport'.$filename));
if(!$fileData || empty($fileData['list'])) show_json(LNG('admin.member.uploadDataInvalid'), false);
$data = Input::getArray(array(
'sizeMax' => array('check' => 'require'),
'roleID' => array('check' => 'require'),
'groupInfo' => array('check' => 'require'),
));
$total = (int) $fileData['total'];
$task = new Task($taskId,'importUser',$total,LNG('admin.member.userImport'));
$error = array();
foreach($fileData['list'] as $value) {
$task->update(1);
if(!is_array($value)) continue;
$this->in = array_merge($value, $data);
$res = ActionCallHook('admin.member.add');
if (!$res['code']) $error[$this->in['name']] = $res['data'];
}
$task->task['error'] = $error;
Cache::set($taskId, $task->task);
$task->end();
$success = $total - count($error);
$info = array(
'total' => $total,
'success' => $success,
'error' => $error,
);
$code = (boolean) $success;
$data = $code ? LNG('admin.member.importSuccess') : LNG('admin.member.importFail');
show_json($data, $code, $info);
}
// 获取csv分隔符——编辑后的csv文件不一定是默认的','
private function getCsvSep($line) {
if (empty($line)) return ',';
$data = array();
$separators = array(',', ';', ':', "\t", '|');
foreach ($separators as $separator) {
$fields = explode($separator, $line);
$fields = array_filter($fields, 'trim');
$data[$separator] = count($fields);
}
// 找到字段数量最多的分隔符
$maxCnt = max($data);
return array_search($maxCnt, $data);
}
/**
* 获取导入文件数据
* @param [type] $file
* @return void
*/
private function getImport($file){
if (!$handle = fopen($file, 'r')) {
del_file($file);
show_json('read file error.', false);
}
$line = fgets($handle); // 获取分隔符
$separator = $this->getCsvSep(trim($line));
$dataList = array();
while (($data = fgetcsv($handle,0,$separator)) !== false) {
$dataList[] = $data;
}
fclose($handle);
// 2.获取列表数据
unset($dataList[0]);
$dataList = array_filter($dataList);
$list = array();
$keys = array('name'=>'','nickName'=>'','password'=>'','sex'=>1,'phone'=>'','email'=>'');
foreach($dataList as $value) {
$tmp = array();
$i = 0;
foreach($keys as $key => $val) {
$val = trim($value[$i]);
$i++;
if($key == 'name' && empty($val)) break;
if($key == 'password' && empty($val)) break;
if (is_null($val)) $val = '';
switch($key) {
case 'name':
case 'nickName':
$val = $this->iconvValue($val);
break;
case 'sex':
$val = $val != '0' ? 1 : 0;
break;
case 'phone':
case 'email':
$val = preg_replace('/[\x00-\x1F\x7F-\xFF]/', '', $val); // 删除不可见的特殊字符如null
if(!Input::check($val, $key)) $val = '';
break;
default: break;
}
$tmp[$key] = $val;
}
if(empty($tmp) || empty($tmp['name']) || empty($tmp['password'])) continue;
if(isset($list[$tmp['name']])) continue;
$list[$tmp['name']] = array_merge($keys,$tmp);
}
return array(
'list' => array_values($list),
'total' => count($list),
);
}
// 部分文件转换无效
private function iconvValue($value){
// $encoding = array('GB2312', 'GBK', 'GB18030', 'UTF-8', 'ASCII', 'BIG5');
// $charset = mb_detect_encoding($value,$encoding);
// $value = iconv_to($value,$charset,'utf-8');
$charset = get_charset($value);
if(!in_array($charset,array('utf-8','ascii'))){
$value = iconv_to($value, $charset, 'utf-8');
}
return $value;
}
}