diff --git a/connect.py b/connect.py index 0039aa05f..7994205ec 100644 --- a/connect.py +++ b/connect.py @@ -17,8 +17,8 @@ from multiprocessing import Pool os.environ['DJANGO_SETTINGS_MODULE'] = 'jumpserver.settings' if django.get_version() != '1.6': django.setup() -from jumpserver.api import BASE_DIR, ServerError, User, UserGroup, Asset, Jtty, get_object -from jumpserver.api import CRYPTOR, logger, is_dir +from jumpserver.api import ServerError, User, Asset, Jtty, get_object +from jumpserver.api import logger from jumpserver.api import BisGroup as AssetGroup login_user = get_object(User, username=getpass.getuser()) @@ -27,7 +27,7 @@ login_user = get_object(User, username=getpass.getuser()) def color_print(msg, color='red', exits=False): """ Print colorful string. - 颜色打印 + 颜色打印字符或者退出 """ color_msg = {'blue': '\033[1;36m%s\033[0m', 'green': '\033[1;32m%s\033[0m', @@ -40,7 +40,10 @@ def color_print(msg, color='red', exits=False): def verify_connect(user, option): - """鉴定用户是否有该主机权限 或 匹配到的ip是否唯一""" + """ + Check user was permed or not . Check ip is unique or not. + 鉴定用户是否有该主机权限 或 匹配到的ip是否唯一 + """ ip_matched = [] try: assets_info = login_user.get_asset_info() @@ -60,7 +63,7 @@ def verify_connect(user, option): logger.debug('%s matched input %s: %s' % (login_user.username, option, ip_matched)) ip_matched = list(set(ip_matched)) - if len(ip_matched) > 1: + if len(ip_matched) > 1: # 如果匹配ip不唯一 ip_comment = {} for ip in ip_matched: ip_comment[ip] = assets_info[ip][2] @@ -71,15 +74,19 @@ def verify_connect(user, option): else: print '%-15s' % ip print '' - elif len(ip_matched) < 1: + elif len(ip_matched) < 1: # 如果没匹配到 color_print('没有该主机,或者您没有该主机的权限 No Permission or No host.', 'red') - else: + else: # 恰好是1个 asset = get_object(Asset, ip=ip_matched[0]) jtty = Jtty(user, asset) jtty.connect() def print_prompt(): + """ + Print prompt + 打印提示导航 + """ msg = """\033[1;32m### Welcome Use JumpServer To Login. ### \033[0m 1) Type \033[32mIP or Part IP, Host Alias or Comments \033[0m To Login. 2) Type \033[32mP/p\033[0m To Print The Servers You Available. @@ -162,6 +169,10 @@ def print_prompt(): def main(): + """ + he he + 主程序 + """ if not login_user: # 判断用户是否存在 color_print(u'没有该用户,或许你是以root运行的 No that user.', exits=True) diff --git a/jumpserver/api.py b/jumpserver/api.py index 6cff43abd..35fd8063e 100644 --- a/jumpserver/api.py +++ b/jumpserver/api.py @@ -4,6 +4,7 @@ import os, sys, time from ConfigParser import ConfigParser import getpass from Crypto.Cipher import AES +import crypt from binascii import b2a_hex, a2b_hex import ldap from ldap import modlist @@ -13,15 +14,18 @@ import random import subprocess import paramiko import struct, fcntl, signal,socket, select, fnmatch +from functools import partial + from django.core.paginator import Paginator, EmptyPage, InvalidPage from django.http import HttpResponse, Http404 -from django.shortcuts import render_to_response +from django.template import RequestContext from juser.models import User, UserGroup, DEPT from jasset.models import Asset, BisGroup, IDC from jlog.models import Log from jasset.models import AssetAlias from django.core.exceptions import ObjectDoesNotExist from django.http import HttpResponseRedirect +from django.shortcuts import render_to_response from django.core.mail import send_mail import json import logging @@ -50,20 +54,29 @@ SEND_PORT = CONF.get('base', 'port') MAIL_FROM = CONF.get('mail', 'email_host_user') log_dir = os.path.join(BASE_DIR, 'logs') + def set_log(level): + """ + return a log file object + 根据提示设置log打印 + """ log_level_total = {'debug': logging.DEBUG, 'info': logging.INFO, 'warning': logging.WARN, 'error': logging.ERROR, 'critical': logging.CRITICAL} - logger = logging.getLogger('jumpserver') - logger.setLevel(logging.DEBUG) + logger_f = logging.getLogger('jumpserver') + logger_f.setLevel(logging.DEBUG) fh = logging.FileHandler(JLOG_FILE) fh.setLevel(log_level_total.get(level, logging.DEBUG)) formatter = logging.Formatter('%(asctime)s - %(filename)s - %(levelname)s - %(message)s') fh.setFormatter(formatter) - logger.addHandler(fh) - return logger + logger_f.addHandler(fh) + return logger_f class LDAPMgmt(): + """ + LDAP class for add, select, del, update + LDAP 管理类,增删改查 + """ def __init__(self, host_url, base_dn, @@ -77,6 +90,10 @@ class LDAPMgmt(): self.conn.simple_bind_s(root_cn, root_pw) def list(self, filter, scope=ldap.SCOPE_SUBTREE, attr=None): + """ + query + 查询 + """ result = {} try: ldap_result = self.conn.search_s(self.ldap_base_dn, scope, filter, attr) @@ -90,6 +107,10 @@ class LDAPMgmt(): print e def add(self, dn, attrs): + """ + add + 添加 + """ try: ldif = modlist.addModlist(attrs) self.conn.add_s(dn, ldif) @@ -97,6 +118,10 @@ class LDAPMgmt(): print e def modify(self, dn, attrs): + """ + modify + 更改 + """ try: attr_s = [] for k, v in attrs.items(): @@ -106,6 +131,10 @@ class LDAPMgmt(): print e def delete(self, dn): + """ + delete + 删除 + """ try: self.conn.delete_s(dn) except ldap.LDAPError, e: @@ -113,6 +142,10 @@ class LDAPMgmt(): def page_list_return(total, current=1): + """ + page + 分页,返回本次分页的最小页数到最大页数列表 + """ min_page = current - 2 if current - 4 > 0 else 1 max_page = min_page + 4 if min_page + 4 < total else total @@ -120,7 +153,10 @@ def page_list_return(total, current=1): def pages(posts, r): - """分页公用函数""" + """ + page public function , return page's object tuple + 分页公用函数,返回分页的对象元组 + """ contact_list = posts p = paginator = Paginator(contact_list, 10) try: @@ -148,6 +184,10 @@ def pages(posts, r): class Jtty(object): + """ + A virtual tty class + 一个虚拟终端类,实现连接ssh和记录日志 + """ def __init__(self, user, asset): self.chan = None self.username = user.username @@ -260,7 +300,10 @@ class Jtty(object): log.save() def get_connect_item(self): - """获取连接需要的参数,也就是服务ip, 端口, 用户账号和密码""" + """ + get args for connect: ip, port, username, passwd + 获取连接需要的参数,也就是服务ip, 端口, 用户账号和密码 + """ if not self.asset.is_active: raise ServerError('该主机被禁用 Host %s is not active.' % self.ip) @@ -283,15 +326,13 @@ class Jtty(object): else: raise ServerError('不支持的服务器登录方式 Login type is not in ["L", "M"]') - def connect(self): + def get_connection(self): """ - Connect server. - 连接服务器 + Get the ssh connection for reuse + 获取连接套接字 """ username, password, ip, port = self.get_connect_item() logger.debug("username: %s, password: %s, ip: %s, port: %s" % (username, password, ip, port)) - ps1 = "PS1='[\u@%s \W]\$ '\n" % self.ip - login_msg = "clear;echo -e '\\033[32mLogin %s done. Enjoy it.\\033[0m'\n" % ip # 发起ssh连接请求 Make a ssh connection ssh = paramiko.SSHClient() @@ -303,6 +344,19 @@ class Jtty(object): raise ServerError('认证错误 Authentication Error.') except socket.error: raise ServerError('端口可能不对 Connect SSH Socket Port Error, Please Correct it.') + else: + return ssh + + def connect(self): + """ + Connect server. + 连接服务器 + """ + ps1 = "PS1='[\u@%s \W]\$ '\n" % self.ip + login_msg = "clear;echo -e '\\033[32mLogin %s done. Enjoy it.\\033[0m'\n" % self.asset.ip + + # 发起ssh连接请求 Make a ssh connection + ssh = self.get_connection() # 获取连接的隧道并设置窗口大小 Make a channel and set windows size global channel @@ -324,11 +378,18 @@ class Jtty(object): channel.close() ssh.close() + def execute(self, cmd): + """ + execute cmd on the asset + 执行命令 + """ + pass + class PyCrypt(object): """ This class used to encrypt and decrypt password. - 对称加密库 + 加密类 """ def __init__(self, key): @@ -353,12 +414,24 @@ class PyCrypt(object): @staticmethod def md5_crypt(string): + """ + md5 encrypt method + md5非对称加密方法 + """ return hashlib.new("md5", string).hexdigest() + @staticmethod + def gen_sha512(salt, password): + """ + generate sha512 format password + 生成sha512加密密码 + """ + return crypt.crypt(password, '$6$%s$' % salt) + def encrypt(self, passwd=None): """ encrypt gen password - 加密生成密码 + 对称加密之加密生成密码 """ if not passwd: passwd = self.random_pass() @@ -376,6 +449,10 @@ class PyCrypt(object): return b2a_hex(cipher_text) def decrypt(self, text): + """ + decrypt pass base the same key + 对称加密之解密,同一个加密随机数 + """ cryptor = AES.new(self.key, self.mode, b'8122ca7d906ad5e1') try: plain_text = cryptor.decrypt(a2b_hex(text)) @@ -386,10 +463,18 @@ class PyCrypt(object): class ServerError(Exception): + """ + self define exception + 自定义异常 + """ pass def get_object(model, **kwargs): + """ + use this function for query + 使用改封装函数查询数据库 + """ try: the_object = model.objects.get(**kwargs) except ObjectDoesNotExist: @@ -399,7 +484,8 @@ def get_object(model, **kwargs): def require_role(role='user'): """ - 要求用户是某种角色 ["super", "admin", "user"] + decorator for require user role in ["super", "admin", "user"] + 要求用户是某种角色 ["super", "admin", "user"]的装饰器 """ def _deco(func): def __deco(request, *args, **kwargs): @@ -413,27 +499,30 @@ def require_role(role='user'): if request.session.get('role_id', 0) != 2: return HttpResponseRedirect('/') return func(request, *args, **kwargs) - return __deco() + return __deco return _deco def is_role_request(request, role='user'): """ - :param request: 请求 - :param role: 角色 - :return: bool + require this request of user is right 要求请求角色正确 """ role_all = {'user': 0, 'admin': 1, 'super': 2} - if request.session.get('role_id') == role_all.get(role, '0'): + if request.session.get('role_id') == role_all.get(role, 0): return True else: return False -@require_role def get_session_user_dept(request): + """ + get department of the user in session + 获取session中用户的部门 + """ user_id = request.session.get('user_id', 0) + print '#' * 20 + print user_id user = User.objects.filter(id=user_id) if user: user = user[0] @@ -443,6 +532,10 @@ def get_session_user_dept(request): @require_role def get_session_user_info(request): + """ + get the user info of the user in session, for example id, username etc. + 获取用户的信息 + """ user_id = request.session.get('user_id', 0) user = User.objects.filter(id=user_id) if user: @@ -452,6 +545,10 @@ def get_session_user_info(request): def get_user_dept(request): + """ + get the user dept id + 获取用户的部门id + """ user_id = request.session.get('user_id') if user_id: user_dept = User.objects.get(id=user_id).dept @@ -466,16 +563,24 @@ def api_user(request): return HttpResponse(json_data) -# def view_splitter(request, su=None, adm=None): -# if is_super_user(request): -# return su(request) -# elif is_group_admin(request): -# return adm(request) -# else: -# return HttpResponseRedirect('/login/') +def view_splitter(request, su=None, adm=None): + """ + for different user use different view + 视图分页器 + """ + if is_role_request(request, 'super'): + return su(request) + elif is_role_request(request, 'admin'): + return adm(request) + else: + return HttpResponseRedirect('/login/') def validate(request, user_group=None, user=None, asset_group=None, asset=None, edept=None): + """ + validate the user request + 判定用户请求是否合法 + """ dept = get_session_user_dept(request)[1] if edept: if dept.id != int(edept[0]): @@ -565,12 +670,18 @@ def verify(request, user_group=None, user=None, asset_group=None, asset=None, ed def bash(cmd): - """执行bash命令""" + """ + run a bash shell command + 执行bash命令 + """ return subprocess.call(cmd, shell=True) def is_dir(dir_name, username='root', mode=0755): - """目录存在,如果不存在就建立,并且权限正确""" + """ + insure the dir exist and mode ok + 目录存在,如果不存在就建立,并且权限正确 + """ if not os.path.isdir(dir_name): os.makedirs(dir_name) bash("chown %s:%s '%s'" % (username, username, dir_name)) diff --git a/jumpserver/context_processors.py b/jumpserver/context_processors.py index aac09c7a7..2beeed3a0 100644 --- a/jumpserver/context_processors.py +++ b/jumpserver/context_processors.py @@ -14,10 +14,12 @@ def name_proc(request): host_active_num = Asset.objects.filter(is_active=True).count() else: user, dept = get_session_user_dept(request) + print user, dept user_total_num = dept.user_set.all().count() user_active_num = dept.user_set.filter(is_active=True).count() host_total_num = dept.asset_set.all().count() host_active_num = dept.asset_set.all().filter(is_active=True).count() + pass username = User.objects.get(id=user_id).name apply_info = Apply.objects.filter(admin=username, status=0, read=0) diff --git a/jumpserver/settings.py b/jumpserver/settings.py index ce4d7e8b5..96f1617a8 100644 --- a/jumpserver/settings.py +++ b/jumpserver/settings.py @@ -56,9 +56,9 @@ INSTALLED_APPS = ( 'django.contrib.humanize', 'jumpserver', 'juser', - 'jasset', - 'jperm', - 'jlog', + # 'jasset', + # 'jperm', + # 'jlog', ) MIDDLEWARE_CLASSES = ( diff --git a/jumpserver/urls.py b/jumpserver/urls.py index bd60d04ba..c7a3eaf31 100644 --- a/jumpserver/urls.py +++ b/jumpserver/urls.py @@ -14,9 +14,9 @@ urlpatterns = patterns('', (r'^file/download/$', 'jumpserver.views.download'), (r'^error/$', 'jumpserver.views.httperror'), (r'^juser/', include('juser.urls')), - (r'^jasset/', include('jasset.urls')), - (r'^jlog/', include('jlog.urls')), - (r'^jperm/', include('jperm.urls')), + # (r'^jasset/', include('jasset.urls')), + # (r'^jlog/', include('jlog.urls')), + # (r'^jperm/', include('jperm.urls')), (r'^node_auth/', 'jumpserver.views.node_auth'), ) diff --git a/jumpserver/views.py b/jumpserver/views.py index fd151d824..e4706eab3 100644 --- a/jumpserver/views.py +++ b/jumpserver/views.py @@ -1,15 +1,18 @@ # coding: utf-8 from __future__ import division +import uuid +import urllib + from django.db.models import Count from django.shortcuts import render_to_response from django.template import RequestContext from django.http import HttpResponseNotFound +from django.http import HttpResponse from jperm.models import Apply import paramiko from jumpserver.api import * -import uuid -import urllib + def getDaysByNum(num): @@ -44,7 +47,7 @@ def get_data(data, items, option): return dic -@require_login +@require_role(role='user') def index_cu(request): user_id = request.session.get('user_id') user = User.objects.filter(id=user_id) @@ -53,7 +56,7 @@ def index_cu(request): login_types = {'L': 'LDAP', 'M': 'MAP'} user_id = request.session.get('user_id') username = User.objects.get(id=user_id).username - posts = user_perm_asset_api(username) + posts = user.get_asset() host_count = len(posts) new_posts = [] post_five = [] @@ -68,16 +71,16 @@ def index_cu(request): return render_to_response('index_cu.html', locals(), context_instance=RequestContext(request)) -@require_login +@require_role(role='user') def index(request): li_date, li_str = getDaysByNum(7) today = datetime.datetime.now().day from_week = datetime.datetime.now() - datetime.timedelta(days=7) - if is_common_user(request): + if is_role_request(request, 'user'): return index_cu(request) - elif is_super_user(request): + elif is_role_request(request, 'super'): users = User.objects.all() hosts = Asset.objects.all() online = Log.objects.filter(is_finished=0) @@ -87,7 +90,7 @@ def index(request): active_hosts = Asset.objects.filter(is_active=1) week_data = Log.objects.filter(start_time__range=[from_week, datetime.datetime.now()]) - elif is_group_admin(request): + elif is_role_request(request, 'admin'): user = get_session_user_info(request)[2] dept_name, dept = get_session_user_info(request)[4:] users = User.objects.filter(dept=dept) @@ -205,7 +208,7 @@ def login(request): user_filter = User.objects.filter(username=username) if user_filter: user = user_filter[0] - if md5_crypt(password) == user.password: + if PyCrypt.md5_crypt(password) == user.password: request.session['user_id'] = user.id user_filter.update(last_login=datetime.datetime.now()) if user.role == 'SU': @@ -216,7 +219,7 @@ def login(request): request.session['role_id'] = 0 response = HttpResponseRedirect('/', ) response.set_cookie('username', username, expires=604800) - response.set_cookie('seed', md5_crypt(password), expires=604800) + response.set_cookie('seed', PyCrypt.md5_crypt(password), expires=604800) return response else: error = '密码错误,请重新输入。' @@ -248,7 +251,7 @@ def filter_ajax_api(request): def install(request): from juser.models import DEPT, User if User.objects.filter(id=5000): - return httperror(request, 'Jumpserver已初始化,不能重复安装!') + return http_error(request, 'Jumpserver已初始化,不能重复安装!') dept = DEPT(id=1, name="超管部", comment="超级管理部门") dept.save() @@ -257,7 +260,7 @@ def install(request): IDC(id=1, name="默认", comment="默认IDC").save() BisGroup(id=1, name="ALL", dept=dept, comment="所有主机组").save() - User(id=5000, username="admin", password=md5_crypt('admin'), + User(id=5000, username="admin", password=PyCrypt.md5_crypt('admin'), name='admin', email='admin@jumpserver.org', role='SU', is_active=True, dept=dept).save() return http_success(request, u'Jumpserver初始化成功') @@ -278,55 +281,56 @@ def transfer(sftp, filenames): def upload(request): - user, dept = get_session_user_dept(request) - if request.method == 'POST': - hosts = request.POST.get('hosts') - upload_files = request.FILES.getlist('file[]', None) - upload_dir = "/tmp/%s" % user.username - is_dir(upload_dir) - date_now = datetime.datetime.now().strftime("%Y%m%d%H%M%S") - hosts_list = hosts.split(',') - user_hosts = get_user_host(user.username).keys() - unperm_hosts = [] - filenames = {} - for ip in hosts_list: - if ip not in user_hosts: - unperm_hosts.append(ip) - - if not hosts: - return HttpResponseNotFound(u'地址不能为空') - - if unperm_hosts: - print hosts_list - return HttpResponseNotFound(u'%s 没有权限.' % ', '.join(unperm_hosts)) - - for upload_file in upload_files: - file_path = '%s/%s.%s' % (upload_dir, upload_file.name, date_now) - filenames[upload_file.name] = file_path - f = open(file_path, 'w') - for chunk in upload_file.chunks(): - f.write(chunk) - f.close() - - sftps = [] - for host in hosts_list: - username, password, host, port = get_connect_item(user.username, host) - try: - t = paramiko.Transport((host, port)) - t.connect(username=username, password=password) - sftp = paramiko.SFTPClient.from_transport(t) - sftps.append(sftp) - except paramiko.AuthenticationException: - return HttpResponseNotFound(u'%s 连接失败.' % host) - - # pool = Pool(processes=5) - for sftp in sftps: - transfer(sftp, filenames) - # pool.close() - # pool.join() - return HttpResponse('传送成功') - - return render_to_response('upload.html', locals(), context_instance=RequestContext(request)) + pass +# user, dept = get_session_user_dept(request) +# if request.method == 'POST': +# hosts = request.POST.get('hosts') +# upload_files = request.FILES.getlist('file[]', None) +# upload_dir = "/tmp/%s" % user.username +# is_dir(upload_dir) +# date_now = datetime.datetime.now().strftime("%Y%m%d%H%M%S") +# hosts_list = hosts.split(',') +# user_hosts = [asset.ip for asset in user.get_asset()] +# unperm_hosts = [] +# filenames = {} +# for ip in hosts_list: +# if ip not in user_hosts: +# unperm_hosts.append(ip) +# +# if not hosts: +# return HttpResponseNotFound(u'地址不能为空') +# +# if unperm_hosts: +# print hosts_list +# return HttpResponseNotFound(u'%s 没有权限.' % ', '.join(unperm_hosts)) +# +# for upload_file in upload_files: +# file_path = '%s/%s.%s' % (upload_dir, upload_file.name, date_now) +# filenames[upload_file.name] = file_path +# f = open(file_path, 'w') +# for chunk in upload_file.chunks(): +# f.write(chunk) +# f.close() +# +# sftps = [] +# for host in hosts_list: +# username, password, host, port = get_connect_item(user.username, host) +# try: +# t = paramiko.Transport((host, port)) +# t.connect(username=username, password=password) +# sftp = paramiko.SFTPClient.from_transport(t) +# sftps.append(sftp) +# except paramiko.AuthenticationException: +# return HttpResponseNotFound(u'%s 连接失败.' % host) +# +# # pool = Pool(processes=5) +# for sftp in sftps: +# transfer(sftp, filenames) +# # pool.close() +# # pool.join() +# return HttpResponse('传送成功') +# +# return render_to_response('upload.html', locals(), context_instance=RequestContext(request)) def node_auth(request): diff --git a/juser/views.py b/juser/views.py index 83bca8921..f3d5525f4 100644 --- a/juser/views.py +++ b/juser/views.py @@ -4,174 +4,15 @@ import random from Crypto.PublicKey import RSA -import crypt from django.db.models import Q from django.template import RequestContext from django.db.models import ObjectDoesNotExist -from jumpserver.api import * +from juser.user_api import * -def md5_crypt(string): - return hashlib.new("md5", string).hexdigest() - - -def gen_rand_pwd(num): - """ - generate random password - 生成随机密码 - """ - seed = "1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" - salt_list = [] - for i in range(num): - salt_list.append(random.choice(seed)) - salt = ''.join(salt_list) - return salt - - -def gen_sha512(salt, password): - """ - generate sha512 format password - 生成sha512加密密码 - """ - return crypt.crypt(password, '$6$%s$' % salt) - - -def group_add_user(group, user_id=None, username=None): - """ - 用户组中添加用户 - UserGroup Add a user - """ - if user_id: - user = get_object(User, id=user_id) - else: - user = get_object(User, username=username) - group.user_set.add(user) - - -def db_add_group(**kwargs): - name = kwargs.get('name') - group = UserGroup.objects.filter(name=name) - users = kwargs.pop('users') - if group: - raise ServerError(u'用户组 %s 已经存在' % name) - group = UserGroup(**kwargs) - group.save() - for user_id in users: - group_add_user(group, user_id) - - -def db_add_user(**kwargs): - groups_post = kwargs.pop('groups') - user = User(**kwargs) - user.save() - if groups_post: - group_select = [] - for group_id in groups_post: - group = UserGroup.objects.filter(id=group_id) - group_select.extend(group) - user.group = group_select - return user - - -def db_update_user(**kwargs): - groups_post = kwargs.pop('groups') - user_id = kwargs.pop('user_id') - user = User.objects.filter(id=user_id) - if user: - user.update(**kwargs) - user = User.objects.get(id=user_id) - user.save() - - if groups_post: - group_select = [] - for group_id in groups_post: - group = UserGroup.objects.filter(id=group_id) - group_select.extend(group) - user.group = group_select - - -def db_del_user(username): - try: - user = User.objects.get(username=username) - user.delete() - except ObjectDoesNotExist: - pass - - -def gen_ssh_key(username, password=None, length=2048): - private_key_dir = os.path.join(BASE_DIR, 'keys/jumpserver/') - private_key_file = os.path.join(private_key_dir, username+".pem") - public_key_dir = '/home/%s/.ssh/' % username - public_key_file = os.path.join(public_key_dir, 'authorized_keys') - is_dir(private_key_dir) - is_dir(public_key_dir, username, mode=0700) - - key = RSA.generate(length) - with open(private_key_file, 'w') as pri_f: - pri_f.write(key.exportKey('PEM', password)) - os.chmod(private_key_file, 0600) - - pub_key = key.publickey() - with open(public_key_file, 'w') as pub_f: - pub_f.write(pub_key.exportKey('OpenSSH')) - os.chmod(public_key_file, 0600) - bash('chown %s:%s %s' % (username, username, public_key_file)) - - -def server_add_user(username, password, ssh_key_pwd): - bash("useradd '%s'; echo '%s' | passwd --stdin '%s'" % (username, password, username)) - gen_ssh_key(username, ssh_key_pwd) - - -def server_del_user(username): - bash('userdel -r %s' % username) - - -def ldap_add_user(username, ldap_pwd): - user_dn = "uid=%s,ou=People,%s" % (username, LDAP_BASE_DN) - password_sha512 = gen_sha512(gen_rand_pwd(6), ldap_pwd) - user = User.objects.filter(username=username) - if user: - user = user[0] - else: - raise ServerError(u'用户 %s 不存在' % username) - - user_attr = {'uid': [str(username)], - 'cn': [str(username)], - 'objectClass': ['account', 'posixAccount', 'top', 'shadowAccount'], - 'userPassword': ['{crypt}%s' % password_sha512], - 'shadowLastChange': ['16328'], - 'shadowMin': ['0'], - 'shadowMax': ['99999'], - 'shadowWarning': ['7'], - 'loginShell': ['/bin/bash'], - 'uidNumber': [str(user.id)], - 'gidNumber': [str(user.id)], - 'homeDirectory': [str('/home/%s' % username)]} - - group_dn = "cn=%s,ou=Group,%s" % (username, LDAP_BASE_DN) - group_attr = {'objectClass': ['posixGroup', 'top'], - 'cn': [str(username)], - 'userPassword': ['{crypt}x'], - 'gidNumber': [str(user.id)]} - - ldap_conn.add(user_dn, user_attr) - ldap_conn.add(group_dn, group_attr) - - -def ldap_del_user(username): - user_dn = "uid=%s,ou=People,%s" % (username, LDAP_BASE_DN) - group_dn = "cn=%s,ou=Group,%s" % (username, LDAP_BASE_DN) - sudo_dn = 'cn=%s,ou=Sudoers,%s' % (username, LDAP_BASE_DN) - - ldap_conn.delete(user_dn) - ldap_conn.delete(group_dn) - ldap_conn.delete(sudo_dn) - - -@require_super_user +@require_role(role='super') def dept_add(request): header_title, path1, path2 = '添加部门', '用户管理', '添加部门' if request.method == 'POST': @@ -192,7 +33,7 @@ def dept_add(request): return render_to_response('juser/dept_add.html', locals(), context_instance=RequestContext(request)) -@require_super_user +@require_role(role='super') def dept_list(request): header_title, path1, path2 = '查看部门', '用户管理', '查看部门' keyword = request.GET.get('search') @@ -206,7 +47,7 @@ def dept_list(request): return render_to_response('juser/dept_list.html', locals(), context_instance=RequestContext(request)) -@require_admin +@require_role(role='admin') def dept_list_adm(request): header_title, path1, path2 = '查看部门', '用户管理', '查看部门' user, dept = get_session_user_dept(request) @@ -226,7 +67,7 @@ def chg_role(request): return HttpResponseRedirect('/') -@require_super_user +@require_role(role='super') def dept_detail(request): dept_id = request.GET.get('id', None) if not dept_id: @@ -238,7 +79,7 @@ def dept_detail(request): return render_to_response('juser/dept_detail.html', locals(), context_instance=RequestContext(request)) -@require_super_user +@require_role(role='super') def dept_del(request): dept_id = request.GET.get('id', None) if not dept_id or dept_id in ['1', '2']: @@ -276,7 +117,7 @@ def dept_member_update(dept, users_id_list): user.save() -@require_super_user +@require_role(role='super') def dept_del_ajax(request): dept_ids = request.POST.get('dept_ids') for dept_id in dept_ids.split(','): @@ -285,7 +126,7 @@ def dept_del_ajax(request): return HttpResponse("删除成功") -@require_super_user +@require_role(role='super') def dept_edit(request): header_title, path1, path2 = '部门编辑', '用户管理', '部门编辑' if request.method == 'GET': @@ -331,7 +172,7 @@ def dept_user_ajax(request): -@require_super_user +@require_role(role='super') def group_add(request): error = '' msg = '' @@ -372,7 +213,7 @@ def group_add(request): return render_to_response('juser/group_add.html', locals(), context_instance=RequestContext(request)) -@require_admin +@require_role(role='admin') def group_add_adm(request): error = '' msg = '' @@ -403,7 +244,7 @@ def group_add_adm(request): return render_to_response('juser/group_add.html', locals(), context_instance=RequestContext(request)) -@require_super_user +@require_role(role='super') def group_list(request): header_title, path1, path2 = '查看小组', '用户管理', '查看小组' keyword = request.GET.get('search', '') @@ -423,7 +264,7 @@ def group_list(request): return render_to_response('juser/group_list.html', locals(), context_instance=RequestContext(request)) -@require_admin +@require_role(role='admin') def group_list_adm(request): header_title, path1, path2 = '查看部门小组', '用户管理', '查看小组' keyword = request.GET.get('search', '') @@ -438,7 +279,7 @@ def group_list_adm(request): return render_to_response('juser/group_list.html', locals(), context_instance=RequestContext(request)) -@require_admin +@require_role(role='admin') def group_detail(request): group_id = request.GET.get('id', None) if not group_id: @@ -448,7 +289,7 @@ def group_detail(request): return render_to_response('juser/group_detail.html', locals(), context_instance=RequestContext(request)) -@require_super_user +@require_role(role='super') def group_del(request): group_id = request.GET.get('id', '') if not group_id: @@ -457,7 +298,7 @@ def group_del(request): return HttpResponseRedirect('/juser/group_list/') -@require_admin +@require_role(role='admin') def group_del_adm(request): group_id = request.GET.get('id', '') if not validate(request, user_group=[group_id]): @@ -468,7 +309,7 @@ def group_del_adm(request): return HttpResponseRedirect('/juser/group_list/') -@require_admin +@require_role(role='admin') def group_del_ajax(request): group_ids = request.POST.get('group_ids') group_ids = group_ids.split(',') @@ -490,7 +331,7 @@ def group_update_member(group_id, users_id_list): group.user_set.add(user) -@require_super_user +@require_role(role='super') def group_edit(request): error = '' msg = '' @@ -538,7 +379,7 @@ def group_edit(request): return HttpResponseRedirect('/juser/group_list/') -@require_admin +@require_role(role='admin') def group_edit_adm(request): error = '' msg = '' @@ -586,7 +427,7 @@ def group_edit_adm(request): return HttpResponseRedirect('/juser/group_list/') -@require_super_user +@require_role(role='super') def user_add(request): error = '' msg = '' @@ -597,15 +438,15 @@ def user_add(request): if request.method == 'POST': username = request.POST.get('username', '') - password = gen_rand_pwd(16) + password = PyCrypt.gen_rand_pwd(16) name = request.POST.get('name', '') email = request.POST.get('email', '') dept_id = request.POST.get('dept_id') groups = request.POST.getlist('groups', []) role_post = request.POST.get('role', 'CU') - ssh_key_pwd = gen_rand_pwd(16) + ssh_key_pwd = PyCrypt.gen_rand_pwd(16) is_active = True if request.POST.get('is_active', '1') == '1' else False - ldap_pwd = gen_rand_pwd(16) + ldap_pwd = PyCrypt.gen_rand_pwd(16) try: if '' in [username, password, ssh_key_pwd, name, groups, role_post, is_active]: @@ -667,7 +508,7 @@ def user_add(request): return render_to_response('juser/user_add.html', locals(), context_instance=RequestContext(request)) -@require_admin +@require_role(role='admin') def user_add_adm(request): error = '' msg = '' @@ -677,13 +518,13 @@ def user_add_adm(request): if request.method == 'POST': username = request.POST.get('username', '') - password = gen_rand_pwd(16) + password = PyCrypt.gen_rand_pwd(16) name = request.POST.get('name', '') email = request.POST.get('email', '') groups = request.POST.getlist('groups', []) - ssh_key_pwd = gen_rand_pwd(16) + ssh_key_pwd = PyCrypt.gen_rand_pwd(16) is_active = True if request.POST.get('is_active', '1') == '1' else False - ldap_pwd = gen_rand_pwd(16) + ldap_pwd = PyCrypt.gen_rand_pwd(16) try: if '' in [username, password, ssh_key_pwd, name, groups, is_active]: @@ -739,7 +580,7 @@ def user_add_adm(request): return render_to_response('juser/user_add.html', locals(), context_instance=RequestContext(request)) -@require_super_user +@require_role(role='super') def user_list(request): user_role = {'SU': u'超级管理员', 'GA': u'组管理员', 'CU': u'普通用户'} header_title, path1, path2 = '查看用户', '用户管理', '用户列表' @@ -768,7 +609,7 @@ def user_list(request): return render_to_response('juser/user_list.html', locals(), context_instance=RequestContext(request)) -@require_admin +@require_role(role='admin') def user_list_adm(request): user_role = {'SU': u'超级管理员', 'GA': u'组管理员', 'CU': u'普通用户'} header_title, path1, path2 = '查看用户', '用户管理', '用户列表' @@ -793,7 +634,7 @@ def user_list_adm(request): return render_to_response('juser/user_list.html', locals(), context_instance=RequestContext(request)) -@require_login +@require_role(role='user') def user_detail(request): header_title, path1, path2 = '查看用户', '用户管理', '用户详情' if request.session.get('role_id') == 0: @@ -810,7 +651,7 @@ def user_detail(request): user = User.objects.filter(id=user_id) if user: user = user[0] - asset_group_permed = user_perm_group_api(user) + asset_group_permed = user.get_asset_group() logs_last = Log.objects.filter(user=user.name).order_by('-start_time')[0:10] logs_all = Log.objects.filter(user=user.name).order_by('-start_time') logs_num = len(logs_all) @@ -818,7 +659,7 @@ def user_detail(request): return render_to_response('juser/user_detail.html', locals(), context_instance=RequestContext(request)) -@require_admin +@require_role(role='admin') def user_del(request): user_id = request.GET.get('id', '') if not user_id: @@ -838,7 +679,7 @@ def user_del(request): return HttpResponseRedirect('/juser/user_list/') -@require_admin +@require_role(role='admin') def user_del_ajax(request): user_ids = request.POST.get('ids') user_ids = user_ids.split(',') @@ -857,7 +698,7 @@ def user_del_ajax(request): return HttpResponse('删除成功') -@require_super_user +@require_role(role='super') def user_edit(request): header_title, path1, path2 = '编辑用户', '用户管理', '用户编辑' if request.method == 'GET': @@ -920,7 +761,7 @@ def user_edit(request): return render_to_response('juser/user_edit.html', locals(), context_instance=RequestContext(request)) -@require_admin +@require_role(role='admin') def user_edit_adm(request): header_title, path1, path2 = '编辑用户', '用户管理', '用户编辑' user, dept = get_session_user_dept(request) @@ -1020,21 +861,18 @@ def chg_info(request): return render_to_response('juser/chg_info.html', locals(), context_instance=RequestContext(request)) - - - -@require_login +@require_role(role='user') def down_key(request): user_id = '' - if is_super_user(request): + if is_role_request(request, 'super'): user_id = request.GET.get('id') - if is_group_admin(request): + if is_role_request(request, 'admin'): user_id = request.GET.get('id') if not validate(request, user=[user_id]): user_id = request.session.get('user_id') - if is_common_user(request): + if is_role_request(request, 'user'): user_id = request.session.get('user_id') if user_id: diff --git a/templates/base.html b/templates/base.html index 729ec6fb7..d325e9ff1 100644 --- a/templates/base.html +++ b/templates/base.html @@ -11,6 +11,7 @@ {% include 'link_css.html' %} {% include 'head_script.html' %} + {% block self_head_css_js %} {% endblock %} @@ -30,4 +31,5 @@ {% include 'foot_script.html' %} + {% block self_footer_js %} {% endblock %} diff --git a/templates/juser/dept_add.html b/templates/juser/dept_add.html index 799336f81..322df22e5 100644 --- a/templates/juser/dept_add.html +++ b/templates/juser/dept_add.html @@ -15,12 +15,7 @@ - + @@ -38,37 +33,13 @@
{% if error %} - + {% else %} - + {% endif %}
- -{#
#} -{#
#} -{# #} -{#
#} -{# #} -{#
#} -{#
#} -{#
#} -{# #} -{# #} -{#
#} -{#
#} -{#
#} -{#
#} -{# #} -{#
#} -{#
#} -{#
#}
@@ -95,6 +66,9 @@
+{% endblock %} + +{% block self_footer_js %}