Pre Merge pull request !165 from wkk/master

pull/165/MERGE
wkk 2020-02-27 10:43:26 +08:00 committed by Gitee
commit 86be06667f
17 changed files with 879 additions and 720 deletions

View File

@ -26,6 +26,7 @@ CREATE TABLE `fa_admin` (
`loginip` varchar(50) DEFAULT NULL COMMENT '登录IP',
`createtime` int(10) DEFAULT NULL COMMENT '创建时间',
`updatetime` int(10) DEFAULT NULL COMMENT '更新时间',
`expiretime` int(10) DEFAULT NULL COMMENT '过期时间',
`token` varchar(59) NOT NULL DEFAULT '' COMMENT 'Session标识',
`status` varchar(30) NOT NULL DEFAULT 'normal' COMMENT '状态',
PRIMARY KEY (`id`),
@ -36,7 +37,7 @@ CREATE TABLE `fa_admin` (
-- Records of fa_admin
-- ----------------------------
BEGIN;
INSERT INTO `fa_admin` VALUES (1, 'admin', 'Admin', '075eaec83636846f51c152f29b98a2fd', 's4f3', '/assets/img/avatar.png', 'admin@fastadmin.net', 0, 1502029281, '127.0.0.1',1492186163, 1502029281, 'd3992c3b-5ecc-4ecb-9dc2-8997780fcadc', 'normal');
INSERT INTO `fa_admin` VALUES (1, 'admin', 'Admin', '075eaec83636846f51c152f29b98a2fd', 's4f3', '/assets/img/avatar.png', 'admin@fastadmin.net', 0, 1502029281, '127.0.0.1',1492186163, 1502029281, 0, 'd3992c3b-5ecc-4ecb-9dc2-8997780fcadc', 'normal');
COMMIT;
-- ----------------------------
@ -99,6 +100,7 @@ CREATE TABLE `fa_auth_group` (
`rules` text NOT NULL COMMENT '规则ID',
`createtime` int(10) DEFAULT NULL COMMENT '创建时间',
`updatetime` int(10) DEFAULT NULL COMMENT '更新时间',
`expiretime` int(10) DEFAULT NULL COMMENT '过期时间',
`status` varchar(30) NOT NULL DEFAULT '' COMMENT '状态',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='分组表';
@ -107,11 +109,11 @@ CREATE TABLE `fa_auth_group` (
-- Records of fa_auth_group
-- ----------------------------
BEGIN;
INSERT INTO `fa_auth_group` VALUES (1, 0, 'Admin group', '*', 1490883540, 149088354, 'normal');
INSERT INTO `fa_auth_group` VALUES (2, 1, 'Second group', '13,14,16,15,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,40,41,42,43,44,45,46,47,48,49,50,55,56,57,58,59,60,61,62,63,64,65,1,9,10,11,7,6,8,2,4,5', 1490883540, 1505465692, 'normal');
INSERT INTO `fa_auth_group` VALUES (3, 2, 'Third group', '1,4,9,10,11,13,14,15,16,17,40,41,42,43,44,45,46,47,48,49,50,55,56,57,58,59,60,61,62,63,64,65,5', 1490883540, 1502205322, 'normal');
INSERT INTO `fa_auth_group` VALUES (4, 1, 'Second group 2', '1,4,13,14,15,16,17,55,56,57,58,59,60,61,62,63,64,65', 1490883540, 1502205350, 'normal');
INSERT INTO `fa_auth_group` VALUES (5, 2, 'Third group 2', '1,2,6,7,8,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34', 1490883540, 1502205344, 'normal');
INSERT INTO `fa_auth_group` VALUES (1, 0, 'Admin group', '*', 1490883540, 149088354, 0,'normal');
INSERT INTO `fa_auth_group` VALUES (2, 1, 'Second group', '13,14,16,15,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,40,41,42,43,44,45,46,47,48,49,50,55,56,57,58,59,60,61,62,63,64,65,1,9,10,11,7,6,8,2,4,5', 1490883540, 1505465692, 0, 'normal');
INSERT INTO `fa_auth_group` VALUES (3, 2, 'Third group', '1,4,9,10,11,13,14,15,16,17,40,41,42,43,44,45,46,47,48,49,50,55,56,57,58,59,60,61,62,63,64,65,5', 1490883540, 1502205322, 0, 'normal');
INSERT INTO `fa_auth_group` VALUES (4, 1, 'Second group 2', '1,4,13,14,15,16,17,55,56,57,58,59,60,61,62,63,64,65', 1490883540, 1502205350, 0, 'normal');
INSERT INTO `fa_auth_group` VALUES (5, 2, 'Third group 2', '1,2,6,7,8,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34', 1490883540, 1502205344, 0, 'normal');
COMMIT;
-- ----------------------------

View File

@ -129,6 +129,7 @@ class Admin extends Backend
$params['salt'] = Random::alnum();
$params['password'] = md5(md5($params['password']) . $params['salt']);
$params['avatar'] = '/assets/img/avatar.png'; //设置新管理员默认头像。
$params['expiretime'] = $params['expiretime']==0 ? 0 : strtotime($params['expiretime']);
$result = $this->model->validate('Admin.add')->save($params);
if ($result === false) {
$this->error($this->model->getError());
@ -174,6 +175,7 @@ class Admin extends Backend
} else {
unset($params['password'], $params['salt']);
}
$params['expiretime'] = $params['expiretime']==0 ? 0 : strtotime($params['expiretime']);
//这里需要针对username和email做唯一验证
$adminValidate = \think\Loader::validate('Admin');
$adminValidate->rule([
@ -208,6 +210,7 @@ class Admin extends Backend
foreach ($grouplist as $k => $v) {
$groupids[] = $v['id'];
}
$row['expiretime'] = $row['expiretime'] === 0 ? 0 : date("Y-m-d H:i:s", $row['expiretime']);
$this->view->assign("row", $row);
$this->view->assign("groupids", $groupids);
return $this->view->fetch();

View File

@ -111,6 +111,11 @@ class Group extends Backend
// 如果当前组别不是超级管理员则需要过滤规则节点,不能超当前组别的权限
$rules = in_array('*', $currentrules) ? $rules : array_intersect($currentrules, $rules);
$params['rules'] = implode(',', $rules);
//日期转时间戳
$params['expiretime'] = empty($params['expiretime']) ? 0 : strtotime($params['expiretime']);
if (false === $params['expiretime']) {
$this->error(__('Invalid format of expire time'));
}
if ($params) {
$this->model->create($params);
$this->success();
@ -144,6 +149,11 @@ class Group extends Backend
$this->error(__('The parent group can not be its own child or itself'));
}
$params['rules'] = explode(',', $params['rules']);
//日期转时间戳
$params['expiretime'] = empty($params['expiretime']) ? 0 : strtotime($params['expiretime']);
if (false === $params['expiretime']) {
$this->error(__('Invalid format of expire time'));
}
$parentmodel = model("AuthGroup")->get($params['pid']);
if (!$parentmodel) {
@ -180,6 +190,7 @@ class Group extends Backend
$this->error();
return;
}
$row['expiretime'] = $row['expiretime'] === 0 ? 0 : date("Y-m-d H:i:s", $row['expiretime']);
$this->view->assign("row", $row);
return $this->view->fetch();
}

View File

@ -96,6 +96,7 @@ return [
'End time' => '结束时间',
'Create time' => '创建时间',
'Update time' => '更新时间',
'Expire time' => '过期时间',
'Flag' => '标志',
'Drag to sort' => '拖动进行排序',
'Redirect now' => '立即跳转',

View File

@ -9,4 +9,5 @@ return [
'You can not delete group that contain child group and administrators' => '你不能删除含有子组和管理员的组',
'The parent group exceeds permission limit' => '父组别超出权限范围',
'The parent group can not be its own child or itself' => '父组别不能是它的子组别及本身',
'Invalid format of expire time' => '过期时间格式错误',
];

View File

@ -27,6 +27,7 @@ return [
'Username is incorrect' => '用户名不正确',
'Password is incorrect' => '密码不正确',
'Admin is forbidden' => '管理员已经被禁止登录',
'Admin is expired' => '管理员已过期',
'Please try again after 1 day' => '请于1天后再尝试登录',
'Login successful' => '登录成功!',
'Logout successful' => '退出成功!',

View File

@ -47,6 +47,10 @@ class Auth extends \fast\Auth
$this->setError('Admin is forbidden');
return false;
}
if ($admin['expiretime'] < time() && $admin['expiretime']!=0) {
$this->setError('Admin is expired');
return false;
}
if (Config::get('fastadmin.login_failure_retry') && $admin->loginfailure >= 10 && time() - $admin->updatetime < 86400) {
$this->setError('Please try again after 1 day');
return false;
@ -282,7 +286,8 @@ class Auth extends \fast\Auth
}
}
// 取出所有分组
$groupList = \app\admin\model\AuthGroup::where(['status' => 'normal'])->select();
// $groupList = \app\admin\model\AuthGroup::where(['status' => 'normal'])->select();
$groupList = \app\admin\model\AuthGroup::all();
$objList = [];
foreach ($groups as $k => $v) {
if ($v['rules'] === '*') {

View File

@ -11,10 +11,11 @@ class Admin extends Validate
* 验证规则
*/
protected $rule = [
'username' => 'require|regex:\w{3,12}|unique:admin',
'username' => 'require|max:50|unique:admin',
'nickname' => 'require',
'password' => 'require|regex:\S{32}',
'password' => 'require',
'email' => 'require|email|unique:admin,email',
'expiretime' => 'require|integer'
];
/**
@ -33,8 +34,8 @@ class Admin extends Validate
* 验证场景
*/
protected $scene = [
'add' => ['username', 'email', 'nickname', 'password'],
'edit' => ['username', 'email', 'nickname', 'password'],
'add' => ['username', 'email', 'nickname', 'password', 'expiretime'],
'edit' => ['username', 'email', 'nickname', 'expiretime'],
];
public function __construct(array $rules = [], $message = [], $field = [])
@ -45,11 +46,6 @@ class Admin extends Validate
'password' => __('Password'),
'email' => __('Email'),
];
$this->message = array_merge($this->message, [
'username.regex' => __('Please input correct username'),
'password.regex' => __('Please input correct password')
]);
parent::__construct($rules, $message, $field);
}
}

View File

@ -30,6 +30,17 @@
<input type="password" class="form-control" id="password" name="row[password]" autocomplete="new-password" value="" data-rule="required;password" />
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Expire time')}:</label>
<div class="col-xs-12 col-sm-8">
<span class="text-muted"><input type="checkbox" name="" id="for_ever" /> <label for="for_ever"><small>永久</small></label></span>
<span class="text-muted"><input type="checkbox" name="" id="select_time" /> <label for="select_time"><small>选择时间</small></label></span>
<div id="expiretime-select" style="display: none;">
<input class="form-control datetimepicker" name="row[expiretime]" type="text" data-date-default-date="now" data-date-min-date="now" data-rule="required" data-date-use-current="true" data-date-format="YYYY-MM-DD HH:mm:ss"/>
</div>
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Status')}:</label>
<div class="col-xs-12 col-sm-8">

View File

@ -9,19 +9,19 @@
<div class="form-group">
<label for="username" class="control-label col-xs-12 col-sm-2">{:__('Username')}:</label>
<div class="col-xs-12 col-sm-8">
<input type="text" class="form-control" id="username" name="row[username]" value="{$row.username|htmlentities}" data-rule="required;username" />
<input type="text" class="form-control" id="username" name="row[username]" value="{$row.username}" data-rule="required;username" />
</div>
</div>
<div class="form-group">
<label for="email" class="control-label col-xs-12 col-sm-2">{:__('Email')}:</label>
<div class="col-xs-12 col-sm-8">
<input type="email" class="form-control" id="email" name="row[email]" value="{$row.email|htmlentities}" data-rule="required;email" />
<input type="email" class="form-control" id="email" name="row[email]" value="{$row.email}" data-rule="required;email" />
</div>
</div>
<div class="form-group">
<label for="nickname" class="control-label col-xs-12 col-sm-2">{:__('Nickname')}:</label>
<div class="col-xs-12 col-sm-8">
<input type="text" class="form-control" id="nickname" name="row[nickname]" autocomplete="off" value="{$row.nickname|htmlentities}" data-rule="required" />
<input type="text" class="form-control" id="nickname" name="row[nickname]" autocomplete="off" value="{$row.nickname}" data-rule="required" />
</div>
</div>
<div class="form-group">
@ -36,6 +36,17 @@
<input type="number" class="form-control" id="loginfailure" name="row[loginfailure]" value="{$row.loginfailure}" data-rule="required" />
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Expire time')}:</label>
<div class="col-xs-12 col-sm-8">
<span class="text-muted"><input type="checkbox" {if $row.expiretime === 0 } checked="checked" {/if} name="" id="for_ever" /> <label for="for_ever"><small>永久</small></label></span>
<span class="text-muted"><input type="checkbox" {if $row.expiretime !== 0 } checked="checked" {/if} name="" id="select_time" /> <label for="select_time"><small>选择时间</small></label></span>
<div id="expiretime-select" {if $row.expiretime === 0 } style="display: none;" {/if}>
<input class="form-control datetimepicker" name="row[expiretime]" type="text" data-date-default-date="{$row.expiretime}" data-rule="required" data-date-format="YYYY-MM-DD HH:mm:ss"/>
</div>
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Status')}:</label>
<div class="col-xs-12 col-sm-8">

View File

@ -22,6 +22,17 @@
<div id="treeview"></div>
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Expire time')}:</label>
<div class="col-xs-12 col-sm-8">
<span class="text-muted"><input type="checkbox" name="" id="for_ever" /> <label for="for_ever"><small>永久</small></label></span>
<span class="text-muted"><input type="checkbox" name="" id="select_time" /> <label for="select_time"><small>选择时间</small></label></span>
<div id="expiretime-select" style="display: none;">
<input class="form-control datetimepicker" name="row[expiretime]" type="text" data-date-default-date="now" data-date-min-date="now" data-rule="required" data-date-use-current="true" data-date-format="YYYY-MM-DD HH:mm:ss"/>
</div>
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Status')}:</label>
<div class="col-xs-12 col-sm-8">

View File

@ -22,6 +22,17 @@
<div id="treeview"></div>
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Expire time')}:</label>
<div class="col-xs-12 col-sm-8">
<span class="text-muted"><input type="checkbox" {if $row.expiretime === 0 } checked="checked" {/if} name="" id="for_ever" /> <label for="for_ever"><small>永久</small></label></span>
<span class="text-muted"><input type="checkbox" {if $row.expiretime !== 0 } checked="checked" {/if} name="" id="select_time" /> <label for="select_time"><small>选择时间</small></label></span>
<div id="expiretime-select" {if $row.expiretime === 0 } style="display: none;" {/if}>
<input class="form-control datetimepicker" name="row[expiretime]" type="text" data-date-default-date="{$row.expiretime}" data-rule="required" data-date-format="YYYY-MM-DD HH:mm:ss"/>
</div>
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Status')}:</label>
<div class="col-xs-12 col-sm-8">

View File

@ -153,11 +153,12 @@ class Auth
}
// 执行查询
$nowTime = time();
$user_groups = Db::name($this->config['auth_group_access'])
->alias('aga')
->join('__' . strtoupper($this->config['auth_group']) . '__ ag', 'aga.group_id = ag.id', 'LEFT')
->field('aga.uid,aga.group_id,ag.id,ag.pid,ag.name,ag.rules')
->where("aga.uid='{$uid}' and ag.status='normal'")
->where("aga.uid='{$uid}' and ag.status='normal' and (ag.expiretime>={$nowTime} or ag.expiretime=0)")
->select();
$groups[$uid] = $user_groups ?: [];
return $groups[$uid];

View File

@ -37,6 +37,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
{field: 'email', title: __('Email')},
{field: 'status', title: __("Status"), formatter: Table.api.formatter.status},
{field: 'logintime', title: __('Login time'), formatter: Table.api.formatter.datetime, operate: 'RANGE', addclass: 'datetimerange', sortable: true},
{field: 'expiretime', title: __('Expire time'), formatter: Table.api.formatter.expiretime, expireOn:'now'},
{field: 'operate', title: __('Operate'), table: table, events: Table.api.events.operate, formatter: function (value, row, index) {
if(row.id == Config.admin.id){
return '';
@ -52,9 +53,27 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
},
add: function () {
Form.api.bindevent($("form[role=form]"));
Controller.api.bindevent();
},
edit: function () {
Form.api.bindevent($("form[role=form]"));
Controller.api.bindevent();
},
api: {
bindevent: function () {
//过期时间: 永久和选择时间
$(document).on("click", "#for_ever", function () {
$("#expiretime-select").attr("style","display:none;");
$("input[name='row[expiretime]']").val('0');
$("#select_time").removeAttr("checked");
});
$(document).on("click", "#select_time", function () {
$("#expiretime-select").attr("style","display:block;");
$("#for_ever").removeAttr("checked");
var nowDate = new Date();
$("input[name='row[expiretime]']").val(nowDate.getFullYear() + '-' + (nowDate.getMonth()+1) + '-' + nowDate.getDate() + ' 23:59:59');
});
}
}
};
return Controller;

View File

@ -50,6 +50,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'jstree'], function (
{field: 'pid', title: __('Parent')},
{field: 'name', title: __('Name'), align: 'left'},
{field: 'status', title: __('Status'), formatter: Table.api.formatter.status},
{field: 'expiretime', title: __('Expire time'), formatter: Table.api.formatter.expiretime},
{
field: 'operate', title: __('Operate'), table: table, events: Table.api.events.operate, formatter: function (value, row, index) {
if (Config.admin.group_ids.indexOf(parseInt(row.id)) > -1) {
@ -122,6 +123,18 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'jstree'], function (
$(document).on("click", "#expandall", function () {
$("#treeview").jstree($(this).prop("checked") ? "open_all" : "close_all");
});
//过期时间: 永久和选择时间
$(document).on("click", "#for_ever", function () {
$("#expiretime-select").attr("style","display:none;");
$("input[name='row[expiretime]']").val('0');
$("#select_time").removeAttr("checked");
});
$(document).on("click", "#select_time", function () {
$("#expiretime-select").attr("style","display:block;");
$("#for_ever").removeAttr("checked");
var nowDate = new Date();
$("input[name='row[expiretime]']").val(nowDate.getFullYear() + '-' + (nowDate.getMonth()+1) + '-' + nowDate.getDate() + ' 23:59:59');
});
$("select[name='row[pid]']").trigger("change");
},
rendertree: function (content) {

File diff suppressed because it is too large Load Diff

View File

@ -599,6 +599,37 @@ define(['jquery', 'bootstrap', 'moment', 'moment/locale/zh-cn', 'bootstrap-table
return value ? Moment(parseInt(value) * 1000).format(datetimeFormat) : __('None');
}
},
expiretime: function (value, row, index) {
if (!value && value!==0) {
return __('None');
}
var result = '';
var color = 'success';
//永久标识
var forerver = [0,'0000-00-00 00:00:00', '0000-00-00 00:00:00.000000'];
if ($.inArray(value, forerver) !== -1) {
result = "永久"
} else {
//过期时间
var expireTimestamp = Moment().unix();
if (typeof this.expireOn !== 'undefined') {
var condition = isNaN(this.expireOn) ? (this.expireOn.toLowerCase() !== 'now') : (this.expireOn !== 0);
if (condition) {
expireTimestamp = isNaN(this.expireOn) ? Moment(this.expireOn).unix() : Moment(parseInt(this.expireOn) * 1000).unix()
}
}
//当前value时间
var valueTimestamp = isNaN(value) ? Moment(value).unix() : Moment(parseInt(value) * 1000).unix();
if (valueTimestamp >= expireTimestamp) {
result = Moment(parseInt(valueTimestamp) * 1000).format('YYYY-MM-DD HH:mm:ss');
} else {
result = '已过期';
color = 'danger';
}
}
return '<span class="label label-' + color + '">' + result + '</span>';
},
operate: function (value, row, index) {
var table = this.table;
// 操作配置