添加忘记密码

pull/26/head
ibuler 2015-08-31 23:04:53 +08:00
parent 44c69ded78
commit c21cdc2131
15 changed files with 475 additions and 321 deletions

View File

@ -262,70 +262,70 @@ def unicode2str(unicode_list):
return [str(i) for i in unicode_list] return [str(i) for i in unicode_list]
def sudo_ldap_add(user_group, user_runas, asset_groups_select, # def sudo_ldap_add(user_group, user_runas, asset_groups_select,
cmd_groups_select): # cmd_groups_select):
if not LDAP_ENABLE: # if not LDAP_ENABLE:
return True # return True
#
assets = [] # assets = []
cmds = [] # cmds = []
user_runas = user_runas.split(',') # user_runas = user_runas.split(',')
if len(asset_groups_select) == 1 and asset_groups_select[0].name == 'ALL': # if len(asset_groups_select) == 1 and asset_groups_select[0].name == 'ALL':
asset_all = True # asset_all = True
else: # else:
asset_all = False # asset_all = False
for asset_group in asset_groups_select: # for asset_group in asset_groups_select:
assets.extend(asset_group.asset_set.all()) # assets.extend(asset_group.asset_set.all())
#
# if user_group.name == 'ALL':
# user_all = True
# users = []
# else:
# user_all = False
# users = user_group.user_set.all()
#
# for cmd_group in cmd_groups_select:
# cmds.extend(cmd_group.cmd.split(','))
#
# if user_all:
# users_name = ['ALL']
# else:
# users_name = list(set([user.username for user in users]))
#
# if asset_all:
# assets_ip = ['ALL']
# else:
# assets_ip = list(set([asset.ip for asset in assets]))
#
# name = 'sudo%s' % user_group.id
# sudo_dn = 'cn=%s,ou=Sudoers,%s' % (name, LDAP_BASE_DN)
# sudo_attr = {'objectClass': ['top', 'sudoRole'],
# 'cn': ['%s' % name],
# 'sudoCommand': unicode2str(cmds),
# 'sudoHost': unicode2str(assets_ip),
# 'sudoOption': ['!authenticate'],
# 'sudoRunAsUser': unicode2str(user_runas),
# 'sudoUser': unicode2str(users_name)}
# ldap_conn.delete(sudo_dn)
# ldap_conn.add(sudo_dn, sudo_attr)
if user_group.name == 'ALL': #
user_all = True # def sudo_update(user_group, user_runas, asset_groups_select, cmd_groups_select, comment):
users = [] # asset_groups_select_list, cmd_groups_select_list = \
else: # asset_cmd_groups_get(asset_groups_select, cmd_groups_select)
user_all = False # sudo_perm = user_group.sudoperm_set.all()
users = user_group.user_set.all() # if sudo_perm:
# sudo_perm.update(user_runas=user_runas, comment=comment)
for cmd_group in cmd_groups_select: # sudo_perm = sudo_perm[0]
cmds.extend(cmd_group.cmd.split(',')) # sudo_perm.asset_group = asset_groups_select_list
# sudo_perm.cmd_group = cmd_groups_select_list
if user_all: # else:
users_name = ['ALL'] # sudo_perm = SudoPerm(user_group=user_group, user_runas=user_runas, comment=comment)
else: # sudo_perm.save()
users_name = list(set([user.username for user in users])) # sudo_perm.asset_group = asset_groups_select_list
# sudo_perm.cmd_group = cmd_groups_select_list
if asset_all: #
assets_ip = ['ALL'] # sudo_ldap_add(user_group, user_runas, asset_groups_select_list, cmd_groups_select_list)
else:
assets_ip = list(set([asset.ip for asset in assets]))
name = 'sudo%s' % user_group.id
sudo_dn = 'cn=%s,ou=Sudoers,%s' % (name, LDAP_BASE_DN)
sudo_attr = {'objectClass': ['top', 'sudoRole'],
'cn': ['%s' % name],
'sudoCommand': unicode2str(cmds),
'sudoHost': unicode2str(assets_ip),
'sudoOption': ['!authenticate'],
'sudoRunAsUser': unicode2str(user_runas),
'sudoUser': unicode2str(users_name)}
ldap_conn.delete(sudo_dn)
ldap_conn.add(sudo_dn, sudo_attr)
def sudo_update(user_group, user_runas, asset_groups_select, cmd_groups_select, comment):
asset_groups_select_list, cmd_groups_select_list = \
asset_cmd_groups_get(asset_groups_select, cmd_groups_select)
sudo_perm = user_group.sudoperm_set.all()
if sudo_perm:
sudo_perm.update(user_runas=user_runas, comment=comment)
sudo_perm = sudo_perm[0]
sudo_perm.asset_group = asset_groups_select_list
sudo_perm.cmd_group = cmd_groups_select_list
else:
sudo_perm = SudoPerm(user_group=user_group, user_runas=user_runas, comment=comment)
sudo_perm.save()
sudo_perm.asset_group = asset_groups_select_list
sudo_perm.cmd_group = cmd_groups_select_list
sudo_ldap_add(user_group, user_runas, asset_groups_select_list, cmd_groups_select_list)
@require_super_user @require_super_user

View File

@ -1,8 +1,7 @@
#coding: utf8 #coding: utf8
[base] [base]
ip = 192.168.20.209 url = http://192.168.244.129
port = 80
key = 88aaaf7ffe3c6c04 key = 88aaaf7ffe3c6c04
log = debug log = debug

View File

