角色管理功能完成。

pull/105/head
Apex Liu 2017-11-02 19:28:05 +08:00
parent 0f25a5e372
commit 0247d5603d
8 changed files with 303 additions and 98 deletions

View File

@ -1,32 +1,16 @@
"use strict";
$app.on_init = function (cb_stack) {
$app.last_role_id = 0;
$app.last_role_id = 0; // todo: 使用数组的方式管理选择历史
$app.selected_role_id = 0;
$app.edit_mode = false;
$app.dom = {
role_list: $('#role-list'),
btn_edit_role: $('#btn-edit-role'),
btn_del_role: $('#btn-delete-role'),
btn_remove_role: $('#btn-remove-role'),
btn_save_role: $('#btn-save-role'),
btn_cancel_edit_role: $('#btn-cancel-edit-role'),
// btn_verify_oath_code: $('#btn-verify-oath-code'),
// btn_verify_oath_code_and_save: $('#btn-verify-oath-and-save'),
// btn_modify_password: $('#btn-modify-password'),
// btn_toggle_oath_download: $('#toggle-oath-download'),
//
// oath_app_download_box: $('#oath-app-download-box'),
//
// input_role_name: $('#input-role-name'),
// input_new_password: $('#new-password-1'),
// input_new_password_confirm: $('#new-password-2'),
// input_oath_code: $('#oath-code'),
// input_oath_code_verify: $('#oath-code-verify'),
//
// dlg_reset_oath_code: $('#dialog-reset-oath-code'),
// oath_secret_image: $('#oath-secret-qrcode'),
// tmp_oath_secret: $('#tmp-oath-secret'),
role_info: $('#role-info'),
privilege_list: $('#privilege-list')
@ -48,6 +32,7 @@ $app.on_init = function (cb_stack) {
};
$app.create_controls = function () {
console.log($app.role_list);
var nodes = [];
var selected_role_id = 0;
for (var i = 0; i < $app.role_list.length; ++i) {
@ -67,7 +52,6 @@ $app.create_controls = function () {
$app.dom.role_list.append($(nodes.join('')));
$app.dom.btn_create_role = $('#btn-create-role');
var privileges = [
{
t: '资产', i: [
@ -130,6 +114,9 @@ $app.create_controls = function () {
$app.show_role(role_id, false);
});
$app.dom.privilege_list.find('[data-privilege]').click(function () {
if (!$app.edit_mode)
return;
var obj = $(this);
if (obj.hasClass('enabled')) {
obj.removeClass('enabled');
@ -137,27 +124,41 @@ $app.create_controls = function () {
obj.addClass('enabled');
}
if (!$app.edit_mode) {
$app.edit_mode = true;
$app.dom.role.save_area.slideDown();
}
// if (!$app.edit_mode) {
// $app.edit_mode = true;
// $app.dom.role.save_area.slideDown();
// }
});
$app.dom.btn_edit_role.click(function () {
$app.show_role($app.selected_role_id, true);
});
$app.dom.btn_cancel_edit_role.click(function () {
if ($app.selected_role_id !== 0)
$app.show_role($app.selected_role_id, false);
else
$app.show_role($app.last_role_id, false);
});
$app.dom.btn_save_role.click(function () {
$app.save_role();
});
$app.dom.btn_remove_role.click(function () {
$app.remove_role();
});
};
$app.show_role = function (role_id, edit_mode) {
var edit = edit_mode || false;
var role = null;
if (role_id === 1 && edit_mode) {
$tp.notify_error('禁止修改管理员角色!');
return;
}
if (role_id === 0) {
role = {id: 0, name: '', privilege: 0};
edit = true;
@ -205,3 +206,122 @@ $app.show_role = function (role_id, edit_mode) {
if (role_id !== 0)
$app.last_role_id = role_id;
};
$app.save_role = function () {
var role_name = $app.dom.role.input_role_name.val();
if (role_name.length === 0) {
$tp.notify_error('请为此角色设置一个名称!');
$app.role.dom.input_role_name.focus();
return;
}
var p = 0;
var privilege_objs = $('#role-info').find('[data-privilege]');
for (var i = 0; i < privilege_objs.length; ++i) {
var obj = $(privilege_objs[i]);
if (obj.hasClass('enabled')) {
p |= parseInt(obj.attr('data-privilege'));
}
}
if (0 === p) {
$tp.notify_error('此角色未设定任何权限!');
return;
}
var action = ($app.selected_role_id === 0) ? '添加' : '更新';
$tp.ajax_post_json('/system/role-update',
{
role_id: $app.selected_role_id,
role_name: role_name,
privilege: p
},
function (ret) {
if (ret.code === TPE_OK) {
var role_id = ret.data;
$tp.notify_success('角色' + action + '成功!');
if ($app.selected_role_id === 0) {
$app.role_list.push({id: role_id, name: role_name, privilege: p});
var html = [];
html.push('<li data-role-id="' + role_id + '"');
html.push('><i class="fa fa-user-circle fa-fw"></i> ');
html.push(role_name);
html.push('</li>');
$app.dom.btn_create_role.before($(html.join('')));
$app.dom.role_list.find('[data-role-id="'+role_id+'"]').click(function () {
var obj = $(this);
if (obj.hasClass('active')) {
return;
}
var r_id = parseInt(obj.attr('data-role-id'));
$app.show_role(r_id, false);
});
} else {
for (var i = 0; i < $app.role_list.length; ++i) {
console.log($app.role_list[i].id, role_id);
if ($app.role_list[i].id === role_id) {
$app.role_list[i].name = role_name;
$app.role_list[i].privilege = p;
break;
}
}
}
$app.dom.role_list.find('[data-role-id="' + role_id + '"]').html('<i class="fa fa-user-circle fa-fw"></i> ' + role_name);
$app.show_role(role_id, false);
} else {
$tp.notify_error('角色' + action + '失败:' + tp_error_msg(ret.code, ret.message));
}
},
function () {
$tp.notify_error('网路故障,角色' + action + '失败!');
}
);
};
$app.remove_role = function () {
if ($app.selected_role_id === 1) {
$tp.notify_error('禁止删除管理员角色!');
return;
}
$tp.ajax_post_json('/system/role-remove',
{
role_id: $app.selected_role_id
},
function (ret) {
if (ret.code === TPE_OK) {
$tp.notify_success('角色删除成功!');
for (var i = 0; i < $app.role_list; ++i) {
if ($app.role_list[i].id === $app.selected_role_id) {
delete $app.role_list[i];
break;
}
}
$app.dom.role_list.find('[data-role-id="' + $app.selected_role_id + '"]').remove();
if ($app.last_role_id === $app.selected_role_id)
$app.last_role_id = 1;
$app.show_role($app.last_role_id, false);
} else {
$tp.notify_error('角色删除失败:' + tp_error_msg(ret.code, ret.message));
}
},
function () {
$tp.notify_error('网路故障,角色删除失败!');
}
);
};

View File

@ -27,7 +27,7 @@
</div>
<div class="stats-content">
<div class="stats-name">用户</div>
<div class="stats-value">21</div>
<div class="stats-value">-</div>
</div>
</div>
</div>
@ -38,7 +38,7 @@
</div>
<div class="stats-content">
<div class="stats-name">主机</div>
<div class="stats-value">128</div>
<div class="stats-value">-</div>
</div>
</div>
</div>
@ -49,7 +49,7 @@
</div>
<div class="stats-content">
<div class="stats-name">主机账号</div>
<div class="stats-value">63</div>
<div class="stats-value">-</div>
</div>
</div>
</div>
@ -60,7 +60,7 @@
</div>
<div class="stats-content">
<div class="stats-name">当前连接</div>
<div class="stats-value">18</div>
<div class="stats-value">-</div>
</div>
</div>
</div>

View File

@ -20,8 +20,6 @@
<i class="fa fa-info-circle fa-fw icon-bg"></i> 角色就是一组权限的集合。
</div>
## <div style="padding:10px 0;">角色列表 <a href="javascript:;"><i class="fa fa-plus-circle fa-fw"></i> 创建新角色</a></div>
<div>
<table class="table table-role">
<tr>
@ -30,7 +28,6 @@
<ul id="role-list"></ul>
</td>
<td id="role-info" class="role-privilege editable">
## <td id="role-info" class="role-privilege">
<div>
<div style="float:left;">
@ -43,62 +40,13 @@
</div>
<div style="float:right;">
<button id="btn-edit-role" class="btn btn-sm btn-primary"><i class="fa fa-edit fa-fw"></i> 编辑角色</button>
<button id="btn-delete-role" class="btn btn-sm btn-danger"><i class="fa fa-trash-o fa-fw"></i> 删除角色</button>
<button id="btn-remove-role" class="btn btn-sm btn-danger"><i class="fa fa-trash-o fa-fw"></i> 删除角色</button>
</div>
<div class="clear-float"></div>
</div>
<div id="privilege-list"></div>
## <hr/>
## <div class="title">资产</div>
## <ul>
## <li><span data-checkbox=TP_PRIVILEGE_ACCOUNT class="">主机信息创建/编辑</span></li>
## <li><span data-checkbox="ASSET_DELETE" class="">删除主机信息</span></li>
## <li><span data-checkbox="ASSET_LOCK" class="">主机禁用/解禁</span></li>
## <li><span data-checkbox="ASSET_GROUP" class="">主机分组管理</span></li>
## <li><span data-checkbox="ACCOUNT" class="">主机账号管理</span></li>
## <li><span data-checkbox="ACCOUNT_GROUP" class="">主机账号分组管理</span></li>
## </ul>
##
## <hr/>
## <div class="title">用户</div>
## <ul>
## <li><span href="#" class="enabled" data-checked="yes">登录WEB系统</span></li>
## <li><span href="#" class="enabled" data-checked="yes">用户创建/编辑</span></li>
## <li><span href="#" class="enabled" data-checked="yes">删除用户</span></li>
## <li><span href="#" class="">用户禁用/解禁</span></li>
## <li><span href="#" class="">用户分组管理</span></li>
## </ul>
##
## <hr/>
## <div class="title">运维</div>
## <ul>
## <li><span href="#" class="enabled" data-checked="yes">远程主机运维</span></li>
## <li><span href="#" class="">运维授权管理</span></li>
## <li><span href="#" class="enabled" data-checked="yes">查看在线会话</span></li>
## <li><span href="#" class="">阻断在线会话</span></li>
## </ul>
##
## <hr/>
## <div class="title">审计</div>
## <ul>
## <li><span href="#" class="enabled" data-checked="yes">审计(查看历史会话)</span></li>
## <li><span href="#" class="enabled" data-checked="yes">审计授权管理</span></li>
## ## <li><span href="#" class="">查看系统日志</span></li>
## </ul>
##
## <hr/>
## <div class="title">系统</div>
## <ul>
## ## <li><span href="#" class="enabled" data-checked="yes">部门管理</span></li>
##
## <li><span href="#" class="enabled">角色管理</span></li>
## <li><span href="#" class="enabled">系统配置与维护</span></li>
## <li><span href="#" class="enabled">历史会话管理</span></li>
## <li><span href="#" class="">系统日志管理</span></li>
## </ul>
<div id="save-area" style="display:none;">
<hr/>
<button id="btn-save-role" class="btn btn-sm btn-primary"><i class="fa fa-check fa-fw"></i> 保存</button>
@ -137,6 +85,6 @@
<li><em>历史会话管理</em></li>
<li><em>系统日志管理</em></li>
</ul>
<p>特别注意teleport系统使用<strong>最小权限判定规则</strong>,也即,在检查权限时,会按用户所具有的最小权限进行判断。例如:如用户无远程主机运维权限,那么即使其所在用户组被授权访问某远程主机,此用户也无法连接到该远程主机。</p>
## <p>特别注意teleport系统使用<strong>最小权限判定规则</strong>,也即,在检查权限时,会按用户所具有的最小权限进行判断。例如:如用户无远程主机运维权限,那么即使其所在用户组被授权访问某远程主机,此用户也无法连接到该远程主机。</p>
</div>
</div>

View File

@ -207,6 +207,10 @@ controllers = [
# 系统管理设置相关
# - 角色管理页面
(r'/system/role', system.RoleHandler),
# - [json] 创建/更新 角色
(r'/system/role-update', system.DoRoleUpdateHandler),
# - [json] 删除 角色
(r'/system/role-remove', system.DoRoleRemoveHandler),
# - 系统日志页面
(r'/system/syslog', system.SysLogHandler),
# - [json] 获取系统日志列表

View File

@ -1,22 +1,16 @@
# -*- coding: utf-8 -*-
import time
import csv
import os
import json
import threading
import tornado.gen
import tornado.httpclient
from app.base.configs import get_cfg
from app.base.controller import TPBaseHandler, TPBaseJsonHandler
from app.base.core_server import core_service_async_enc
from app.base.logger import *
from app.const import *
# from app.base.utils import *
from app.model import account
from app.model import group
from app.base.logger import *
from app.base.core_server import core_service_async_enc
from app.base.session import session_manager
from app.base.controller import TPBaseHandler, TPBaseJsonHandler
# cfg = get_cfg()

View File

@ -1,15 +1,15 @@
# -*- coding: utf-8 -*-
import json
import datetime
import json
import shutil
import copy
import app.model.system as system_model
import tornado.gen
from app.base import mail
from app.base.configs import get_cfg
from app.base.controller import TPBaseHandler, TPBaseJsonHandler
from app.base.logger import *
from app.const import *
from app.model import syslog
@ -52,6 +52,67 @@ class RoleHandler(TPBaseHandler):
self.render('system/role.mako')
class DoRoleUpdateHandler(TPBaseJsonHandler):
@tornado.gen.coroutine
def post(self):
ret = self.check_privilege(TP_PRIVILEGE_SYS_ROLE)
if ret != TPE_OK:
return
args = self.get_argument('args', None)
if args is None:
return self.write_json(TPE_PARAM)
try:
args = json.loads(args)
except:
return self.write_json(TPE_JSON_FORMAT)
try:
role_id = int(args['role_id'])
role_name = args['role_name']
privilege = int(args['privilege'])
except:
log.e('\n')
return self.write_json(TPE_PARAM)
if role_id == 0:
err, role_id = system_model.add_role(self, role_id, role_name, privilege)
else:
if role_id == 1:
return self.write_json(TPE_FAILED, '禁止修改系统管理员角色!')
err = system_model.update_role(self, role_id, role_name, privilege)
return self.write_json(err, data=role_id)
class DoRoleRemoveHandler(TPBaseJsonHandler):
@tornado.gen.coroutine
def post(self):
ret = self.check_privilege(TP_PRIVILEGE_SYS_ROLE)
if ret != TPE_OK:
return
args = self.get_argument('args', None)
if args is None:
return self.write_json(TPE_PARAM)
try:
args = json.loads(args)
except:
return self.write_json(TPE_JSON_FORMAT)
try:
role_id = int(args['role_id'])
except:
log.e('\n')
return self.write_json(TPE_PARAM)
if role_id == 1:
return self.write_json(TPE_FAILED, '禁止删除系统管理员角色!')
err = system_model.remove_role(self, role_id)
return self.write_json(err)
class SysLogHandler(TPBaseHandler):
def get(self):
ret = self.check_privilege(TP_PRIVILEGE_SYS_LOG)

View File

@ -291,7 +291,6 @@ def remove_accounts(handler, host_id, acc_ids):
"""
db = get_db()
acc_count = len(acc_ids)
print(acc_count)
acc_ids = ','.join([str(uid) for uid in acc_ids])
s = SQL(db)
@ -303,9 +302,6 @@ def remove_accounts(handler, host_id, acc_ids):
return err
if len(s.recorder) == 0:
return TPE_NOT_EXISTS
print(s.recorder)
s.reset().select_from('acc', ['host_ip', 'router_ip', 'router_port', 'username'], alt_name='a')
s.where('a.host_id={h_id} AND a.id IN ({ids}) '.format(h_id=host_id, ids=acc_ids))
@ -350,7 +346,6 @@ def remove_accounts(handler, host_id, acc_ids):
return err
if len(s.recorder) == 0:
return TPE_NOT_EXISTS
print(s.recorder)
syslog.sys_log(handler.get_current_user(), handler.request.remote_ip, TPE_OK, "删除账号:{}".format(''.join(acc_names)))

View File

@ -3,6 +3,8 @@
from app.const import *
from app.base.db import get_db, SQL
from app.base.logger import log
from app.base.utils import tp_timestamp_utc_now
from . import syslog
def save_mail_config(_server, _port, _ssl, _sender, _password):
@ -23,6 +25,87 @@ def save_mail_config(_server, _port, _ssl, _sender, _password):
return TPE_FAILED, '数据库操作失败'
def add_role(handler, role_id, role_name, privilege):
db = get_db()
_time_now = tp_timestamp_utc_now()
operator = handler.get_current_user()
# 1. 判断是否已经存在了
sql = 'SELECT id FROM {}role WHERE name="{name}";'.format(db.table_prefix, name=role_name)
db_ret = db.query(sql)
if db_ret is not None and len(db_ret) > 0:
return TPE_EXISTS, 0
sql = 'INSERT INTO `{}role` (name, privilege, creator_id, create_time) VALUES ' \
'("{name}", {privilege}, {creator_id}, {create_time});' \
''.format(db.table_prefix,
name=role_name, privilege=privilege, creator_id=operator['id'], create_time=_time_now)
db_ret = db.exec(sql)
if not db_ret:
return TPE_DATABASE, 0
_id = db.last_insert_id()
syslog.sys_log(operator, handler.request.remote_ip, TPE_OK, "创建角色:{}".format(role_name))
return TPE_OK, _id
def update_role(handler, role_id, role_name, privilege):
"""
更新一个远程账号
"""
db = get_db()
# 1. 判断是否存在
sql = 'SELECT id FROM {}role WHERE id={rid};'.format(db.table_prefix, rid=role_id)
db_ret = db.query(sql)
if db_ret is None or len(db_ret) == 0:
return TPE_NOT_EXISTS
sql = 'UPDATE `{}role` SET name="{name}", privilege={p} WHERE id={rid};' \
''.format(db.table_prefix, name=role_name, p=privilege, rid=role_id)
db_ret = db.exec(sql)
if not db_ret:
return TPE_DATABASE
return TPE_OK
def remove_role(handler, role_id):
db = get_db()
s = SQL(db)
# 1. 判断是否存在
s.select_from('role', ['name'], alt_name='r')
s.where('r.id={rid}'.format(rid=role_id))
err = s.query()
if err != TPE_OK:
return err
if len(s.recorder) == 0:
return TPE_NOT_EXISTS
role_name = s.recorder[0].name
sql_list = []
sql = 'DELETE FROM `{}role` WHERE id={};'.format(db.table_prefix, role_id)
sql_list.append(sql)
# 更新此角色相关的用户信息
sql = 'UPDATE `{}user` SET role_id=0 WHERE role_id={rid};'.format(db.table_prefix, rid=role_id)
sql_list.append(sql)
if not db.transaction(sql_list):
return TPE_DATABASE
syslog.sys_log(handler.get_current_user(), handler.request.remote_ip, TPE_OK, "删除角色:{}".format(''.join(role_name)))
return TPE_OK
# def get_config_list():
# try:
# from eom_app.module.common import get_db_con