Files
yusheng-php/application/guildadmin/controller/Admin.php

764 lines
28 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\guildadmin\controller;
use app\admin\command\Menu;
use app\guildadmin\model\AuthGroup;
use app\guildadmin\model\AuthGroupAccess;
use app\guildadmin\model\AuthRule;
use app\common\controller\GuildAdmin;
use fast\Random;
use fast\Tree;
use think\Cache;
use think\Db;
use think\Exception;
use think\Session;
use think\Validate;
/**
* 管理员管理
*
* @icon fa fa-users
* @remark 一个管理员可以有多个角色组,左侧的菜单根据管理员所拥有的权限进行生成
*/
class Admin extends GuildAdmin
{
/**
* @var \app\admin\model\Admin
*/
protected $model = null;
protected $authRuleModel = null;
protected $childrenGroupIds = [];
protected $childrenAdminIds = [];
protected $guildId = null;
public function _initialize()
{
parent::_initialize();
$this->model = model('guildadmin/Admin');
$this->authRuleModel = model('guildadmin/AuthRule');
$this->authGroup = model('guildadmin/AuthGroup');
$this->guildId = Session::get('guild_id');
$this->childrenAdminIds = $this->auth->getChildrenAdminIds($this->auth->isSuperAdmin());
$this->childrenGroupIds = $this->auth->getChildrenGroupIds($this->auth->isSuperAdmin());
if($this->auth->id ==1){
$groupList = collection(AuthGroup::where('id', 'in', $this->childrenGroupIds)->select())->toArray();
}else{
$groupList = collection(AuthGroup::where('id', 'in', $this->childrenGroupIds)->where('guild_id', $this->guildId)->select())->toArray();
}
Tree::instance()->init($groupList);
$groupdata = [];
if ($this->auth->isSuperAdmin()) {
$result = Tree::instance()->getTreeList(Tree::instance()->getTreeArray(0));
foreach ($result as $k => $v) {
$groupdata[$v['id']] = $v['name'];
}
} else {
$result = [];
$groups = $this->auth->getGroups();
foreach ($groups as $m => $n) {
$childlist = Tree::instance()->getTreeList(Tree::instance()->getTreeArray($n['id']));
$temp = [];
foreach ($childlist as $k => $v) {
$temp[$v['id']] = $v['name'];
}
$result[__($n['name'])] = $temp;
}
$groupdata = $result;
}
$this->assignconfig("admin", ['id' => $this->auth->id]);
$this->childrenGroupIds = $this->auth->getChildrenGroupIds(true);
$groupList = collection(AuthGroup::where('id', 'in', $this->childrenGroupIds)->where('guild_id', $this->guildId)->select())->toArray();
Tree::instance()->init($groupList);
$groupList = [];
if ($this->auth->isSuperAdmin()) {
$groupList = Tree::instance()->getTreeList(Tree::instance()->getTreeArray(1));
} else {
$groups = $this->auth->getGroups();
$groupIds = [];
foreach ($groups as $m => $n) {
if (in_array($n['id'], $groupIds) || in_array($n['pid'], $groupIds)) {
continue;
}
$groupList = array_merge($groupList, Tree::instance()->getTreeList(Tree::instance()->getTreeArray($n['pid'])));
foreach ($groupList as $index => $item) {
$groupIds[] = $item['id'];
}
}
}
$groupName = [];
foreach ($groupList as $k => $v) {
$groupName[$v['id']] = $v['name'];
}
$this->grouplist = $groupList;
$this->groupdata = $groupName;
$this->assignconfig("admin", ['id' => $this->auth->id, 'group_ids' => $this->auth->getGroupIds()]);
$ruleList = db::name("vs_guild_admin_auth")->field('type,condition,remark,createtime,updatetime', true)->where('status', "normal")->order('weigh DESC,id ASC')->select();
foreach ($ruleList as $k => &$v) {
$v['title'] = __($v['title']);
}
unset($v);
Tree::instance()->init($ruleList);
$this->rulelist = Tree::instance()->getTreeArray(0);
$ruledata = [0 => __('None')];
foreach ($this->rulelist as $k => &$v) {
if (!$v['ismenu']) {
continue;
}
$ruledata[$v['id']] = $v['title'];
unset($v['spacer']);
}
unset($v);
}
/**
* 权限列表
*/
public function auth_index()
{
$ruleList = db::name("vs_guild_admin_auth")->field('type,condition,remark,createtime,updatetime', true)->order('weigh DESC,id ASC')->select();
foreach ($ruleList as $k => &$v) {
$v['title'] = __($v['title']);
}
unset($v);
Tree::instance()->init($ruleList);
$ruleList = Tree::instance()->getTreeArray(0);
$ruledata = [0 => __('None')];
foreach ($ruleList as $k => &$v) {
if (!$v['ismenu']) {
continue;
}
$ruledata[$v['id']] = $v['title'];
unset($v['spacer']);
}
unset($v);
$list = $ruleList;
$total = count($ruleList);
$result = array("total" => $total, "rows" => $list);
return V(1,"菜单规则列表", $result);
}
/**
* 权限添加
*/
public function auth_add()
{
if ($this->request->isPost()) {
$params = $this->request->post();
if ($params) {
if (!$params['ismenu'] && !$params['pid']) {
return V(0,'非菜单规则节点必须有父级', null);
}
$result = $this->authRuleModel->validate('app\admin\validate\AuthRule')->save($params);
if ($result === false) {
return V(0,'操作失败', null);
}
return V(1,'操作成功', null);
}
return V(0,'操作失败', null);
}
return V(0,'操作失败', null);
}
/**
* 权限编辑
*/
public function auth_edit($ids = NULL)
{
if ($this->request->isPost()) {
$params = $this->request->post();
if ($params) {
if (!$params['ismenu'] && !$params['pid']) {
return V(0,'非菜单规则节点必须有父级', null);
}
if ($params['pid'] == $params['id']) {
return V(0,'父级不能是它自己', null);
}
if ($params['pid'] != $params['pid']) {
$childrenIds = Tree::instance()->init(collection(AuthRule::select())->toArray())->getChildrenIds($params['id']);
if (in_array($params['pid'], $childrenIds)) {
return V(0,'父组别不能是它的子组别', null);
}
}
//这里需要针对name做唯一验证
$ruleValidate = \think\Loader::validate('app\admin\validate\AuthRule');
$ruleValidate->rule([
'name' => 'require|unique:AuthRule,name,' . $params['id'],
]);
$result = $this->authRuleModel->validate('app\admin\validate\AuthRule')->save($params, $params['id']);
if ($result === false) {
return V(0,'操作失败', null);
}
return V(1,'操作成功', null);
}
return V(0,'操作失败', null);
}
}
/*
* 权限详情
*/
public function auth_detail(){
$id = $this->request->param('id');
$row = $this->authRuleModel->get($id);
if (!$row) {
return V(0,'操作失败', null);
}
return V(1,"详情", $row);
}
/**
* 权限删除
*/
public function auth_del($ids = "")
{
$ids = input('ids', '');
if ($ids) {
$delIds = [];
foreach (explode(',', $ids) as $k => $v) {
$delIds = array_merge($delIds, Tree::instance()->getChildrenIds($v, true));
}
$delIds = array_unique($delIds);
$count = $this->authRuleModel->where('id', 'in', $delIds)->delete();
if ($count) {
Cache::rm('__guild_menu__');
return V(1,'操作成功', null);return V(1,'操作成功', null);
}
}
return V(0,'操作失败', null);
}
/*
* 菜单接口
*/
public function menus(){
$ruleList = Tree::instance()->getTreeArray(0);
$ruleList = $this->getTree($ruleList,['title','url','name','icon','extend']);
return V(1,"系统菜单接口", $ruleList);
}
public function getTree($ruleList,$fieldData=[]){
$ruledata = [];
$i= 0;
foreach ($ruleList as $k => &$v) {
if (!$v['ismenu']) {
continue;
}
if(!$this->auth->check($v['name'])){
continue;
}
foreach ($fieldData as $key => $value) {
$ruledata[$i][$value] = $v[$value];
}
if(!empty($v['childlist'])){
$ruledata[$i]['childlist'] = $this->getTree($v['childlist'],$fieldData);
if(empty($ruledata[$i]['childlist'])){
unset($ruledata[$i]['childlist']);
}
}
$i++;
}
return $ruledata;
}
/**
* 角色列表
*/
public function role_index()
{
$list = $this->grouplist;
$total = count($list);
$result = array("total" => $total, "list" => $list);
return V(1,"角色管理列表", $result);
}
/**
* 角色添加
*/
public function role_add()
{
if ($this->request->isPost()) {
$params = $this->request->post();
$params['rules'] = explode(',', $params['rules']);
if (!in_array($params['pid'], $this->childrenGroupIds)) {
return V(0,'请选择正确的父角色', null);
}
$parentmodel = model("guildadmin/AuthGroup")->get($params['pid']);
if (!$parentmodel) {
return V(0,'请选择正确的父角色', null);
}
// 父级别的规则节点
$parentrules = explode(',', $parentmodel->rules);
// 当前组别的规则节点
$currentrules = $this->auth->getRuleIds();
$rules = $params['rules'];
// 如果父组不是超级管理员则需要过滤规则节点,不能超过父组别的权限
$rules = in_array('*', $parentrules) ? $rules : array_intersect($parentrules, $rules);
// 如果当前组别不是超级管理员则需要过滤规则节点,不能超当前组别的权限
$rules = in_array('*', $currentrules) ? $rules : array_intersect($currentrules, $rules);
$params['rules'] = implode(',', $rules);
if ($params) {
$params['guild_id'] = $this->guildId;
$this->authGroup->create($params);
return V(1,"成功", null);
}
return V(0,'操作失败', null);
}
return V(0,'操作失败', null);
}
/**
* 角色编辑
*/
public function role_edit($ids = null)
{
$params = $this->request->post();
$id = $params['id'];
if (!in_array($id, $this->childrenGroupIds)) {
return V(0,'你没有权限访问', null);
}
$row = $this->authGroup->get(['id' => $id]);
if (!$row) {
return V(0,'角色不存在', null);
}
if ($this->request->isPost()) {
//父节点不能是非权限内节点
if (!in_array($params['pid'], $this->childrenGroupIds)) {
return V(0,'请选择正确的父角色', null);
}
// 父节点不能是它自身的子节点或自己本身
if (in_array($params['pid'], Tree::instance()->getChildrenIds($row->id, true))) {
return V(0,'父节点不能是它自身的子节点或自己本身', null);
}
$params['rules'] = explode(',', $params['rules']);
$parentmodel = model("guildadmin/AuthGroup")->get($params['pid']);
if (!$parentmodel) {
return V(0,'请选择正确的父角色', null);
}
// 父级别的规则节点
$parentrules = explode(',', $parentmodel->rules);
// 当前组别的规则节点
$currentrules = $this->auth->getRuleIds();
$rules = $params['rules'];
// 如果父组不是超级管理员则需要过滤规则节点,不能超过父组别的权限
$rules = in_array('*', $parentrules) ? $rules : array_intersect($parentrules, $rules);
// 如果当前组别不是超级管理员则需要过滤规则节点,不能超当前组别的权限
$rules = in_array('*', $currentrules) ? $rules : array_intersect($currentrules, $rules);
$params['rules'] = implode(',', $rules);
if ($params) {
Db::startTrans();
try {
$row->save($params);
$children_auth_groups = model("guildadmin/AuthGroup")->all(['id' => ['in', implode(',', (Tree::instance()->getChildrenIds($row->id)))]]);
$childparams = [];
foreach ($children_auth_groups as $key => $children_auth_group) {
$childparams[$key]['id'] = $children_auth_group->id;
$childparams[$key]['rules'] = implode(',', array_intersect(explode(',', $children_auth_group->rules), $rules));
}
model("guildadmin/AuthGroup")->saveAll($childparams);
Db::commit();
return V(1,"成功", null);
} catch (Exception $e) {
Db::rollback();
return V(0,'操作失败', null);
}
}
return V(0,'操作失败', null);
}
}
/*
* 角色详情
*/
public function role_detail(){
$id =input('id', 0);
if (!$id) {
return V(0,'参数错误', null);
}
$row = $this->authGroup->get($id);
if (!$row) {
return V(0,'数据不存在', null);
}
return V(1,'成功', $row);
}
/**
* 角色删除
*/
public function role_del($ids = null)
{
$ids = $ids ? $ids : $this->request->post("ids");
if (!$ids) {
return V(0,'参数错误', null);
}
$ids = explode(',', $ids);
$grouplist = $this->auth->getGroups();
$group_ids = array_map(function ($group) {
return $group['id'];
}, $grouplist);
// 移除掉当前管理员所在组别
$ids = array_diff($ids, $group_ids);
// 循环判断每一个组别是否可删除
$grouplist = $this->authGroup->where('id', 'in', $ids)->select();
$groupaccessmodel = model('guildadmin/AuthGroupAccess');
foreach ($grouplist as $k => $v) {
// 当前组别下有管理员
$groupone = $groupaccessmodel->get(['group_id' => $v['id']]);
if ($groupone) {
$ids = array_diff($ids, [$v['id']]);
continue;
}
// 当前组别下有子组别
$groupone = $this->authGroup->get(['pid' => $v['id']]);
if ($groupone) {
$ids = array_diff($ids, [$v['id']]);
continue;
}
}
$count = $this->authGroup->where('id', 'in', $ids)->delete();
if ($count) {
return V(1,'成功', $count);
}
return V(0,'操作失败', null);
}
/**
* 读取角色权限树
*
* @internal
*/
public function role_tree()
{
$model = model('guildadmin/AuthGroup');
$id = $this->request->post("id");
$pid = $this->request->post("pid");
$parentGroupModel = $model->get($pid);
$currentGroupModel = null;
if ($id) {
$currentGroupModel = $model->get($id);
}
if (($pid || $parentGroupModel) && (!$id || $currentGroupModel)) {
$id = $id ? $id : null;
$ruleList = collection(model('guildadmin/AuthRule')->order('weigh', 'desc')->order('id', 'asc')->select())->toArray();
//读取父类角色所有节点列表
$parentRuleList = [];
if (in_array('*', explode(',', $parentGroupModel->rules))) {
$parentRuleList = $ruleList;
} else {
$parentRuleIds = explode(',', $parentGroupModel->rules);
foreach ($ruleList as $k => $v) {
if (in_array($v['id'], $parentRuleIds)) {
$parentRuleList[] = $v;
}
}
}
$ruleTree = new Tree();
$groupTree = new Tree();
//当前所有正常规则列表
$ruleTree->init($parentRuleList);
//角色组列表
$groupTree->init(collection(model('guildadmin/AuthGroup')->where('id', 'in', $this->childrenGroupIds)->select())->toArray());
//读取当前角色下规则ID集合
$adminRuleIds = $this->auth->getRuleIds();
//是否是超级管理员
$superadmin = $this->auth->isSuperAdmin();
//当前拥有的规则ID集合
$currentRuleIds = $id ? explode(',', $currentGroupModel->rules) : [];
if (!$id || !in_array($pid, $this->childrenGroupIds) || !in_array($pid, $groupTree->getChildrenIds($id, true))) {
$parentRuleList = $ruleTree->getTreeList($ruleTree->getTreeArray(0), 'name');
$hasChildrens = [];
foreach ($parentRuleList as $k => $v) {
if ($v['haschild']) {
$hasChildrens[] = $v['id'];
}
}
$parentRuleIds = array_map(function ($item) {
return $item['id'];
}, $parentRuleList);
$nodeList = [];
foreach ($parentRuleList as $k => $v) {
if (!$superadmin && !in_array($v['id'], $adminRuleIds)) {
continue;
}
if ($v['pid'] && !in_array($v['pid'], $parentRuleIds)) {
continue;
}
$state = array('selected' => in_array($v['id'], $currentRuleIds) && !in_array($v['id'], $hasChildrens));
$nodeList[] = array('id' => $v['id'], 'parent' => $v['pid'] ? $v['pid'] : '#', 'text' => __($v['title']), 'type' => 'menu', 'state' => $state);
}
return V(1,'成功', $nodeList);
} else {
return V(0,'父组别不能是它的子组别或它自己', null);
}
} else {
return V(0,'角色未找到', null);
}
}
/**
* 查看
*/
public function admin_index()
{
//设置过滤方法
$this->request->filter(['strip_tags', 'trim']);
//如果发送的来源是Selectpage则转发到Selectpage
if ($this->request->request('keyField')) {
return $this->selectpage();
}
$childrenGroupIds = $this->childrenGroupIds;
$groupName = AuthGroup::where('id', 'in', $childrenGroupIds)
->column('id,name');
$authGroupList = AuthGroupAccess::where('group_id', 'in', $childrenGroupIds)
->field('uid,group_id')
->select();
$adminGroupName = [];
foreach ($authGroupList as $k => $v) {
if (isset($groupName[$v['group_id']])) {
$adminGroupName[$v['uid']][$v['group_id']] = $groupName[$v['group_id']];
}
}
$groups = $this->auth->getGroups();
foreach ($groups as $m => $n) {
$adminGroupName[$this->auth->id][$n['id']] = $n['name'];
}
list($where, $sort, $order, $offset, $limit) = $this->buildparams();
$guild_where = [];
if($this->auth->id != 1){
$guild_where['guild_id'] = $this->guildId;
$guild_where['id'] = ['in', $this->childrenAdminIds];
}
$list = $this->model
->where($where)
->where($guild_where)
->field(['password', 'salt', 'token'], true)
->order($sort, $order)
->paginate($limit);
foreach ($list as $k => &$v) {
$groups = isset($adminGroupName[$v['id']]) ? $adminGroupName[$v['id']] : [];
$v['groups'] = implode(',', array_keys($groups));
$v['groups_text'] = implode(',', array_values($groups));
}
unset($v);
$result = array("total" => $list->total(), "rows" => $list->items());
return V(1,"管理员列表", $result);
}
/**
* 管理员添加
* username
* email
* mobile
* nickname
* password
* status
*/
public function admin_add()
{
$params = $this->request->Post();
if (empty($params)) {
return V(0,"参数错误", []);
}
if (!Validate::is($params['password'], '\S{6,30}')) {
return V(0,"密码长度必须在6-30位之间不能包含空格", []);
}
$group = $params['group'];
unset($params['group']);
unset($params['__token__']);
$group = explode(',',$group);
if ($params) {
Db::startTrans();
try {
$params['salt'] = Random::alnum();
$params['password'] = $this->auth->getEncryptPassword($params['password'], $params['salt']);
$params['avatar'] = '/assets/img/avatar.png'; //设置新管理员默认头像。
$params['guild_id'] = $this->guildId;
$result = $this->model->save($params);
if ($result === false) {
return V(0,"失败", []);
}
//过滤不允许的组别,避免越权
$group = array_intersect($this->childrenGroupIds, $group);
if (!$group) {
return V(0,"失败", []);
}
$dataset = [];
foreach ($group as $value) {
$dataset[] = ['uid' => $this->model->id, 'group_id' => $value];
}
model('guildadmin/AuthGroupAccess')->saveAll($dataset);
Db::commit();
return V(1,"添加成功", []);
} catch (\Exception $e) {
Db::rollback();
return V(0,"失败", []);
$this->error($e->getMessage());
}
}
}
/**
* 管理员编辑
*/
public function admin_edit($ids = null)
{
if ($this->request->isPost()) {
$params = $this->request->post();
$group = $params['group']?? [];
unset($params['group']);
unset($params['__token__']);
if($group){
$group = explode(',',$group);
}
if ($params) {
Db::startTrans();
try {
if ($params['password']) {
if (!Validate::is($params['password'], '\S{6,30}')) {
return V(0,"密码长度必须在6-30位之间不能包含空格", []);
}
$params['salt'] = Random::alnum();
$params['password'] = $this->auth->getEncryptPassword($params['password'], $params['salt']);
} else {
unset($params['password'], $params['salt']);
}
//这里需要针对username和email做唯一验证
$adminValidate = \think\Loader::validate('admin/Admin');
$adminValidate->rule([
'username' => 'require|regex:\w{3,30}|unique:admin,username,' . $params['id'],
'email' => 'require|email|unique:admin,email,' . $params['id'],
'mobile' => 'regex:1[3-9]\d{9}|unique:admin,mobile,' . $params['id'],
'password' => 'regex:\S{32}',
]);
$result = $this->model->save($params, $params['id']);
if ($result === false) {
return V(0,"失败", []);
}
if(!empty($group)){
// 先移除所有权限
model('guildadmin/AuthGroupAccess')->where('uid', $params['id'])->delete();
// 过滤不允许的组别,避免越权
$group = array_intersect($this->childrenGroupIds, $group);
if (!$group) {
return V(0,"失败", []);
}
$dataset = [];
foreach ($group as $value) {
$dataset[] = ['uid' => $params['id'], 'group_id' => $value];
}
model('guildadmin/AuthGroupAccess')->saveAll($dataset);
}
Db::commit();
return V(1,"成功", []);
} catch (\Exception $e) {
Db::rollback();
return V(0,"失败", []);
}
}
return V(0,"参数错误!", []);
}else{
return V(0,"参数错误!", []);
}
}
/*
* 管理员详情
*
*/
public function admin_detail($ids = ""){
$id = $this->request->get('id');
if (!$id) {
return V(0,"未找到记录", []);
}
if (!in_array($id, $this->childrenAdminIds)) {
return V(0,"你没有权限访问", []);
}
$data = $this->model->where('id',$id)->find();
$grouplist = $this->auth->getGroups($id);
$groupids = [];
foreach ($grouplist as $k => $v) {
$groupids[] = $v['id'];
}
$result = [];
$result['row'] = $data;
$result['groupids'] = $groupids;
return V(1,"管理员详情", $result);
}
/*
* 管理员状态修改
*/
public function admin_change_status(){
if (!$this->request->isPost()) {
return V(0,"失败", []);
}
$id = $this->request->post("id");
if (empty($id)) {
return V(0,"失败", []);
}
if($id==1){
return V(0,"超级管理员不能修改状态", []);
}
$status = $this->request->post("status");
$data = [];
$data['status'] = $status;
$res = Db::name("vs_guild_admin")->where("id",$id)->update($data);
if ($res) {
return V(1,"成功", []);
}else{
return V(0,"失败", []);
}
}
/**
* 删除
*/
public function admin_del($ids = "")
{
if (!$this->request->isPost()) {
return V(0,"失败", []);
}
$ids = $ids ? $ids : $this->request->post("id");
if ($ids) {
$ids = array_intersect($this->childrenAdminIds, array_filter(explode(',', $ids)));
// 避免越权删除管理员
$childrenGroupIds = $this->childrenGroupIds;
$adminList = $this->model->where('id', 'in', $ids)->where('id', 'in', function ($query) use ($childrenGroupIds) {
$query->name('vs_guild_admin_auth_group_access')->where('group_id', 'in', $childrenGroupIds)->field('uid');
})->select();
if ($adminList) {
$deleteIds = [];
foreach ($adminList as $k => $v) {
$deleteIds[] = $v->id;
}
$deleteIds = array_values(array_diff($deleteIds, [$this->auth->id]));
if ($deleteIds) {
Db::startTrans();
try {
$this->model->destroy($deleteIds);
model('guildadmin/AuthGroupAccess')->where('uid', 'in', $deleteIds)->delete();
Db::commit();
return V(1,"成功", []);
} catch (\Exception $e) {
Db::rollback();
return V(0,"失败", []);
}
}
}
}
return V(0,"失败", []);
}
}