@ -6,15 +6,12 @@ import getpass
from Crypto.Cipher import AES from Crypto.Cipher import AES
import crypt import crypt
from binascii import b2a_hex, a2b_hex from binascii import b2a_hex, a2b_hex
import ldap
from ldap import modlist
import hashlib import hashlib
import datetime import datetime
import random import random
import subprocess import subprocess
import paramiko import paramiko
import struct, fcntl, signal,socket, select, fnmatch import struct, fcntl, signal,socket, select, fnmatch
from functools import partial
from django.core.paginator import Paginator, EmptyPage, InvalidPage from django.core.paginator import Paginator, EmptyPage, InvalidPage
from django.http import HttpResponse, Http404 from django.http import HttpResponse, Http404
@ -23,7 +20,7 @@ from juser.models import User, UserGroup
from jasset.models import Asset, BisGroup, IDC from jasset.models import Asset, BisGroup, IDC
from jlog.models import Log from jlog.models import Log
from jasset.models import AssetAlias from jasset.models import AssetAlias
from django.core.exceptions import ObjectDoesNotExist from django.core.exceptions import ObjectDoesNotExist, MultipleObjectsReturned
from django.http import HttpResponseRedirect from django.http import HttpResponseRedirect
from django.shortcuts import render_to_response from django.shortcuts import render_to_response
from django.core.mail import send_mail from django.core.mail import send_mail
@ -48,9 +45,8 @@ SSH_KEY_DIR = os.path.join(BASE_DIR, 'keys')
# SERVER_KEY_DIR = os.path.join(SSH_KEY_DIR, 'server') # SERVER_KEY_DIR = os.path.join(SSH_KEY_DIR, 'server')
KEY = CONF.get('base', 'key') KEY = CONF.get('base', 'key')
LOGIN_NAME = getpass.getuser() LOGIN_NAME = getpass.getuser()
LDAP_ENABLE = CONF.getint('ldap', 'ldap_enable') # LDAP_ENABLE = CONF.getint('ldap', 'ldap_enable')
SEND_IP = CONF.get('base', 'ip') URL = CONF.get('base', 'url')
SEND_PORT = CONF.get('base', 'port')
MAIL_ENABLE = CONF.get('mail', 'mail_enable') MAIL_ENABLE = CONF.get('mail', 'mail_enable')
MAIL_FROM = CONF.get('mail', 'email_host_user') MAIL_FROM = CONF.get('mail', 'email_host_user')
log_dir = os.path.join(BASE_DIR, 'logs') log_dir = os.path.join(BASE_DIR, 'logs')
@ -73,73 +69,73 @@ def set_log(level):
return logger_f return logger_f
class LDAPMgmt(): # class LDAPMgmt():
""" # """
LDAP class for add, select, del, update # LDAP class for add, select, del, update
LDAP 管理类增删改查 # LDAP 管理类,增删改查
""" # """
def __init__(self, # def __init__(self,
host_url, # host_url,
base_dn, # base_dn,
root_cn, # root_cn,
root_pw): # root_pw):
self.ldap_host = host_url # self.ldap_host = host_url
self.ldap_base_dn = base_dn # self.ldap_base_dn = base_dn
self.conn = ldap.initialize(host_url) # self.conn = ldap.initialize(host_url)
self.conn.set_option(ldap.OPT_REFERRALS, 0) # self.conn.set_option(ldap.OPT_REFERRALS, 0)
self.conn.protocol_version = ldap.VERSION3 # self.conn.protocol_version = ldap.VERSION3
self.conn.simple_bind_s(root_cn, root_pw) # self.conn.simple_bind_s(root_cn, root_pw)
#
def list(self, filter, scope=ldap.SCOPE_SUBTREE, attr=None): # def list(self, filter, scope=ldap.SCOPE_SUBTREE, attr=None):
""" # """
query # query
查询 # 查询
""" # """
result = {} # result = {}
try: # try:
ldap_result = self.conn.search_s(self.ldap_base_dn, scope, filter, attr) # ldap_result = self.conn.search_s(self.ldap_base_dn, scope, filter, attr)
for entry in ldap_result: # for entry in ldap_result:
name, data = entry # name, data = entry
for k, v in data.items(): # for k, v in data.items():
print '%s: %s' % (k, v) # print '%s: %s' % (k, v)
result[k] = v # result[k] = v
return result # return result
except ldap.LDAPError, e: # except ldap.LDAPError, e:
print e # print e
#
def add(self, dn, attrs): # def add(self, dn, attrs):
""" # """
add # add
添加 # 添加
""" # """
try: # try:
ldif = modlist.addModlist(attrs) # ldif = modlist.addModlist(attrs)
self.conn.add_s(dn, ldif) # self.conn.add_s(dn, ldif)
except ldap.LDAPError, e: # except ldap.LDAPError, e:
print e # print e
#
def modify(self, dn, attrs): # def modify(self, dn, attrs):
""" # """
modify # modify
更改 # 更改
""" # """
try: # try:
attr_s = [] # attr_s = []
for k, v in attrs.items(): # for k, v in attrs.items():
attr_s.append((2, k, v)) # attr_s.append((2, k, v))
self.conn.modify_s(dn, attr_s) # self.conn.modify_s(dn, attr_s)
except ldap.LDAPError, e: # except ldap.LDAPError, e:
print e # print e
#
def delete(self, dn): # def delete(self, dn):
""" # """
delete # delete
删除 # 删除
""" # """
try: # try:
self.conn.delete_s(dn) # self.conn.delete_s(dn)
except ldap.LDAPError, e: # except ldap.LDAPError, e:
print e # print e
def page_list_return(total, current=1): def page_list_return(total, current=1):
@ -480,9 +476,10 @@ def get_object(model, **kwargs):
use this function for query use this function for query
使用改封装函数查询数据库 使用改封装函数查询数据库
""" """
try: the_object = model.objects.filter(**kwargs)
the_object = model.objects.get(**kwargs) if len(the_object) == 1:
except ObjectDoesNotExist: the_object = the_object[0]
else:
the_object = None the_object = None
return the_object return the_object
@ -498,10 +495,10 @@ def require_role(role='user'):
if not request.session.get('user_id'): if not request.session.get('user_id'):
return HttpResponseRedirect('/login/') return HttpResponseRedirect('/login/')
elif role == 'admin': elif role == 'admin':
if request.session.get('role_id', 0) != 1: if request.session.get('role_id', 0) < 1:
return HttpResponseRedirect('/') return HttpResponseRedirect('/')
elif role == 'super': elif role == 'super':
if request.session.get('role_id', 0) != 2: if request.session.get('role_id', 0) < 2:
return HttpResponseRedirect('/') return HttpResponseRedirect('/')
return func(request, *args, **kwargs) return func(request, *args, **kwargs)
return __deco return __deco
@ -531,8 +528,7 @@ def get_session_user_dept(request):
user = User.objects.filter(id=user_id) user = User.objects.filter(id=user_id)
if user: if user:
user = user[0] user = user[0]
dept = user.dept return user, None
return user, dept
@require_role @require_role
@ -704,14 +700,14 @@ def http_error(request, emg):
CRYPTOR = PyCrypt(KEY) CRYPTOR = PyCrypt(KEY)
if LDAP_ENABLE: # if LDAP_ENABLE:
LDAP_HOST_URL = CONF.get('ldap', 'host_url') # LDAP_HOST_URL = CONF.get('ldap', 'host_url')
LDAP_BASE_DN = CONF.get('ldap', 'base_dn') # LDAP_BASE_DN = CONF.get('ldap', 'base_dn')
LDAP_ROOT_DN = CONF.get('ldap', 'root_dn') # LDAP_ROOT_DN = CONF.get('ldap', 'root_dn')
LDAP_ROOT_PW = CONF.get('ldap', 'root_pw') # LDAP_ROOT_PW = CONF.get('ldap', 'root_pw')
ldap_conn = LDAPMgmt(LDAP_HOST_URL, LDAP_BASE_DN, LDAP_ROOT_DN, LDAP_ROOT_PW) # ldap_conn = LDAPMgmt(LDAP_HOST_URL, LDAP_BASE_DN, LDAP_ROOT_DN, LDAP_ROOT_PW)
else: # else:
ldap_conn = None # ldap_conn = None
log_level = CONF.get('base', 'log') log_level = CONF.get('base', 'log')
logger = set_log(log_level) logger = set_log(log_level)

