Files
BESCMS/dayrui/App/Member/Controllers/Admin/Auth.php
T

635 lines
25 KiB
PHP

<?php namespace Phpcmf\Controllers\Admin;
class Auth extends \Phpcmf\Common
{
// 用户权限开关项
protected $member_check_fields = [
'avatar' => '强制上传头像',
'complete' => '强制完善资料',
'mobile' => '强制手机认证',
'email' => '强制邮箱认证',
'downfile' => '附件下载权限',
'uploadfile' => '附件上传权限',
];
// 用户权限数值项
protected $member_number_fields = [
'login' => [
'name' => '每日登录奖励',
'items' => [
'login_score' => ['app' => 'scorelog', 'unit' => 'score'],
'login_exp' => ['app' => 'explog', 'unit' => 'exp'],
],
],
'avatar_award' => [
'name' => '头像认证奖励',
'items' => [
'avatar_score' => ['app' => 'scorelog', 'unit' => 'score'],
'avatar_exp' => ['app' => 'explog', 'unit' => 'exp'],
],
],
];
public function index() {
// 用户组列
$group = [
0 => [
'id' => 0,
'name' => dr_lang('游客'),
'use' => 1,
]
];
foreach ($this->member_cache['group'] as $t) {
$group[$t['id']] = [
'id' => $t['id'],
'name' => dr_lang($t['name']),
'use' => 1,
];
}
// 用户组等级列
$level = [
0 => [
'id' => 0,
'name' => dr_lang('游客'),
'group_name' => '',
'level_name' => dr_lang('游客'),
'use' => 1,
]
];
foreach ($this->member_cache['group'] as $t) {
$gname = dr_lang($t['name']);
$level[$t['id']] = [
'id' => $t['id'],
'name' => $gname,
'group_name' => '',
'level_name' => $gname,
'use' => 1,
];
if ($t['level']) {
foreach ($t['level'] as $lv) {
$lname = dr_lang($lv['name']);
$level[$t['id'].'-'.$lv['id']] = [
'id' => $t['id'].'-'.$lv['id'],
'name' => $gname.' / '.$lname,
'group_name' => $gname,
'level_name' => $lname,
'use' => 1,
];
$level[$t['id']]['use'] = 0;
}
}
}
$v = \Phpcmf\Service::M()->db->table('member_setting')->where('name', 'auth_type')->get()->getRowArray();
$auth_type = intval($v['value']);
// 当前模式对应的列
if ($auth_type == 1) {
$columns = $group;
} elseif ($auth_type == 2) {
$columns = [];
foreach ($level as $i => $t) {
if ($t['use']) {
$columns[$i] = $t;
}
}
} else {
$columns = [
'public' => [
'id' => 'public',
'name' => dr_lang('全局'),
'use' => 1,
]
];
}
// 读取权限
$row = \Phpcmf\Service::M()->db->table('member_setting')->where('name', 'auth2')->get()->getRowArray();
$value = $row ? dr_string2array($row['value']) : [];
if (!is_array($value)) {
$value = [];
}
$auth_data = isset($value[SITE_ID]) && is_array($value[SITE_ID]) ? $value[SITE_ID] : [];
if (IS_AJAX_POST) {
$post = \Phpcmf\Service::L('input')->post('data');
if (!is_array($post)) {
$post = [];
}
foreach ($columns as $aid => $col) {
$key = (string)$aid;
$old = [];
if (isset($auth_data[$aid]) && is_array($auth_data[$aid])) {
$old = $auth_data[$aid];
} elseif (isset($auth_data[$key]) && is_array($auth_data[$key])) {
$old = $auth_data[$key];
}
// 仅读取当前列提交值,且只白名单写入,避免 POST 注入多余字段
$post_member = [];
if (isset($post[$aid]['member']) && is_array($post[$aid]['member'])) {
$post_member = $post[$aid]['member'];
} elseif (isset($post[$key]['member']) && is_array($post[$key]['member'])) {
$post_member = $post[$key]['member'];
}
$member = [];
foreach ($this->member_check_fields as $field => $name) {
$member[$field] = empty($post_member[$field]) ? 0 : 1;
}
foreach ($this->member_number_fields as $group_item) {
foreach ($group_item['items'] as $field => $cfg) {
$member[$field] = isset($post_member[$field]) ? intval($post_member[$field]) : 0;
}
}
$old['member'] = $member;
// 应用插件 / 内容权限仍保留,此处不覆盖
$auth_data[$aid] = $old;
}
$value[SITE_ID] = $auth_data;
\Phpcmf\Service::M()->db->table('member_setting')->replace([
'name' => 'auth2',
'value' => dr_array2string($value)
]);
\Phpcmf\Service::M('cache')->sync_cache('member');
$this->_json(1, dr_lang('操作成功'));
}
$diy = $this->_get_diy();
$col_count = dr_count($columns);
$is_single = $col_count <= 1;
// 取某列已存 member 配置
$get_member = function ($aid) use ($auth_data) {
$key = (string)$aid;
if (isset($auth_data[$aid]['member']) && is_array($auth_data[$aid]['member'])) {
return $auth_data[$aid]['member'];
}
if (isset($auth_data[$key]['member']) && is_array($auth_data[$key]['member'])) {
return $auth_data[$key]['member'];
}
return [];
};
$form_html = '';
$thead_html = '';
$tbody_html = '';
if ($is_single) {
// 全局模式:标准表单排版
$aid = 'public';
foreach ($columns as $k => $col) {
$aid = (string)$k;
break;
}
$member = $get_member($aid);
$aid_attr = htmlspecialchars($aid);
foreach ($this->member_check_fields as $field => $name) {
$checked = !empty($member[$field]) ? ' checked' : '';
$form_html .= '<div class="form-group">'
.'<label class="col-md-2 control-label">'.dr_lang($name).'</label>'
.'<div class="col-md-9">'
.'<input type="checkbox" name="data['.$aid_attr.'][member]['.$field.']" value="1"'.$checked
.' data-on-text="'.dr_lang('是').'" data-off-text="'.dr_lang('否').'"'
.' data-on-color="success" data-off-color="danger" class="make-switch" data-size="small">'
.'</div></div>';
}
foreach ($this->member_number_fields as $item) {
$form_html .= '<div class="form-group">'
.'<label class="col-md-2 control-label">'.dr_lang($item['name']).'</label>'
.'<div class="col-md-9">';
foreach ($item['items'] as $field => $cfg) {
$val = intval(isset($member[$field]) ? $member[$field] : 0);
$readonly = (($cfg['app'] == 'scorelog' && !dr_is_app('scorelog'))
|| ($cfg['app'] == 'explog' && !dr_is_app('explog'))) ? ' readonly' : '';
$unit = $cfg['unit'] == 'score' ? SITE_SCORE : SITE_EXPERIENCE;
$form_html .= '<label style="margin-right:10px;">'
.'<div class="input-group" style="width:200px;">'
.'<input type="text" class="form-control" name="data['.$aid_attr.'][member]['.$field.']" value="'.$val.'"'.$readonly.'>'
.'<span class="input-group-btn"><button class="btn default" type="button">+'.htmlspecialchars((string)$unit).'</button></span>'
.'</div></label>';
}
$form_html .= '</div></div>';
}
if (!empty($diy['app'])) {
$url = dr_url('member/auth/add', ['aid' => $aid, 'page' => 'app']);
$form_html .= '<div class="form-group">'
.'<label class="col-md-2 control-label">'.dr_lang('应用插件权限').'</label>'
.'<div class="col-md-9">'
.'<a href="'.$url.'" class="btn blue btn-sm"><i class="fa fa-puzzle-piece"></i> '.dr_lang('设置').'</a>'
.'</div></div>';
}
} else {
// 多列矩阵
$thead_html = '<th class="fc-auth-name">'.dr_lang('权限项').'</th>';
foreach ($columns as $aid => $col) {
$key = (string)$aid;
if ($key === '0') {
$title = '<span class="font-red">'.htmlspecialchars((string)$col['name']).'</span>';
} elseif (!empty($col['group_name'])) {
$title = '<span class="fc-auth-gname">'.htmlspecialchars((string)$col['group_name']).'</span>'
.'<span class="fc-auth-lname">'.htmlspecialchars((string)$col['level_name']).'</span>';
} else {
$title = htmlspecialchars((string)$col['name']);
}
$thead_html .= '<th class="fc-auth-col">'.$title.'</th>';
}
foreach ($this->member_check_fields as $field => $name) {
$tbody_html .= '<tr><td class="fc-auth-name">'.dr_lang($name).'</td>';
foreach ($columns as $aid => $col) {
$key = (string)$aid;
$member = $get_member($aid);
$checked = !empty($member[$field]) ? ' checked' : '';
$tbody_html .= '<td class="fc-auth-col">'
.'<input type="checkbox" class="fc-auth-check" name="data['.htmlspecialchars($key).'][member]['.$field.']" value="1"'.$checked.' />'
.'</td>';
}
$tbody_html .= '</tr>';
}
foreach ($this->member_number_fields as $item) {
$tbody_html .= '<tr><td class="fc-auth-name">'.dr_lang($item['name']).'</td>';
foreach ($columns as $aid => $col) {
$key = (string)$aid;
$member = $get_member($aid);
$tbody_html .= '<td class="fc-auth-col fc-auth-num-cell">';
foreach ($item['items'] as $field => $cfg) {
$val = intval(isset($member[$field]) ? $member[$field] : 0);
$readonly = (($cfg['app'] == 'scorelog' && !dr_is_app('scorelog'))
|| ($cfg['app'] == 'explog' && !dr_is_app('explog'))) ? ' readonly' : '';
$unit = $cfg['unit'] == 'score' ? SITE_SCORE : SITE_EXPERIENCE;
$tbody_html .= '<div class="input-group input-group-sm fc-auth-num">'
.'<input type="text" class="form-control" name="data['
.htmlspecialchars($key).'][member]['.$field.']" value="'.$val.'"'.$readonly.' />'
.'<span class="input-group-addon">+'.htmlspecialchars((string)$unit).'</span>'
.'</div>';
}
$tbody_html .= '</td>';
}
$tbody_html .= '</tr>';
}
if (!empty($diy['app'])) {
$tbody_html .= '<tr><td class="fc-auth-name">'.dr_lang('应用插件权限').'</td>';
foreach ($columns as $aid => $col) {
$key = (string)$aid;
$url = dr_url('member/auth/add', ['aid' => $key, 'page' => 'app']);
$tbody_html .= '<td class="fc-auth-col">'
.'<a href="'.$url.'" class="btn blue btn-xs"><i class="fa fa-puzzle-piece"></i> '.dr_lang('设置').'</a>'
.'</td>';
}
$tbody_html .= '</tr>';
}
}
\Phpcmf\Service::V()->assign([
'menu' => \Phpcmf\Service::M('auth')->_admin_menu(
[
'用户权限' => ['member/auth/index', 'fa fa-cog'],
'help' => [801],
]
),
'auth_type' => $auth_type,
'is_single' => $is_single,
'is_cms' => (defined('IS_USE_CMS') && IS_USE_CMS) ? 1 : 0,
'cms_auth_url' => (defined('IS_USE_CMS') && IS_USE_CMS) ? dr_url('cms/auth/index') : '',
'form_html' => $form_html,
'thead_html' => $thead_html,
'tbody_html' => $tbody_html,
]);
\Phpcmf\Service::V()->display('member_auth.html');
}
// 存储模式值
public function save_edit() {
$value = intval(\Phpcmf\Service::L('input')->get('value'));
if (!$value) {
$msg = dr_lang('已切换至按全局配置模式');
} elseif ($value == 1) {
$msg = dr_lang('已切换至按用户组配置模式');
} elseif ($value == 2) {
$msg = dr_lang('已切换至按用户组等级配置模式');
} else {
$this->_json(0, dr_lang('未知模式'));
}
\Phpcmf\Service::M()->db->table('member_setting')->replace([
'name' => 'auth_type',
'value' => $value
]);
\Phpcmf\Service::M('cache')->sync_cache('member');
$this->_json(1, $msg);
}
// 初始化组权限(仅清空用户相关配置,保留内容权限)
public function init_edit() {
$v = \Phpcmf\Service::M()->db->table('member_setting')->where('name', 'auth2')->get()->getRowArray();
$aid = \Phpcmf\Service::L('input')->get('aid');
if ($aid === null || $aid === false || $aid === '') {
$this->_json(0, dr_lang('参数错误'));
}
// 允许 public / 数字组ID / 组-等级
if ($aid !== 'public' && $aid !== '0' && $aid !== 0
&& !preg_match('/^\d+(-\d+)?$/', (string)$aid)) {
$this->_json(0, dr_lang('参数错误'));
}
$value = $v ? dr_string2array($v['value']) : [];
if (!is_array($value)) {
$value = [];
}
$old = isset($value[SITE_ID][$aid]) && is_array($value[SITE_ID][$aid]) ? $value[SITE_ID][$aid] : [];
// 兼容整型键
if (!$old && is_numeric($aid) && isset($value[SITE_ID][intval($aid)]) && is_array($value[SITE_ID][intval($aid)])) {
$old = $value[SITE_ID][intval($aid)];
unset($value[SITE_ID][intval($aid)]);
}
unset($old['member'], $old['app']);
$value[SITE_ID][$aid] = $old;
\Phpcmf\Service::M()->db->table('member_setting')->replace([
'name' => 'auth2',
'value' => dr_array2string($value)
]);
\Phpcmf\Service::M('cache')->sync_cache('member');
$this->_json(1, dr_lang('本组权限初始化完成'));
}
// 兼容:单组详细设置(应用插件扩展权限)
public function add() {
$aid = \Phpcmf\Service::L('input')->get('aid');
if ($aid == 'public') {
$name = dr_lang('全局');
} elseif (!$aid) {
$aid = 0;
$name = dr_lang('游客');
} elseif (strpos($aid, '-') !== false) {
list($gid, $lid) = explode('-', $aid);
if (!$this->member_cache['group'][$gid]) {
$this->_admin_msg(0, dr_lang('此用户组不存在'));
} elseif (!$this->member_cache['group'][$gid]['level'][$lid]) {
$this->_admin_msg(0, dr_lang('此用户组等级不存在'));
}
$name = $this->member_cache['group'][$gid]['name'].'-'.$this->member_cache['group'][$gid]['level'][$lid]['name'];
} else {
if (!$this->member_cache['group'][$aid]) {
$this->_admin_msg(0, dr_lang('此用户组不存在'));
}
$name = $this->member_cache['group'][$aid]['name'];
}
$v = \Phpcmf\Service::M()->db->table('member_setting')->where('name', 'auth2')->get()->getRowArray();
$value = $v ? dr_string2array($v['value']) : [];
if (!is_array($value)) {
$value = [];
}
$data = isset($value[SITE_ID][$aid]) && is_array($value[SITE_ID][$aid]) ? $value[SITE_ID][$aid] : [];
if (IS_AJAX_POST) {
$post = \Phpcmf\Service::L('input')->post('data');
if (!is_array($post)) {
$post = [];
}
$save = $data;
// 本页仅维护应用插件权限,禁止通过 POST 覆盖用户权限 member
if (isset($post['app']) && is_array($post['app'])) {
$save['app'] = $post['app'];
}
$value[SITE_ID][$aid] = $save;
\Phpcmf\Service::M()->db->table('member_setting')->replace([
'name' => 'auth2',
'value' => dr_array2string($value)
]);
\Phpcmf\Service::M('cache')->sync_cache('member');
$this->_json(1, dr_lang('操作成功'));
}
$page = trim(\Phpcmf\Service::L('input')->get('page'));
if (!$page) {
$page = 'app';
}
\Phpcmf\Service::V()->assign([
'aid' => $aid,
'diy' => $this->_get_diy(),
'menu' => \Phpcmf\Service::M('auth')->_admin_menu(
[
'返回' => ['member/auth/index', 'fa fa-cog'],
dr_lang('%s:应用权限', $name) => ['member/auth/add{aid='.$aid.'}', 'fa fa-puzzle-piece'],
'help' => [801],
]
),
'page' => $page,
'data' => $data,
'is_ajax_edit' => 0,
]);
\Phpcmf\Service::V()->display('member_auth_setting.html');
}
public function edit() {
$this->_json(0, dr_lang('内容权限请到【内容系统 → 权限设置 → 内容权限】中配置'));
}
public function copy_edit() {
$at = dr_safe_filename(\Phpcmf\Service::L('input')->get('at'));
if (!$at) {
$this->_json(0, dr_lang('at参数错误'));
}
$v = \Phpcmf\Service::M()->db->table('member_setting')->where('name', 'auth2')->get()->getRowArray();
$aid = dr_safe_filename(\Phpcmf\Service::L('input')->get('aid'));
!$aid && $aid = 0;
$value = dr_string2array($v['value']);
switch ($at) {
case 'level':
$group = [
0 => [
'id' => 0,
'name' => dr_lang('游客'),
],
];
foreach ($this->member_cache['group'] as $t) {
$group[$t['id']] = [
'id' => $t['id'],
'name' => dr_lang($t['name']),
];
if ($t['level']) {
foreach ($t['level'] as $lv) {
$group[$t['id'].'-'.$lv['id']] = [
'id' => $t['id'].'-'.$lv['id'],
'name' => ' └ '.dr_lang($lv['name']),
];
}
}
}
if (IS_AJAX_POST) {
$auth = $value[SITE_ID][$aid];
if (!$auth) {
$this->_json(0, dr_lang('当前用户组没有配置权限规则'));
}
$catids = \Phpcmf\Service::L('input')->post('catid');
if (!$catids) {
$this->_json(0, dr_lang('你还没有选择用户组呢'));
}
$c = 0;
if (isset($catids[0]) && $catids[0] == 0) {
foreach ($group as $id => $t) {
$c ++;
$value[SITE_ID][$id] = $auth;
}
} else {
foreach ($catids as $id) {
$c ++;
$value[SITE_ID][$id] = $auth;
}
}
\Phpcmf\Service::M()->db->table('member_setting')->replace([
'name' => 'auth2',
'value' => dr_array2string($value)
]);
\Phpcmf\Service::M('cache')->sync_cache('member');
$this->_json(1, dr_lang('共复制%s个用户组', $c));
exit;
}
\Phpcmf\Service::V()->assign([
'form' => dr_form_hidden(),
'select' => \Phpcmf\Service::L('tree')->select_category(
$group,
0,
'id=\'dr_catid\' name=\'catid[]\' multiple="multiple" style="height:200px"',
'',
0,
0
),
]);
\Phpcmf\Service::V()->display('member_auth_copy_group.html');exit;
case 'group':
$group = [
0 => [
'id' => 0,
'name' => dr_lang('游客'),
],
];
foreach ($this->member_cache['group'] as $t) {
$group[$t['id']] = $t;
}
if (IS_AJAX_POST) {
$auth = $value[SITE_ID][$aid];
if (!$auth) {
$this->_json(0, dr_lang('当前用户组没有配置权限规则'));
}
$catids = \Phpcmf\Service::L('input')->post('catid');
if (!$catids) {
$this->_json(0, dr_lang('你还没有选择用户组呢'));
}
$c = 0;
if (isset($catids[0]) && $catids[0] == 0) {
foreach ($group as $id => $t) {
$c ++;
$value[SITE_ID][$id] = $auth;
}
} else {
foreach ($catids as $id) {
$c ++;
$value[SITE_ID][$id] = $auth;
}
}
\Phpcmf\Service::M()->db->table('member_setting')->replace([
'name' => 'auth2',
'value' => dr_array2string($value)
]);
\Phpcmf\Service::M('cache')->sync_cache('member');
$this->_json(1, dr_lang('共复制%s个用户组', $c));
exit;
}
\Phpcmf\Service::V()->assign([
'form' => dr_form_hidden(),
'select' => \Phpcmf\Service::L('tree')->select_category(
$group,
0,
'id=\'dr_catid\' name=\'catid[]\' multiple="multiple" style="height:200px"',
'',
0,
0
),
]);
\Phpcmf\Service::V()->display('member_auth_copy_group.html');exit;
case 'share_category':
case 'category':
$this->_json(0, dr_lang('内容权限请到【内容系统 → 权限设置 → 内容权限】中配置'));
break;
}
$this->_json(0, dr_lang('未知类型'));
}
private function _get_diy() {
$diy = [
'member' => [],
'app' => [],
];
$local = \Phpcmf\Service::Apps(1);
foreach ($local as $dir => $path) {
if (is_file($path.'Config/Auth.php')) {
$_data = require $path.'Config/Auth.php';
if ($_data) {
foreach ($_data as $key => $val) {
if ($val && isset($diy[$key])) {
foreach ($val as $file) {
if (is_file($path.'Views/auth/'.$file)) {
$diy[$key][] = [
'app' => $dir,
'file' => $path.'Views/auth/'.$file,
];
} else {
log_message('error', '应用插件['.$dir.']权限模板文件不存在:'.$path.'Views/auth/'.$file);
}
}
}
}
}
}
}
return $diy;
}
}