diff --git a/jasset/views.py b/jasset/views.py index b1c92a4a0..37d4864e7 100644 --- a/jasset/views.py +++ b/jasset/views.py @@ -7,9 +7,7 @@ from django.template import RequestContext from django.shortcuts import render_to_response from jasset.models import IDC, Asset, BisGroup, AssetAlias -from juser.models import UserGroup, DEPT from jperm.models import Perm, SudoPerm -from jumpserver.views import pages from jumpserver.api import * cryptor = PyCrypt(KEY) diff --git a/jumpserver/api.py b/jumpserver/api.py index 671d6112f..83be10278 100644 --- a/jumpserver/api.py +++ b/jumpserver/api.py @@ -10,6 +10,7 @@ from binascii import b2a_hex, a2b_hex import ldap from ldap import modlist import hashlib +import datetime from django.core.paginator import Paginator, EmptyPage, InvalidPage from django.http import HttpResponse, Http404 from juser.models import User, UserGroup, DEPT @@ -289,6 +290,7 @@ def user_perm_asset_api(username): asset_list.extend(asset_group.asset_set.all()) return asset_list + return [] def asset_perm_api(asset): @@ -359,4 +361,4 @@ def validate(request, user_group=None, user=None, asset_group=None, asset=None, def get_dept_asset(request): dept_id = get_user_dept(request) - dept_asset = DEPT.objects.get(id=dept_id).asset_set.all() \ No newline at end of file + dept_asset = DEPT.objects.get(id=dept_id).asset_set.all() diff --git a/jumpserver/context_processors.py b/jumpserver/context_processors.py index 6fdd4d07f..baa3f091b 100644 --- a/jumpserver/context_processors.py +++ b/jumpserver/context_processors.py @@ -2,6 +2,7 @@ from juser.models import User from jasset.models import Asset from jumpserver.api import * + def name_proc(request): user_id = request.session.get('user_id') role_id = request.session.get('role_id') diff --git a/jumpserver/templatetags/mytags.py b/jumpserver/templatetags/mytags.py index 159bbd5e3..5cf0d50ae 100644 --- a/jumpserver/templatetags/mytags.py +++ b/jumpserver/templatetags/mytags.py @@ -57,7 +57,7 @@ def groups_str2(group_list): @register.filter(name='group_str2_all') -def groups_str2(group_list): +def group_str2_all(group_list): group_lis = [] for i in group_list: if str(i) != 'ALL': @@ -107,6 +107,12 @@ def member_count(group_id): return group.user_set.count() +@register.filter(name='group_user_count') +def group_user_count(group_id): + group = UserGroup.objects.get(id=group_id) + return group.user_set.count() + + @register.filter(name='dept_user_num') def dept_user_num(dept_id): dept = DEPT.objects.filter(id=dept_id) @@ -230,3 +236,31 @@ def to_avatar(role_id='0'): @register.filter(name='get_user_asset_group') def get_user_asset_group(user): return user_perm_group_api(user) + + +@register.filter(name='group_asset_list') +def group_asset_list(group): + return group.asset_set.all() + + +@register.filter(name='group_asset_list_count') +def group_asset_list_count(group): + return group.asset_set.all().count() + + +@register.filter(name='time_delta') +def time_delta(time_before): + delta = datetime.datetime.now() - time_before + days = delta.days + if days: + return "%s 天前" % days + else: + hours = delta.seconds/3600 + if hours: + return "%s 小时前" % hours + else: + mins = delta.seconds/60 + if mins: + return '%s 分钟前' % mins + else: + return '%s 秒前' % delta.seconds diff --git a/jumpserver/urls.py b/jumpserver/urls.py index e20762448..57d9a1b59 100644 --- a/jumpserver/urls.py +++ b/jumpserver/urls.py @@ -15,9 +15,12 @@ urlpatterns = patterns('', (r'^base/$', 'jumpserver.views.base'), (r'^login/$', 'jumpserver.views.login'), (r'^logout/$', 'jumpserver.views.logout'), + (r'^upload/$', 'jumpserver.views.upload'), + (r'^download/$', 'jumpserver.views.download'), (r'^juser/', include('juser.urls')), (r'^jasset/', include('jasset.urls')), (r'^jlog/', include('jlog.urls')), (r'^jperm/', include('jperm.urls')), + ) diff --git a/jumpserver/views.py b/jumpserver/views.py index c2c46aafc..a317db473 100644 --- a/jumpserver/views.py +++ b/jumpserver/views.py @@ -45,78 +45,37 @@ def get_data(data, items, option): return dic -@require_login -def index(request): - users = User.objects.all() - hosts = Asset.objects.all() - online = Log.objects.filter(is_finished=0) - online_host = online.values('host').distinct() - online_user = online.values('user').distinct() - active_users = User.objects.filter(is_active=1) - active_hosts = Asset.objects.filter(is_active=1) - - # percent of dashboard - percent_user = format(active_users.count() / users.count(), '.0%') - percent_host = format(active_hosts.count() / hosts.count(), '.0%') - percent_online_user = format(online_user.count() / users.count(), '.0%') - percent_online_host = format(online_host.count() / hosts.count(), '.0%') - - li_date, li_str = getDaysByNum(7) - today = datetime.datetime.now().day - from_week = datetime.datetime.now() - datetime.timedelta(days=7) - week_data = Log.objects.filter(start_time__range=[from_week, datetime.datetime.now()]) - user_top_ten = week_data.values('user').annotate(times=Count('user')).order_by('-times')[:10] - host_top_ten = week_data.values('host').annotate(times=Count('host')).order_by('-times')[:10] - user_dic, host_dic = get_data(week_data, user_top_ten, 'user'), get_data(week_data, host_top_ten, 'host') - - # a week data - week_users = week_data.values('user').distinct().count() - week_hosts = week_data.count() - - user_top_five = week_data.values('user').annotate(times=Count('user')).order_by('-times')[:5] - color = ['label-success', 'label-info', 'label-primary', 'label-default', 'label-warnning'] - - # perm apply latest 10 - perm_apply_10 = Apply.objects.order_by('-date_add')[:10] - - # latest 10 login - login_10 = Log.objects.order_by('-start_time')[:10] - - # a week top 10 - for user_info in user_top_ten: - username = user_info.get('user') - last = Log.objects.filter(user=username).latest('start_time') - user_info['last'] = last - print user_top_ten - - top = {'user': '活跃用户数', 'host': '活跃主机数', 'times': '登录次数'} - top_dic = {} - for key, value in top.items(): - li = [] - for t in li_date: - year, month, day = t.year, t.month, t.day - if key != 'times': - times = week_data.filter(start_time__year=year, start_time__month=month, start_time__day=day).values(key).distinct().count() - else: - times = week_data.filter(start_time__year=year, start_time__month=month, start_time__day=day).count() - li.append(times) - top_dic[value] = li - return render_to_response('index.html', locals(), context_instance=RequestContext(request)) - - @require_admin -def admin_index(request): - user_id = request.session.get('user_id', '') - user = User.objects.get(id=user_id) - dept = user.dept - dept_name = user.dept.name - users = User.objects.filter(dept=dept) - hosts = Asset.objects.filter(dept=dept) - online = Log.objects.filter(dept_name=dept_name, is_finished=0) - online_host = online.values('host').distinct() - online_user = online.values('user').distinct() - active_users = users.filter(is_active=1) - active_hosts = hosts.filter(is_active=1) +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_super_user(request): + users = User.objects.all() + hosts = Asset.objects.all() + online = Log.objects.filter(is_finished=0) + online_host = online.values('host').distinct() + online_user = online.values('user').distinct() + active_users = User.objects.filter(is_active=1) + 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): + user_id = request.session.get('user_id', '') + user = User.objects.get(id=user_id) + dept = user.dept + dept_name = user.dept.name + users = User.objects.filter(dept=dept) + hosts = Asset.objects.filter(dept=dept) + online = Log.objects.filter(dept_name=dept_name, is_finished=0) + online_host = online.values('host').distinct() + online_user = online.values('user').distinct() + active_users = users.filter(is_active=1) + active_hosts = hosts.filter(is_active=1) + week_data = Log.objects.filter(dept_name=dept_name, start_time__range=[from_week, datetime.datetime.now()]) + + user_top_ten = week_data.values('user').annotate(times=Count('user')).order_by('-times')[:10] + host_top_ten = week_data.values('host').annotate(times=Count('host')).order_by('-times')[:10] + user_dic, host_dic = get_data(week_data, user_top_ten, 'user'), get_data(week_data, host_top_ten, 'host') # percent of dashboard percent_user = format(active_users.count() / users.count(), '.0%') @@ -124,14 +83,6 @@ def admin_index(request): percent_online_user = format(online_user.count() / users.count(), '.0%') percent_online_host = format(online_host.count() / hosts.count(), '.0%') - li_date, li_str = getDaysByNum(7) - today = datetime.datetime.now().day - from_week = datetime.datetime.now() - datetime.timedelta(days=7) - week_data = Log.objects.filter(dept_name=dept_name, start_time__range=[from_week, datetime.datetime.now()]) - user_top_ten = week_data.values('user').annotate(times=Count('user')).order_by('-times')[:10] - host_top_ten = week_data.values('host').annotate(times=Count('host')).order_by('-times')[:10] - user_dic, host_dic = get_data(week_data, user_top_ten, 'user'), get_data(week_data, host_top_ten, 'host') - # a week data week_users = week_data.values('user').distinct().count() week_hosts = week_data.count() diff --git a/juser/urls.py b/juser/urls.py index 71bc09ee7..cbaba7bb0 100644 --- a/juser/urls.py +++ b/juser/urls.py @@ -29,4 +29,5 @@ urlpatterns = patterns('juser.views', (r'^profile/$', 'profile'), (r'^chg_info/$', 'chg_info'), (r'^chg_role/$', 'chg_role'), + (r'^down_key/$', 'down_key'), ) diff --git a/juser/views.py b/juser/views.py index eb0a361ec..a4f39076a 100644 --- a/juser/views.py +++ b/juser/views.py @@ -6,7 +6,6 @@ import random import subprocess from Crypto.PublicKey import RSA import crypt -import datetime from django.shortcuts import render_to_response from django.core.exceptions import ObjectDoesNotExist @@ -32,9 +31,10 @@ def bash(cmd): return subprocess.call(cmd, shell=True) -def is_dir(dir_name, mode=0755): +def is_dir(dir_name, username='root', mode=0755): if not os.path.isdir(dir_name): os.makedirs(dir_name) + bash("chown %s:%s '%s'" % (username, username, dir_name)) os.chmod(dir_name, mode) @@ -109,11 +109,11 @@ def db_del_user(username): 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) + 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, mode=0700) + is_dir(public_key_dir, username, mode=0700) key = RSA.generate(length) with open(private_key_file, 'w') as pri_f: @@ -128,7 +128,7 @@ def gen_ssh_key(username, password=None, length=2048): def server_add_user(username, password, ssh_key_pwd): - bash('useradd %s; echo %s | passwd --stdin %s' % (username, password, username)) + bash("useradd '%s'; echo '%s' | passwd --stdin '%s'" % (username, password, username)) gen_ssh_key(username, ssh_key_pwd) @@ -775,18 +775,26 @@ def user_list_adm(request): return render_to_response('juser/user_list.html', locals(), context_instance=RequestContext(request)) -@require_admin +@require_login def user_detail(request): - user_id = request.GET.get('id', '') + header_title, path1, path2 = '查看用户', '用户管理', '用户详情' + if request.session.get('role_id') == 0: + user_id = request.session.get('user_id') + else: + user_id = request.GET.get('id', '') + if request.session.get('role_id') == 1: + user, dept = get_session_user_dept(request) + if not validate(request, user=[user_id]): + return HttpResponseRedirect('/') if not user_id: return HttpResponseRedirect('/juser/user_list/') - if request.session.get('role_id', '') == '1': - if not validate(request, user=[user_id]): - return HttpResponseRedirect('/juser/user_list/') + user = User.objects.filter(id=user_id) if user: user = user[0] asset_group_permed = user_perm_group_api(user) + 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') return render_to_response('juser/user_detail.html', locals(), context_instance=RequestContext(request)) @@ -875,6 +883,7 @@ def user_edit(request): password = md5_crypt(password) if ssh_key_pwd != user.ssh_key_pwd: + gen_ssh_key(user.username, ssh_key_pwd) ssh_key_pwd = CRYPTOR.encrypt(ssh_key_pwd) db_update_user(user_id=user_id, @@ -953,11 +962,11 @@ def profile(request): if not user_id: return HttpResponseRedirect('/') user = User.objects.get(id=user_id) - return render_to_response('juser/user_detail.html', locals(), context_instance=RequestContext(request)) + return render_to_response('juser/profile.html', locals(), context_instance=RequestContext(request)) def chg_info(request): - header_title, path1, path2 = '修改信息 | Edit Info', '用户管理', '修改个人信息' + header_title, path1, path2 = '修改信息', '用户管理', '修改个人信息' user_id = request.session.get('user_id') user_set = User.objects.filter(id=user_id) error = '' @@ -983,9 +992,42 @@ def chg_info(request): password = md5_crypt(password) if ssh_key_pwd != user.ssh_key_pwd: + gen_ssh_key(user.username, ssh_key_pwd) ssh_key_pwd = md5_crypt(ssh_key_pwd) + user_set.update(name=name, password=password, ssh_key_pwd=ssh_key_pwd, email=email) msg = '修改成功' return render_to_response('juser/chg_info.html', locals(), context_instance=RequestContext(request)) + +@require_login +def down_key(request): + user_id = '' + if is_super_user(request): + user_id = request.GET.get('id') + + if is_group_admin(request): + 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): + user_id = request.session.get('user_id') + + if user_id: + user = User.objects.filter(id=user_id) + if user: + user = user[0] + username = user.username + private_key_dir = os.path.join(BASE_DIR, 'keys/jumpserver/') + private_key_file = os.path.join(private_key_dir, username+".pem") + if os.path.isfile(private_key_file): + f = open(private_key_file) + data = f.read() + f.close() + response = HttpResponse(data, content_type='application/octet-stream') + response['Content-Disposition'] = 'attachment; filename=%s' % os.path.basename(private_key_file) + return response + + return HttpResponse('No Key File. Contact Admin.') \ No newline at end of file diff --git a/templates/index_cu.html b/templates/index_cu.html new file mode 100644 index 000000000..116613fab --- /dev/null +++ b/templates/index_cu.html @@ -0,0 +1,162 @@ +{% extends 'base.html' %} +{% load mytags %} +{% block content %} +{% include 'nav_cat_bar.html' %} + +
+
+
+
+
+
使用说明
+ +
+ +
+ 迎使用Jumpserver跳板机系统, + 首先需要 下载 登录跳板机的SSH密钥文件,然后导入到工具或者ssh命令指定密钥文件(确保密钥文件权限600),输入收到的密钥密码,登录跳板机。 + 登录后根据提示进行操作。跳板机web界面支持修改密码、个人信息和上传下载文件等功能,可以向管理员申请权限。 +
+
+ +
+
+
已授权主机
+
+
总共:{{ host_count }}
+ + + + + + + + + + +
+
+ +
+ + {% for host_five in new_posts %} + + {% for host in host_five %} + + {% endfor %} + + {% endfor %} +
{{ host.ip }}
+ {% ifequal host_count 0 %} + (空) + {% endifequal %} +
+
+
+ +
+
+
+ {{ user.name }} +
+ + + + + + + + + + +
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ID{{ user.id }}
用户名{{ user.username }}
姓名{{ user.name }}
角色{{ user.id | get_role }}
部门{{ user.dept.name }}
Email{{ user.email }}
激活{{ user.is_active|bool2str }}
添加日期{{ user.date_joined|date:"Y-m-d H:i:s" }}
最后登录{{ user.last_login|date:"Y-m-d H:i:s" }}
所在用户组 + + {% for group in user.group.all %} + + + + {% endfor %} +
{{ group.name }}
+
+
+
+
+
+
+
+
+ + +{% endblock %} \ No newline at end of file diff --git a/templates/jperm/perm_detail.html b/templates/jperm/perm_detail.html index dac9b254d..039151aad 100644 --- a/templates/jperm/perm_detail.html +++ b/templates/jperm/perm_detail.html @@ -8,7 +8,7 @@
-
授权用户 User.
+
用户详情
diff --git a/templates/juser/profile.html b/templates/juser/profile.html new file mode 100644 index 000000000..7be33cce4 --- /dev/null +++ b/templates/juser/profile.html @@ -0,0 +1,82 @@ +{% load mytags %} + + + {% include 'link_css.html' %} + + + + + +
+
+

{{ user.name }} 用户详情

+
+ + + + + + + + + + + +{# #} +{# #} + + + + + + + + + + + + +{# #} +{# #} + + + + + + + + + + + +{# #} +{# #} +{# #} +{# #} +{# #} +{# #} +{# #} +{# #} +{# #} +
ID用户名姓名角色部门Email激活添加时间最后登录
{{ user.id }}{{ user.username }}{{ user.name }}{{ user.id | get_role }}{{ user.dept.name }}{{ user.email }}{{ user.is_active|bool2str }}{{ user.date_joined }}{{ user.last_login }}
添加日期: {{ user.date_joined }}最后登录: {{ user.last_login }}
用户组: + {% for group in user.group.all %} + {{ group.name }} + {% endfor %} +
授权主机组:#} +{# {% for group in user|get_user_asset_group %}#} +{# {{ group.name }}#} +{# {% endfor %}#} +{#
授权主机组#} +{# {% for asset_group in asset_group_permed %}#} +{# {{ asset_group.name }}#} +{# {% endfor %}#} +{#
+
+
+ + \ No newline at end of file diff --git a/templates/juser/user_detail.html b/templates/juser/user_detail.html index 119aa028d..811076921 100644 --- a/templates/juser/user_detail.html +++ b/templates/juser/user_detail.html @@ -1,82 +1,218 @@ +{% extends 'base.html' %} {% load mytags %} - - - {% include 'link_css.html' %} - - - +{% block content %} + {% include 'nav_cat_bar.html' %} +
-
-

{{ user.name }} 用户详情

-
- - \ No newline at end of file +
+
+
+
授权主机/组
+ +
+
+

用户的所有授权主机

+ 这里包含了用户所有的主机组和组下的主机. +
+
+ {% for group in user|get_user_asset_group %} +
+
+
+ + {{ group.name }} +
+ 共: {{ group | group_asset_list_count }}台 +
+
+

{{ group.comment }}

+ +

+ {% for asset in group|group_asset_list %} + {{ asset.ip }}
+ {% endfor %} +

+

+ +
+
+
+ {% endfor %} + {% if not user|get_user_asset_group %} + (无) + {% endif %} +
+
+
+ +
+
+
+
登录记录
+
+ 最近登录 +
+
+
+ +
+
+ {% for log in logs_last %} +
+ + image + +
+ {{ log.start_time|time_delta }} + {{ log.user }} 登录了 {{ log.host }}.
+ {{ log.start_time|date:"Y-m-d H:i:s" }} +
+
+ {% endfor %} + {% if not logs_last %} + (无) + {% endif %} +
+ + + +
+ + + +
+
+ +
+ +
+
+ + + + +{% endblock %} \ No newline at end of file diff --git a/templates/juser/user_edit.html b/templates/juser/user_edit.html index ee30e9c36..c8ad656a3 100644 --- a/templates/juser/user_edit.html +++ b/templates/juser/user_edit.html @@ -59,7 +59,7 @@
- 登陆 Jumpserver 使用的SSH密钥的密码 + 登陆 Jumpserver 使用的SSH密钥的密码,更改密钥密码需要重新下载密钥
diff --git a/templates/juser/user_list.html b/templates/juser/user_list.html index d6b362f00..bd2a81bea 100644 --- a/templates/juser/user_list.html +++ b/templates/juser/user_list.html @@ -56,6 +56,7 @@ 小组 角色 激活 + 下载密钥 操作 @@ -71,8 +72,9 @@ {{ user.group.all | group_str2 }} {{ user.id | get_role }} {{ user.is_active|bool2str }} + 下载 - 详情 + 详情 {% ifequal session_role_id 2 %} 编辑 删除 diff --git a/templates/nav.html b/templates/nav.html index 5178586cb..e132c5b35 100644 --- a/templates/nav.html +++ b/templates/nav.html @@ -19,7 +19,7 @@
  • 添加部门
  • 查看小组
  • 添加小组
  • -
  • 查看用户{{ user_active_num }}/{{ user_total_num }}
  • +
  • 查看用户{{ user_active_num }}/{{ user_total_num }}
  • 添加用户
  • @@ -136,8 +136,8 @@
  • 仪表盘
  • -
  • - 个人信息 +
  • + 个人信息
  • 查看主机 @@ -156,13 +156,10 @@
  • 上传下载
  • -
  • - 使用说明 -