View File

@ -213,7 +213,7 @@ def login(request):
user_filter.update(last_login=datetime.datetime.now()) user_filter.update(last_login=datetime.datetime.now())
if user.role == 'SU': if user.role == 'SU':
request.session['role_id'] = 2 request.session['role_id'] = 2
elif user.role == 'DA': elif user.role == 'GA':
request.session['role_id'] = 1 request.session['role_id'] = 1
else: else:
request.session['role_id'] = 0 request.session['role_id'] = 0

View File

@ -30,8 +30,8 @@ class User(models.Model):
name = models.CharField(max_length=80) name = models.CharField(max_length=80)
email = models.EmailField(max_length=75) email = models.EmailField(max_length=75)
role = models.CharField(max_length=2, choices=USER_ROLE_CHOICES, default='CU') role = models.CharField(max_length=2, choices=USER_ROLE_CHOICES, default='CU')
uuid = models.CharField(max_length=100)
group = models.ManyToManyField(UserGroup) group = models.ManyToManyField(UserGroup)
ldap_pwd = models.CharField(max_length=128)
ssh_key_pwd = models.CharField(max_length=200) ssh_key_pwd = models.CharField(max_length=200)
is_active = models.BooleanField(default=True) is_active = models.BooleanField(default=True)
last_login = models.DateTimeField(null=True) last_login = models.DateTimeField(null=True)
@ -128,4 +128,6 @@ class AdminGroup(models.Model):
""" """
user = models.ForeignKey(User) user = models.ForeignKey(User)
group = models.ForeignKey(UserGroup) group = models.ForeignKey(UserGroup)

View File

