角色管理功能完成。

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"; "use strict";
$app.on_init = function (cb_stack) { $app.on_init = function (cb_stack) {
$app.last_role_id = 0; $app.last_role_id = 0; // todo: 使用数组的方式管理选择历史
$app.selected_role_id = 0; $app.selected_role_id = 0;
$app.edit_mode = false; $app.edit_mode = false;
$app.dom = { $app.dom = {
role_list: $('#role-list'), role_list: $('#role-list'),
btn_edit_role: $('#btn-edit-role'), 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_save_role: $('#btn-save-role'),
btn_cancel_edit_role: $('#btn-cancel-edit-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'), role_info: $('#role-info'),
privilege_list: $('#privilege-list') privilege_list: $('#privilege-list')
@ -48,6 +32,7 @@ $app.on_init = function (cb_stack) {
}; };
$app.create_controls = function () { $app.create_controls = function () {
console.log($app.role_list);
var nodes = []; var nodes = [];
var selected_role_id = 0; var selected_role_id = 0;
for (var i = 0; i < $app.role_list.length; ++i) { 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.role_list.append($(nodes.join('')));
$app.dom.btn_create_role = $('#btn-create-role'); $app.dom.btn_create_role = $('#btn-create-role');
var privileges = [ var privileges = [
{ {
t: '资产', i: [ t: '资产', i: [
@ -130,6 +114,9 @@ $app.create_controls = function () {
$app.show_role(role_id, false); $app.show_role(role_id, false);
}); });
$app.dom.privilege_list.find('[data-privilege]').click(function () { $app.dom.privilege_list.find('[data-privilege]').click(function () {
if (!$app.edit_mode)
return;
var obj = $(this); var obj = $(this);
if (obj.hasClass('enabled')) { if (obj.hasClass('enabled')) {
obj.removeClass('enabled'); obj.removeClass('enabled');
@ -137,27 +124,41 @@ $app.create_controls = function () {
obj.addClass('enabled'); obj.addClass('enabled');
} }
if (!$app.edit_mode) { // if (!$app.edit_mode) {
$app.edit_mode = true; // $app.edit_mode = true;
$app.dom.role.save_area.slideDown(); // $app.dom.role.save_area.slideDown();
} // }
}); });
$app.dom.btn_edit_role.click(function () { $app.dom.btn_edit_role.click(function () {
$app.show_role($app.selected_role_id, true); $app.show_role($app.selected_role_id, true);
}); });
$app.dom.btn_cancel_edit_role.click(function () { $app.dom.btn_cancel_edit_role.click(function () {
if ($app.selected_role_id !== 0) if ($app.selected_role_id !== 0)
$app.show_role($app.selected_role_id, false); $app.show_role($app.selected_role_id, false);
else else
$app.show_role($app.last_role_id, false); $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) { $app.show_role = function (role_id, edit_mode) {
var edit = edit_mode || false; var edit = edit_mode || false;
var role = null; var role = null;
if (role_id === 1 && edit_mode) {
$tp.notify_error('禁止修改管理员角色!');
return;
}
if (role_id === 0) { if (role_id === 0) {
role = {id: 0, name: '', privilege: 0}; role = {id: 0, name: '', privilege: 0};
edit = true; edit = true;
@ -205,3 +206,122 @@ $app.show_role = function (role_id, edit_mode) {
if (role_id !== 0) if (role_id !== 0)
$app.last_role_id = role_id; $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>
<div class="stats-content"> <div class="stats-content">
<div class="stats-name">用户</div> <div class="stats-name">用户</div>
<div class="stats-value">21</div> <div class="stats-value">-</div>
</div> </div>
</div> </div>
</div> </div>
@ -38,7 +38,7 @@
</div> </div>
<div class="stats-content"> <div class="stats-content">
<div class="stats-name">主机</div> <div class="stats-name">主机</div>
<div class="stats-value">128</div> <div class="stats-value">-</div>
</div> </div>
</div> </div>
</div> </div>
@ -49,7 +49,7 @@
</div> </div>
<div class="stats-content"> <div class="stats-content">
<div class="stats-name">主机账号</div> <div class="stats-name">主机账号</div>
<div class="stats-value">63</div> <div class="stats-value">-</div>
</div> </div>
</div> </div>
</div> </div>
@ -60,7 +60,7 @@
</div> </div>
<div class="stats-content"> <div class="stats-content">
<div class="stats-name">当前连接</div> <div class="stats-name">当前连接</div>
<div class="stats-value">18</div> <div class="stats-value">-</div>
</div> </div>
</div> </div>
</div> </div>

View File

@ -20,8 +20,6 @@
<i class="fa fa-info-circle fa-fw icon-bg"></i> 角色就是一组权限的集合。 <i class="fa fa-info-circle fa-fw icon-bg"></i> 角色就是一组权限的集合。
</div> </div>
## <div style="padding:10px 0;">角色列表 <a href="javascript:;"><i class="fa fa-plus-circle fa-fw"></i> 创建新角色</a></div>
<div> <div>
<table class="table table-role"> <table class="table table-role">
<tr> <tr>
@ -30,7 +28,6 @@
<ul id="role-list"></ul> <ul id="role-list"></ul>
</td> </td>
<td id="role-info" class="role-privilege editable"> <td id="role-info" class="role-privilege editable">
## <td id="role-info" class="role-privilege">
<div> <div>
<div style="float:left;"> <div style="float:left;">
@ -43,62 +40,13 @@
</div> </div>
<div style="float:right;"> <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-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>
<div class="clear-float"></div> <div class="clear-float"></div>
</div> </div>
<div id="privilege-list"></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;"> <div id="save-area" style="display:none;">
<hr/> <hr/>
<button id="btn-save-role" class="btn btn-sm btn-primary"><i class="fa fa-check fa-fw"></i> 保存</button> <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>
<li><em>系统日志管理</em></li> <li><em>系统日志管理</em></li>
</ul> </ul>
<p>特别注意teleport系统使用<strong>最小权限判定规则</strong>,也即,在检查权限时,会按用户所具有的最小权限进行判断。例如:如用户无远程主机运维权限,那么即使其所在用户组被授权访问某远程主机,此用户也无法连接到该远程主机。</p> ## <p>特别注意teleport系统使用<strong>最小权限判定规则</strong>,也即,在检查权限时,会按用户所具有的最小权限进行判断。例如:如用户无远程主机运维权限,那么即使其所在用户组被授权访问某远程主机,此用户也无法连接到该远程主机。</p>
</div> </div>
</div> </div>

View File

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

View File

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

View File

@ -1,15 +1,15 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import json
import datetime import datetime
import json
import shutil import shutil
import copy
import app.model.system as system_model import app.model.system as system_model
import tornado.gen import tornado.gen
from app.base import mail from app.base import mail
from app.base.configs import get_cfg from app.base.configs import get_cfg
from app.base.controller import TPBaseHandler, TPBaseJsonHandler from app.base.controller import TPBaseHandler, TPBaseJsonHandler
from app.base.logger import *
from app.const import * from app.const import *
from app.model import syslog from app.model import syslog
@ -52,6 +52,67 @@ class RoleHandler(TPBaseHandler):
self.render('system/role.mako') 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): class SysLogHandler(TPBaseHandler):
def get(self): def get(self):
ret = self.check_privilege(TP_PRIVILEGE_SYS_LOG) 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() db = get_db()
acc_count = len(acc_ids) acc_count = len(acc_ids)
print(acc_count)
acc_ids = ','.join([str(uid) for uid in acc_ids]) acc_ids = ','.join([str(uid) for uid in acc_ids])
s = SQL(db) s = SQL(db)
@ -303,9 +302,6 @@ def remove_accounts(handler, host_id, acc_ids):
return err return err
if len(s.recorder) == 0: if len(s.recorder) == 0:
return TPE_NOT_EXISTS return TPE_NOT_EXISTS
print(s.recorder)
s.reset().select_from('acc', ['host_ip', 'router_ip', 'router_port', 'username'], alt_name='a') 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)) 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 return err
if len(s.recorder) == 0: if len(s.recorder) == 0:
return TPE_NOT_EXISTS return TPE_NOT_EXISTS
print(s.recorder)
syslog.sys_log(handler.get_current_user(), handler.request.remote_ip, TPE_OK, "删除账号:{}".format(''.join(acc_names))) 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.const import *
from app.base.db import get_db, SQL from app.base.db import get_db, SQL
from app.base.logger import log 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): 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, '数据库操作失败' 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(): # def get_config_list():
# try: # try:
# from eom_app.module.common import get_db_con # from eom_app.module.common import get_db_con