@ -13,7 +13,10 @@ urlpatterns = patterns('juser.views',
(r'^group_del_ajax', group_del_ajax), (r'^group_del_ajax', group_del_ajax),
(r'^group_edit/$', group_edit), (r'^group_edit/$', group_edit),
(r'^user_add/$', user_add), (r'^user_add/$', user_add),
(r'^user_list/$', view_splitter, {'su': user_list, 'adm': user_list_adm}), (r'^user_list/$', user_list),
(r'^send_mail_retry/$', send_mail_retry),
(r'^reset_password/$', reset_password),
(r'^forget_password/$', forget_password),
(r'^user_detail/$', 'user_detail'), (r'^user_detail/$', 'user_detail'),
(r'^user_del/$', 'user_del'), (r'^user_del/$', 'user_del'),
(r'^user_del_ajax/$', 'user_del_ajax'), (r'^user_del_ajax/$', 'user_del_ajax'),

View File

@ -101,11 +101,9 @@ def db_del_user(username):
delete a user from database delete a user from database
从数据库中删除用户 从数据库中删除用户
""" """
try: user = get_object(User, username=username)
user = User.objects.get(username=username) if user:
user.delete() user.delete()
except ObjectDoesNotExist:
pass
def gen_ssh_key(username, password=None, length=2048): def gen_ssh_key(username, password=None, length=2048):
@ -134,13 +132,14 @@ def gen_ssh_key(username, password=None, length=2048):
print "gen_ssh_key_end" + str(time.time()) print "gen_ssh_key_end" + str(time.time())
def server_add_user(username, password, ssh_key_pwd): def server_add_user(username, password, ssh_key_pwd, ssh_key_login_need):
""" """
add a system user in jumpserver add a system user in jumpserver
在jumpserver服务器上添加一个用户 在jumpserver服务器上添加一个用户
""" """
bash("useradd '%s'; echo '%s' | passwd --stdin '%s'" % (username, password, username)) bash("useradd '%s'; echo '%s'; echo '%s' | passwd --stdin '%s'" % (username, password, password, username))
gen_ssh_key(username, ssh_key_pwd) if ssh_key_login_need:
gen_ssh_key(username, ssh_key_pwd)
def user_add_mail(user, kwargs): def user_add_mail(user, kwargs):
@ -156,10 +155,10 @@ def user_add_mail(user, kwargs):
您的角色 %s 您的角色 %s
您的web登录密码 %s 您的web登录密码 %s
您的ssh密钥文件密码 %s 您的ssh密钥文件密码 %s
密钥下载地址 http://%s:%s/juser/down_key/?id=%s 密钥下载地址 %s/juser/down_key/?uuid=%s
说明 请登陆后再下载密钥 说明 请登陆后再下载密钥
""" % (user.name, user.username, user_role.get(user.role, u'普通用户'), """ % (user.name, user.username, user_role.get(user.role, u'普通用户'),
kwargs.get('password'), kwargs.get('ssh_key_pwd'), SEND_IP, SEND_PORT, user.id) kwargs.get('password'), kwargs.get('ssh_key_pwd'), URL, user.uuid)
send_mail(mail_title, mail_msg, MAIL_FROM, [user.email], fail_silently=False) send_mail(mail_title, mail_msg, MAIL_FROM, [user.email], fail_silently=False)
@ -171,49 +170,73 @@ def server_del_user(username):
bash('userdel -r %s' % username) bash('userdel -r %s' % username)
def ldap_add_user(username, ldap_pwd): def get_display_msg(user, password, ssh_key_pwd, ssh_key_login_need, send_mail_need):
""" if send_mail_need:
add a user in ldap database msg = u'添加用户 %s 成功! 用户密码已发送到 %s 邮箱!' % (user.name, user.email)
在LDAP中添加用户 return msg
"""
user_dn = "uid=%s,ou=People,%s" % (username, LDAP_BASE_DN)
password_sha512 = PyCrypt.gen_sha512(PyCrypt.random_pass(6), ldap_pwd)
user = get_object(User, username=username)
if not user:
raise ServerError(u'用户 %s 不存在' % username)
user_attr = {'uid': [str(username)], if ssh_key_login_need:
'cn': [str(username)], msg = u"""
'objectClass': ['account', 'posixAccount', 'top', 'shadowAccount'], 跳板机地址 %s
'userPassword': ['{crypt}%s' % password_sha512], 用户名%s
'shadowLastChange': ['16328'], 密码%s
'shadowMin': ['0'], 密钥密码%s
'shadowMax': ['99999'], 密钥下载url: %s/juser/down_key/?id=%s
'shadowWarning': ['7'], 该账号密码可以登陆web和跳板机
'loginShell': ['/bin/bash'], """ % (URL, user.username, password, ssh_key_pwd, URL, user.id)
'uidNumber': [str(user.id)], else:
'gidNumber': [str(user.id)], msg = u"""
'homeDirectory': [str('/home/%s' % username)]} 跳板机地址 %s \n
用户名%s \n
密码%s \n
该账号密码可以登陆web和跳板机
""" % (URL, user.username, password)
group_dn = "cn=%s,ou=Group,%s" % (username, LDAP_BASE_DN) return msg
group_attr = {'objectClass': ['posixGroup', 'top'],
'cn': [str(username)],
'userPassword': ['{crypt}x'],
'gidNumber': [str(user.id)]}
ldap_conn.add(user_dn, user_attr) # def ldap_add_user(username, ldap_pwd):
ldap_conn.add(group_dn, group_attr) # """
# add a user in ldap database
# 在LDAP中添加用户
# """
# user_dn = "uid=%s,ou=People,%s" % (username, LDAP_BASE_DN)
# password_sha512 = PyCrypt.gen_sha512(PyCrypt.random_pass(6), ldap_pwd)
# user = get_object(User, username=username)
# if not user:
# 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): # def ldap_del_user(username):
""" # """
delete a user in ldap database # delete a user in ldap database
在ldap中删除某用户 # 在ldap中删除某用户
""" # """
user_dn = "uid=%s,ou=People,%s" % (username, LDAP_BASE_DN) # user_dn = "uid=%s,ou=People,%s" % (username, LDAP_BASE_DN)
group_dn = "cn=%s,ou=Group,%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) # sudo_dn = 'cn=%s,ou=Sudoers,%s' % (username, LDAP_BASE_DN)
#
ldap_conn.delete(user_dn) # ldap_conn.delete(user_dn)
ldap_conn.delete(group_dn) # ldap_conn.delete(group_dn)
ldap_conn.delete(sudo_dn) # ldap_conn.delete(sudo_dn)

View File

@ -4,6 +4,7 @@
import random import random
from Crypto.PublicKey import RSA from Crypto.PublicKey import RSA
import uuid as uuid_r
from django.db.models import Q from django.db.models import Q
from django.template import RequestContext from django.template import RequestContext
@ -235,13 +236,15 @@ def user_add(request):
groups = request.POST.getlist('groups', []) groups = request.POST.getlist('groups', [])
admin_groups = request.POST.getlist('admin_groups', []) admin_groups = request.POST.getlist('admin_groups', [])
role = request.POST.get('role', 'CU') role = request.POST.get('role', 'CU')
uuid = uuid_r.uuid1()
ssh_key_pwd = PyCrypt.random_pass(16) ssh_key_pwd = PyCrypt.random_pass(16)
extra = request.POST.getlist('extra', []) extra = request.POST.getlist('extra', [])
is_active = True if '0' in extra else False is_active = True if '0' in extra else False
ldap_pwd = PyCrypt.random_pass(32, especial=True) ssh_key_login_need = True if '1' in extra else False
send_mail_need = True if '2' in extra else False
try: try:
if '' in [username, password, ssh_key_pwd, name, groups, role, is_active]: if '' in [username, password, ssh_key_pwd, name, role]:
error = u'带*内容不能为空' error = u'带*内容不能为空'
raise ServerError raise ServerError
user_test = get_object(User, username=username) user_test = get_object(User, username=username)
@ -253,30 +256,25 @@ def user_add(request):
pass pass
else: else:
try: try:
user = db_add_user(username=username, user = db_add_user(username=username, name=name,
password=CRYPTOR.md5_crypt(password), password=CRYPTOR.md5_crypt(password),
name=name, email=email, role=role, email=email, role=role, uuid=uuid,
groups=groups, admin_groups=admin_groups, groups=groups, admin_groups=admin_groups,
ssh_key_pwd=CRYPTOR.md5_crypt(ssh_key_pwd), ssh_key_pwd=CRYPTOR.md5_crypt(ssh_key_pwd),
ldap_pwd=CRYPTOR.encrypt(ldap_pwd),
is_active=is_active, is_active=is_active,
date_joined=datetime.datetime.now()) date_joined=datetime.datetime.now())
if LDAP_ENABLE: server_add_user(username, password, ssh_key_pwd, ssh_key_login_need)
ldap_add_user(username, ldap_pwd) except Exception, e:
except IndexError, e:
error = u'添加用户 %s 失败 %s ' % (username, e) error = u'添加用户 %s 失败 %s ' % (username, e)
try: try:
db_del_user(username) db_del_user(username)
server_del_user(username) server_del_user(username)
if LDAP_ENABLE:
ldap_del_user(username)
except Exception: except Exception:
pass pass
else: else:
if MAIL_ENABLE: if MAIL_ENABLE and send_mail_need:
user_add_mail(user, kwargs=locals()) user_add_mail(user, kwargs=locals())
msg = u'添加用户 %s 成功! 用户密码已发送到 %s 邮箱!' % (username, email) msg = get_display_msg(user, password, ssh_key_pwd, ssh_key_login_need, send_mail_need)
return render_to_response('juser/user_add.html', locals(), context_instance=RequestContext(request)) return render_to_response('juser/user_add.html', locals(), context_instance=RequestContext(request))
@ -358,7 +356,6 @@ def user_list(request):
header_title, path1, path2 = '查看用户', '用户管理', '用户列表' header_title, path1, path2 = '查看用户', '用户管理', '用户列表'
keyword = request.GET.get('keyword', '') keyword = request.GET.get('keyword', '')
gid = request.GET.get('gid', '') gid = request.GET.get('gid', '')
did = request.GET.get('did', '')
contact_list = User.objects.all().order_by('name') contact_list = User.objects.all().order_by('name')
if gid: if gid:
@ -367,12 +364,6 @@ def user_list(request):
user_group = user_group[0] user_group = user_group[0]
contact_list = user_group.user_set.all() contact_list = user_group.user_set.all()
if did:
dept = DEPT.objects.filter(id=did)
if dept:
dept = dept[0]
contact_list = dept.user_set.all().order_by('name')
if keyword: if keyword:
contact_list = contact_list.filter(Q(username__icontains=keyword) | Q(name__icontains=keyword)).order_by('name') contact_list = contact_list.filter(Q(username__icontains=keyword) | Q(name__icontains=keyword)).order_by('name')
@ -381,49 +372,48 @@ def user_list(request):
return render_to_response('juser/user_list.html', locals(), context_instance=RequestContext(request)) return render_to_response('juser/user_list.html', locals(), context_instance=RequestContext(request))
@require_role(role='admin') # @require_role(role='admin')
def user_list_adm(request): # def user_list_adm(request):
user_role = {'SU': u'超级管理员', 'GA': u'组管理员', 'CU': u'普通用户'} # user_role = {'SU': u'超级管理员', 'GA': u'组管理员', 'CU': u'普通用户'}
header_title, path1, path2 = '查看用户', '用户管理', '用户列表' # header_title, path1, path2 = '查看用户', '用户管理', '用户列表'
keyword = request.GET.get('keyword', '') # keyword = request.GET.get('keyword', '')
user, dept = get_session_user_dept(request) # user, dept = get_session_user_dept(request)
gid = request.GET.get('gid', '') # gid = request.GET.get('gid', '')
contact_list = dept.user_set.all().order_by('name') # contact_list = dept.user_set.all().order_by('name')
#
if gid: # if gid:
if not validate(request, user_group=[gid]): # if not validate(request, user_group=[gid]):
return HttpResponseRedirect('/juser/user_list/') # return HttpResponseRedirect('/juser/user_list/')
user_group = UserGroup.objects.filter(id=gid) # user_group = UserGroup.objects.filter(id=gid)
if user_group: # if user_group:
user_group = user_group[0] # user_group = user_group[0]
contact_list = user_group.user_set.all() # contact_list = user_group.user_set.all()
#
if keyword: # if keyword:
contact_list = contact_list.filter(Q(username__icontains=keyword) | Q(name__icontains=keyword)).order_by('name') # contact_list = contact_list.filter(Q(username__icontains=keyword) | Q(name__icontains=keyword)).order_by('name')
#
contact_list, p, contacts, page_range, current_page, show_first, show_end = pages(contact_list, request) # contact_list, p, contacts, page_range, current_page, show_first, show_end = pages(contact_list, request)
#
return render_to_response('juser/user_list.html', locals(), context_instance=RequestContext(request)) # return render_to_response('juser/user_list.html', locals(), context_instance=RequestContext(request))
@require_role(role='user') @require_role(role='user')
def user_detail(request): def user_detail(request):
header_title, path1, path2 = '查看用户', '用户管理', '用户详情' header_title, path1, path2 = '用户详情', '用户管理', '用户详情'
if request.session.get('role_id') == 0: if request.session.get('role_id') == 0:
user_id = request.session.get('user_id') user_id = request.session.get('user_id')
else: else:
user_id = request.GET.get('id', '') user_id = request.GET.get('id', '')
if request.session.get('role_id') == 1: # if request.session.get('role_id') == 1:
user, dept = get_session_user_dept(request) # user, dept = get_session_user_dept(request)
if not validate(request, user=[user_id]): # if not validate(request, user=[user_id]):
return HttpResponseRedirect('/') # return HttpResponseRedirect('/')
if not user_id: # if not user_id:
return HttpResponseRedirect('/juser/user_list/') # return HttpResponseRedirect('/juser/user_list/')
user = User.objects.filter(id=user_id) user = get_object(User, id=user_id)
if user: if user:
user = user[0] # asset_group_permed = user.get_asset_group()
asset_group_permed = user.get_asset_group()
logs_last = Log.objects.filter(user=user.name).order_by('-start_time')[0:10] 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_all = Log.objects.filter(user=user.name).order_by('-start_time')
logs_num = len(logs_all) logs_num = len(logs_all)
@ -437,17 +427,10 @@ def user_del(request):
if not user_id: if not user_id:
return HttpResponseRedirect('/juser/user_list/') return HttpResponseRedirect('/juser/user_list/')
if request.session.get('role_id', '') == '1': user = get_object(User, id=user_id)
if not validate(request, user=[user_id]): if user and user.username != 'admin':
return HttpResponseRedirect('/juser/user_list/')
user = User.objects.filter(id=user_id)
if user and user[0].username != 'admin':
user = user[0]
user.delete() user.delete()
server_del_user(user.username) server_del_user(user.username)
if LDAP_ENABLE:
ldap_del_user(user.username)
return HttpResponseRedirect('/juser/user_list/') return HttpResponseRedirect('/juser/user_list/')
@ -458,32 +441,97 @@ def user_del_ajax(request):
if request.session.get('role_id', '') == 1: if request.session.get('role_id', '') == 1:
if not validate(request, user=user_ids): if not validate(request, user=user_ids):
return "error" return "error"
for user_id in user_ids: for user_id in user_ids:
user = User.objects.filter(id=user_id) user = get_object(User, id=user_id)
if user and user[0].username != 'admin': if user and user.username != 'admin':
user = user[0]
user.delete() user.delete()
server_del_user(user.username) server_del_user(user.username)
if LDAP_ENABLE:
ldap_del_user(user.username)
return HttpResponse('删除成功') return HttpResponse('删除成功')
@require_role('admin')
def send_mail_retry(request):
user_uuid = request.GET.get('uuid', '1')
user = get_object(User, uuid=user_uuid)
msg = u"""
跳板机地址 %s
用户名%s
重设密码%s/juser/forget_password/
请登录web重新生成key
""" % (URL, user.username, URL)
try:
send_mail(u'邮件重发', msg, MAIL_FROM, [user.email], fail_silently=False)
except IndexError:
return Http404
return HttpResponse('发送成功')
def forget_password(request):
if request.method == 'POST':
email = request.POST.get('email', '')
username = request.POST.get('username', '')
user = get_object(User, username=username, email=email)
if user:
timestamp = int(time.time())
hash_encode = PyCrypt.md5_crypt(str(user.uuid) + str(timestamp) + KEY)
msg = u"""
Hi %s, 请点击下面链接重设密码
%s/juser/reset_password/?uuid=%s&timestamp=%s&hash=%s
""" % (user.name, URL, user.uuid, timestamp, hash_encode)
send_mail('忘记跳板机密码', msg, MAIL_FROM, [email], fail_silently=False)
msg = u'请登陆邮箱,点击邮件重设密码'
return HttpResponse(msg)
else:
error = u'用户不存在或邮件地址错误'
return render_to_response('juser/forget_password.html', locals())
def reset_password(request):
uuid = request.GET.get('uuid', '')
timestamp = request.GET.get('timestamp', '')
hash_encode = request.GET.get('hash', '')
action = '/juser/reset_password/?uuid=%s&timestamp=%s&hash=%s' % (uuid, timestamp, hash_encode)
if request.method == 'POST':
password = request.POST.get('password')
password_confirm = request.POST.get('password_confirm')
if password != password_confirm:
return HttpResponse('密码不匹配')
else:
user = get_object(User, uuid=uuid)
if user:
user.password = PyCrypt.md5_crypt(password)
user.save()
return HttpResponse('密码重设成功')
else:
return HttpResponse('用户不存在')
if hash_encode == PyCrypt.md5_crypt(uuid + timestamp + KEY):
if int(time.time()) - int(timestamp) > 600:
return HttpResponse('链接已超时')
else:
return render_to_response('juser/reset_password.html', locals())
return http_error(request, u'错误请求')
@require_role(role='super') @require_role(role='super')
def user_edit(request): def user_edit(request):
header_title, path1, path2 = '编辑用户', '用户管理', '用户编辑' header_title, path1, path2 = '编辑用户', '用户管理', '编辑用户'
if request.method == 'GET': if request.method == 'GET':
user_id = request.GET.get('id', '') user_id = request.GET.get('id', '')
if not user_id: if not user_id:
return HttpResponseRedirect('/') return HttpResponseRedirect('/')
user_role = {'SU': u'超级管理员', 'DA': u'部门管理员', 'CU': u'普通用户'} user_role = {'SU': u'超级管理员', 'DA': u'组管理员', 'CU': u'普通用户'}
user = User.objects.filter(id=user_id) user = get_object(User, id=user_id)
dept_all = DEPT.objects.all()
group_all = UserGroup.objects.all() group_all = UserGroup.objects.all()
if user: if user:
user = user[0]
groups_str = ' '.join([str(group.id) for group in user.group.all()]) groups_str = ' '.join([str(group.id) for group in user.group.all()])
else: else:

View File

@ -3516,8 +3516,8 @@ body.modal-open {
z-index: 100; z-index: 100;
} }
.lockscreen.middle-box { .lockscreen.middle-box {
width: 200px; width: 400px;
margin-left: -100px; margin-left: -200px;
margin-top: -190px; margin-top: -190px;
} }
.loginscreen.middle-box { .loginscreen.middle-box {

View File

@ -0,0 +1,53 @@
<html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>忘记密码</title>
<link href="/static/css/bootstrap.min.css" rel="stylesheet">
<link href="/static/font-awesome/css/font-awesome.css" rel="stylesheet">
<link href="/static/css/animate.css" rel="stylesheet">
<link href="/static/css/style.css" rel="stylesheet">
<style type="text/css"></style></head>
<body class="gray-bg">
<div class="lock-word animated fadeInDown">
<span class="first-word">Jumperver</span>
</div>
<div class="middle-box text-center lockscreen animated fadeInDown">
<div>
<div class="m-b-md">
{# <img alt="image" class="img-circle circle-border" src="https://s3.amazonaws.com/uifaces/faces/twitter/ok/128.jpg">#}
{% if error %}
<div class="alert alert-warning text-center">{{ error }}</div>
{% endif %}
{% if msg %}
<div class="alert alert-success text-center">{{ msg }}</div>
{% endif %}
</div>
<h3>忘记密码</h3>
<p>请输入您原来的信息</p>
<form class="m-t" role="form" action="" method="post">
<div class="form-group">
<input type="text" name='username' class="form-control" placeholder="Username" required="">
</div>
<div class="form-group">
<input type="text" name='email' class="form-control" placeholder="Email" required="">
</div>
<button type="submit" class="btn btn-primary block full-width">确定</button>
</form>
</div>
</div>
<!-- Mainly scripts -->
<script src="/static/js/jquery-2.1.1.js"></script>
<script src="/static/js/bootstrap.min.js"></script>
</body></html>

View File

@ -0,0 +1,50 @@
<html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>重置{{ name }}</title>
<link href="/static/css/bootstrap.min.css" rel="stylesheet">
<link href="/static/font-awesome/css/font-awesome.css" rel="stylesheet">
<link href="/static/css/animate.css" rel="stylesheet">
<link href="/static/css/style.css" rel="stylesheet">
<style type="text/css"></style></head>
<body class="gray-bg">
<div class="lock-word animated fadeInDown">
<span class="first-word">Jump</span><span>Server</span>
</div>
<div class="middle-box text-center lockscreen animated fadeInDown">
<div>
<div class="m-b-md">
{# <img alt="image" class="img-circle circle-border" src="https://s3.amazonaws.com/uifaces/faces/twitter/ok/128.jpg">#}
{% if error %}
<div class="alert alert-warning text-center">{{ error }}</div>
{% endif %}
{% if msg %}
<div class="alert alert-success text-center">{{ msg }}</div>
{% endif %}
</div>
<h3>请输入新密码</h3>
<form class="m-t" role="form" action="{{ action }}" method="post">
<div class="form-group">
<input type="password" name='password' class="form-control" placeholder="New Password" required="">
<input type="password" name='password_confirm' class="form-control" placeholder="Password Confirm" required="">
</div>
<button type="submit" class="btn btn-primary block full-width">确定</button>
</form>
</div>
</div>
<!-- Mainly scripts -->
<script src="/static/js/jquery-2.1.1.js"></script>
<script src="/static/js/bootstrap.min.js"></script>
</body></html>

View File

@ -96,7 +96,7 @@
<div class="form-group"><label class="col-sm-2 control-label">额外</label> <div class="form-group"><label class="col-sm-2 control-label">额外</label>
<div class="col-sm-2"> <div class="col-sm-2">
<div class="checkbox i-checks"> <div class="checkbox i-checks">
<label><input type="checkbox" value="0" name="extra" checked>禁用 </label> <label><input type="checkbox" value="0" name="extra" >禁用 </label>
</div> </div>
</div> </div>
<div class="col-sm-2"> <div class="col-sm-2">
@ -106,7 +106,7 @@
</div> </div>
<div class="col-sm-2"> <div class="col-sm-2">
<div class="checkbox i-checks"> <div class="checkbox i-checks">
<label><input type="checkbox" value="1" name="extra">发送邮件 </label> <label><input type="checkbox" value="2" name="extra">发送邮件 </label>
</div> </div>
</div> </div>
</div> </div>

View File

@ -17,12 +17,6 @@
<a class="dropdown-toggle" data-toggle="dropdown" href="#"> <a class="dropdown-toggle" data-toggle="dropdown" href="#">
<i class="fa fa-wrench"></i> <i class="fa fa-wrench"></i>
</a> </a>
<ul class="dropdown-menu dropdown-user">
<li><a href="#">未启用 1</a>
</li>
<li><a href="#">未启用 2</a>
</li>
</ul>
<a class="close-link"> <a class="close-link">
<i class="fa fa-times"></i> <i class="fa fa-times"></i>
</a> </a>
@ -71,23 +65,6 @@
</div> </div>
</div> </div>
<div class="hr-line-dashed"></div> <div class="hr-line-dashed"></div>
{% ifequal session_role_id 2 %}
<div class="form-group">
<label for="dept_id" class="col-lg-2 control-label">部门<span class="red-fonts">*</span></label>
<div class="col-sm-8">
<select id="dept_id" name="dept_id" class="form-control m-b">
{% for dept in dept_all %}
{% ifequal user.dept.id dept.id %}
<option selected value="{{ dept.id }}">{{ dept.name }}</option>
{% else %}
<option value="{{ dept.id }}">{{ dept.name }}</option>
{% endifequal %}
{% endfor %}
</select>
</div>
</div>
<div class="hr-line-dashed"></div>
{% endifequal %}
<div class="form-group"> <div class="form-group">
<label for="groups" class="col-lg-2 control-label">小组</label> <label for="groups" class="col-lg-2 control-label">小组</label>
<div class="col-sm-8"> <div class="col-sm-8">

View File

@ -37,7 +37,7 @@
<input type="text" class="form-control input-sm" id="search_input" name="keyword" placeholder="Search"> <input type="text" class="form-control input-sm" id="search_input" name="keyword" placeholder="Search">
<div class="input-group-btn"> <div class="input-group-btn">
<button id='search_btn' type="submit" class="btn btn-sm btn-primary"> <button id='search_btn' type="submit" class="btn btn-sm btn-primary">
Search - 搜索 -
</button> </button>
</div> </div>
</div> </div>
@ -52,7 +52,6 @@
</th> </th>
<th class="text-center">用户名</th> <th class="text-center">用户名</th>
<th class="text-center">姓名</th> <th class="text-center">姓名</th>
<th class="text-center">部门</th>
<th class="text-center">小组</th> <th class="text-center">小组</th>
<th class="text-center">角色</th> <th class="text-center">角色</th>
<th class="text-center">激活</th> <th class="text-center">激活</th>
@ -68,20 +67,15 @@
</td> </td>
<td class="text-center"> {{ user.username }} </td> <td class="text-center"> {{ user.username }} </td>
<td class="text-center"> {{ user.name }} </td> <td class="text-center"> {{ user.name }} </td>
<td class="text-center"> {{ user.dept.name }} </td>
<td class="text-center" title="{% for user_group in user.group.all %} {{ user_group.name }} {% endfor %}"> {{ user.group.all | group_str2 }} </td> <td class="text-center" title="{% for user_group in user.group.all %} {{ user_group.name }} {% endfor %}"> {{ user.group.all | group_str2 }} </td>
<td class="text-center"> {{ user.id | get_role }}</td> <td class="text-center"> {{ user.id | get_role }}</td>
<td class="text-center">{{ user.is_active|bool2str }}</td> <td class="text-center">{{ user.is_active|bool2str }}</td>
<td class="text-center"><a href="/juser/down_key/?id={{ user.id }}">下载</a></td> <td class="text-center"><a href="/juser/down_key/?id={{ user.id }}">下载</a></td>
<td class="text-center"> <td class="text-center">
<a href="../user_detail/?id={{ user.id }}" class="btn btn-xs btn-primary">详情</a> <a href="../user_detail/?id={{ user.id }}" class="btn btn-xs btn-primary">详情</a>
{% ifequal session_role_id 2 %}
<a href="../user_edit/?id={{ user.id }}" class="btn btn-xs btn-info">编辑</a> <a href="../user_edit/?id={{ user.id }}" class="btn btn-xs btn-info">编辑</a>
<a value="{{ user.uuid }}" class="btn btn-xs btn-warning email">Email</a>
<a href="../user_del/?id={{ user.id }}" class="btn btn-xs btn-danger {% if user.username == 'admin' %} disabled {% endif %}">删除</a> <a href="../user_del/?id={{ user.id }}" class="btn btn-xs btn-danger {% if user.username == 'admin' %} disabled {% endif %}">删除</a>
{% else %}
<a href="../user_edit/?id={{ user.id }}" class="btn btn-xs btn-info {% if user.role != 'CU' %} disabled {% endif %}">编辑</a>
<a href="../user_del/?id={{ user.id }}" class="btn btn-xs btn-danger {% if user.role != 'CU' %} disabled {% endif %}">删除</a>
{% endifequal %}
</td> </td>
</tr> </tr>
{% endfor %} {% endfor %}
@ -101,6 +95,8 @@
</div> </div>
</div> </div>
{% endblock %}
{% block self_head_css_js %}
<script> <script>
$(document).ready(function(){ $(document).ready(function(){
$(".iframe").on('click', function() { $(".iframe").on('click', function() {
@ -117,23 +113,30 @@
iframe: {src: url} iframe: {src: url}
}) })
}); });
var check_array = []; var check_array = [];
$('#del_btn').click(function(){ $('#del_btn').click(function(){
if (confirm("确定删除")) { if (confirm("确定删除")) {
$(".gradeX input:checked").each(function() {check_array.push($(this).attr("value")) }); $(".gradeX input:checked").each(function() {check_array.push($(this).attr("value")) });
$(".gradeX input:checked").closest("tr").remove();
$.post("/juser/user_del_ajax/", $.post("/juser/user_del_ajax/",
{ids: check_array.join(",")}, {ids: check_array.join(",")},
function(data){ function(data){
$(".gradeX input:checked").closest("tr").remove();
window.open("/juser/user_list/", "_self"); window.open("/juser/user_list/", "_self");
} }
) )
} }
});
$('.email').click(function(){
$.get('/juser/send_mail_retry/?uuid=' + $(this).attr('value'),
{},
function(data){
alert(data)
}
)
}) })
}); });
</script> </script>
{% endblock %}
{% endblock %}

View File

@ -31,7 +31,7 @@
</div> </div>
<button type="submit" class="btn btn-primary block full-width m-b">Login</button> <button type="submit" class="btn btn-primary block full-width m-b">Login</button>
<a href="#"><small>Forgot password? Contact Administrator. </small></a> <a href="/juser/forget_password/"><small>Forgot password? </small></a>
</form> </form>
<p class="m-t"> <small><b>Copyright</b> Jumpserver.org Organization © 2014-2015</small> </p> <p class="m-t"> <small><b>Copyright</b> Jumpserver.org Organization © 2014-2015</small> </p>
</div> </div>