mirror of https://github.com/jumpserver/jumpserver
user-profile page
parent
31bded8953
commit
f3647ea46d
|
@ -225,6 +225,7 @@ table.dataTable tbody td.selected td i.text-navy
|
||||||
background: #f1f1f1;
|
background: #f1f1f1;
|
||||||
margin-right: 2px;
|
margin-right: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.form-asset-on{
|
.form-asset-on{
|
||||||
border: 1px solid #e5e6e7;
|
border: 1px solid #e5e6e7;
|
||||||
padding-top:5px;
|
padding-top:5px;
|
||||||
|
@ -263,4 +264,16 @@ div.dataTables_wrapper div.dataTables_filter,
|
||||||
|
|
||||||
div.dataTables_wrapper div.dataTables_filter {
|
div.dataTables_wrapper div.dataTables_filter {
|
||||||
margin-left: 15px;
|
margin-left: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.simple-tag {
|
||||||
|
background-color: #f3f3f4;
|
||||||
|
border: 1px solid #e7eaec;
|
||||||
|
border-radius: 2px;
|
||||||
|
color: inherit;
|
||||||
|
display: inline-block;
|
||||||
|
font-size: 10px;
|
||||||
|
margin-right: 5px;
|
||||||
|
margin-top: 5px;
|
||||||
|
padding: 5px 12px;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,114 @@
|
||||||
|
{% extends 'base.html' %}
|
||||||
|
{% load common_tags %}
|
||||||
|
{% load users_tags %}
|
||||||
|
{% load static %}
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
{% block custom_head_css_js %}
|
||||||
|
<link href="{% static "css/plugins/sweetalert/sweetalert.css" %}" rel="stylesheet">
|
||||||
|
<script src="{% static "js/plugins/sweetalert/sweetalert.min.js" %}"></script>
|
||||||
|
{% endblock %}
|
||||||
|
{% block content %}
|
||||||
|
<div class="wrapper wrapper-content animated fadeInRight">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-4">
|
||||||
|
<div class="ibox float-e-margins">
|
||||||
|
<div class="ibox-title">
|
||||||
|
<span class="label label-primary"><b>{{ user.name }}</b></span>
|
||||||
|
<div class="ibox-tools">
|
||||||
|
<a class="collapse-link">
|
||||||
|
<i class="fa fa-chevron-up"></i>
|
||||||
|
</a>
|
||||||
|
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
|
||||||
|
<i class="fa fa-wrench"></i>
|
||||||
|
</a>
|
||||||
|
<ul class="dropdown-menu dropdown-user">
|
||||||
|
<li><a href="#"></a>
|
||||||
|
</li>
|
||||||
|
<li><a href="#"></a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<a class="close-link">
|
||||||
|
<i class="fa fa-times"></i>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="ibox-content">
|
||||||
|
<div>
|
||||||
|
<div class="text-left">
|
||||||
|
<table class="table">
|
||||||
|
<tr>
|
||||||
|
<td class="text-navy">用户名</td>
|
||||||
|
<td>{{ user.username }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="text-navy">姓名</td>
|
||||||
|
<td>{{ user.name }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="text-navy">权限</td>
|
||||||
|
<td>{{ user.get_role_display }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="text-navy">Email</td>
|
||||||
|
<td>{{ user.email }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="text-navy">激活</td>
|
||||||
|
<td>{{ user.is_active }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="text-navy">添加日期</td>
|
||||||
|
<td>{{ user.date_joined|date:"Y-m-d H:i:s" }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="text-navy">最后登录</td>
|
||||||
|
<td>{{ user.last_login|date:"Y-m-d H:i:s" }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="text-navy">所在用户组</td>
|
||||||
|
<td>
|
||||||
|
{% for group in user.groups.all %}
|
||||||
|
<span class="simple-tag with-link">
|
||||||
|
<a href="{% url 'users:user-group-detail' group.id %}">{{ group.name }}</a>
|
||||||
|
</span>
|
||||||
|
{% endfor %}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="text-navy">授权主机数量</td>
|
||||||
|
<td>{{ assets | length }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="text-navy">授权主机组</td>
|
||||||
|
<td>
|
||||||
|
{% for group in asset_groups %}
|
||||||
|
<span class="simple-tag with-link">
|
||||||
|
<a href="#">{{ group.name }}</a>
|
||||||
|
</span>
|
||||||
|
{% endfor %}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="text-navy">授权规则</td>
|
||||||
|
<td>
|
||||||
|
{% for perm in permissions %}
|
||||||
|
<span class="simple-tag with-link">
|
||||||
|
<a href="#">{{ perm.name }}</a>
|
||||||
|
</span>
|
||||||
|
{% endfor %}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-4"></div>
|
||||||
|
<div class="col-sm-4"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
|
{% block custom_foot_js %}
|
||||||
|
{% endblock %}
|
|
@ -1,6 +1,7 @@
|
||||||
from __future__ import absolute_import
|
from __future__ import absolute_import
|
||||||
|
|
||||||
from django.conf.urls import url
|
from django.conf.urls import url
|
||||||
|
|
||||||
from .. import views
|
from .. import views
|
||||||
|
|
||||||
app_name = 'users'
|
app_name = 'users'
|
||||||
|
@ -20,6 +21,11 @@ urlpatterns = [
|
||||||
views.UserResetPasswordSuccessView.as_view(),
|
views.UserResetPasswordSuccessView.as_view(),
|
||||||
name='reset-password-success'),
|
name='reset-password-success'),
|
||||||
|
|
||||||
|
# Profile
|
||||||
|
url(r'^profile/$',
|
||||||
|
views.UserProfileView.as_view(),
|
||||||
|
name='user-profile'),
|
||||||
|
|
||||||
# User view
|
# User view
|
||||||
url(r'^user$', views.UserListView.as_view(), name='user-list'),
|
url(r'^user$', views.UserListView.as_view(), name='user-list'),
|
||||||
url(r'^user/(?P<pk>[0-9]+)$', views.UserDetailView.as_view(),
|
url(r'^user/(?P<pk>[0-9]+)$', views.UserDetailView.as_view(),
|
||||||
|
|
|
@ -1,17 +1,19 @@
|
||||||
# ~*~ coding: utf-8 ~*~
|
# ~*~ coding: utf-8 ~*~
|
||||||
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
import uuid
|
|
||||||
import json
|
|
||||||
|
|
||||||
from django.shortcuts import redirect
|
import json
|
||||||
|
import uuid
|
||||||
|
|
||||||
|
from openpyxl import load_workbook
|
||||||
from openpyxl import Workbook
|
from openpyxl import Workbook
|
||||||
from openpyxl.writer.excel import save_virtual_workbook
|
from openpyxl.writer.excel import save_virtual_workbook
|
||||||
from openpyxl import load_workbook
|
|
||||||
from django import forms
|
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||||
|
from django.contrib.messages.views import SuccessMessageMixin
|
||||||
from django.core.cache import cache
|
from django.core.cache import cache
|
||||||
from django.http import HttpResponse, JsonResponse
|
from django.http import HttpResponse, JsonResponse
|
||||||
from django.contrib.messages.views import SuccessMessageMixin
|
from django.shortcuts import redirect
|
||||||
from django.urls import reverse_lazy, reverse
|
from django.urls import reverse_lazy, reverse
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.utils.translation import ugettext as _
|
from django.utils.translation import ugettext as _
|
||||||
|
@ -19,22 +21,23 @@ from django.utils.decorators import method_decorator
|
||||||
from django.views import View
|
from django.views import View
|
||||||
from django.views.generic import ListView
|
from django.views.generic import ListView
|
||||||
from django.views.generic.base import TemplateView
|
from django.views.generic.base import TemplateView
|
||||||
from django.views.generic.edit import CreateView, UpdateView, FormMixin, \
|
from django.views.generic.edit import (CreateView, UpdateView, FormMixin,
|
||||||
FormView
|
FormView)
|
||||||
from django.views.generic.detail import DetailView, SingleObjectMixin
|
from django.views.generic.detail import DetailView, SingleObjectMixin
|
||||||
from django.views.decorators.csrf import csrf_exempt
|
from django.views.decorators.csrf import csrf_exempt
|
||||||
|
|
||||||
|
from .. import forms
|
||||||
|
from ..models import User, UserGroup
|
||||||
|
from ..utils import AdminUserRequiredMixin, user_add_success_next
|
||||||
from common.mixins import JSONResponseMixin
|
from common.mixins import JSONResponseMixin
|
||||||
from common.utils import get_logger
|
from common.utils import get_logger
|
||||||
from perms.models import AssetPermission
|
from perms.models import AssetPermission
|
||||||
from ..models import User, UserGroup
|
|
||||||
from ..utils import AdminUserRequiredMixin, user_add_success_next
|
|
||||||
from .. import forms
|
|
||||||
|
|
||||||
__all__ = ['UserListView', 'UserCreateView', 'UserDetailView',
|
__all__ = ['UserListView', 'UserCreateView', 'UserDetailView',
|
||||||
'UserUpdateView', 'UserAssetPermissionCreateView',
|
'UserUpdateView', 'UserAssetPermissionCreateView',
|
||||||
'UserAssetPermissionView', 'UserGrantedAssetView',
|
'UserAssetPermissionView', 'UserGrantedAssetView',
|
||||||
'UserExportView', 'UserBulkImportView']
|
'UserExportView', 'UserBulkImportView', 'UserProfileView']
|
||||||
|
|
||||||
logger = get_logger(__name__)
|
logger = get_logger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
@ -118,6 +121,7 @@ class UserDetailView(AdminUserRequiredMixin, DetailView):
|
||||||
|
|
||||||
@method_decorator(csrf_exempt, name='dispatch')
|
@method_decorator(csrf_exempt, name='dispatch')
|
||||||
class UserExportView(View):
|
class UserExportView(View):
|
||||||
|
|
||||||
def get(self, request, *args, **kwargs):
|
def get(self, request, *args, **kwargs):
|
||||||
spm = request.GET.get('spm', '')
|
spm = request.GET.get('spm', '')
|
||||||
users_id = cache.get(spm)
|
users_id = cache.get(spm)
|
||||||
|
@ -135,13 +139,14 @@ class UserExportView(View):
|
||||||
for user in users:
|
for user in users:
|
||||||
ws.append([user.name, user.username, user.email,
|
ws.append([user.name, user.username, user.email,
|
||||||
','.join([group.name for group in user.groups.all()]),
|
','.join([group.name for group in user.groups.all()]),
|
||||||
user.role, user.phone, user.wechat, user.comment])
|
user.role, user.phone, user.wechat, user.comment])
|
||||||
|
|
||||||
filename = 'users-{}.xlsx'.format(
|
filename = 'users-{}.xlsx'.format(
|
||||||
timezone.localtime(timezone.now()).strftime('%Y-%m-%d_%H-%M-%S'))
|
timezone.localtime(timezone.now()).strftime('%Y-%m-%d_%H-%M-%S'))
|
||||||
response = HttpResponse(save_virtual_workbook(wb),
|
response = HttpResponse(save_virtual_workbook(wb),
|
||||||
content_type='applications/vnd.ms-excel')
|
content_type='applications/vnd.ms-excel')
|
||||||
response['Content-Disposition'] = 'attachment; filename="%s"' % filename
|
response[
|
||||||
|
'Content-Disposition'] = 'attachment; filename="%s"' % filename
|
||||||
return response
|
return response
|
||||||
|
|
||||||
def post(self, request, *args, **kwargs):
|
def post(self, request, *args, **kwargs):
|
||||||
|
@ -180,11 +185,13 @@ class UserBulkImportView(AdminUserRequiredMixin, JSONResponseMixin, FormView):
|
||||||
return self.render_json_response(data)
|
return self.render_json_response(data)
|
||||||
|
|
||||||
rows = ws.rows
|
rows = ws.rows
|
||||||
header_need = ["name", 'username', 'email', 'groups', "role", "phone", "wechat", "comment"]
|
header_need = ["name", 'username', 'email',
|
||||||
|
'groups', "role", "phone", "wechat", "comment"]
|
||||||
header = [col.value for col in next(rows)]
|
header = [col.value for col in next(rows)]
|
||||||
print(header)
|
print(header)
|
||||||
if header != header_need:
|
if header != header_need:
|
||||||
data = {'valid': False, 'msg': 'Must be same format as template or export file'}
|
data = {
|
||||||
|
'valid': False, 'msg': 'Must be same format as template or export file'}
|
||||||
return self.render_json_response(data)
|
return self.render_json_response(data)
|
||||||
|
|
||||||
created = []
|
created = []
|
||||||
|
@ -297,4 +304,28 @@ class UserGrantedAssetView(AdminUserRequiredMixin, DetailView):
|
||||||
'action': 'User granted asset',
|
'action': 'User granted asset',
|
||||||
}
|
}
|
||||||
kwargs.update(context)
|
kwargs.update(context)
|
||||||
return super(UserGrantedAssetView, self).get_context_data(**kwargs)
|
return super(UserGrantedAssetView, self).get_context_data(**kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
class UserProfileView(LoginRequiredMixin, TemplateView):
|
||||||
|
template_name = 'users/user_profile.html'
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
from perms.utils import (get_user_granted_assets,
|
||||||
|
get_user_granted_asset_groups,
|
||||||
|
get_user_asset_permissions)
|
||||||
|
assets = get_user_granted_assets(self.request.user)
|
||||||
|
asset_groups = get_user_granted_asset_groups(self.request.user)
|
||||||
|
permissions = get_user_asset_permissions(self.request.user)
|
||||||
|
context = {
|
||||||
|
'app': 'User',
|
||||||
|
'action': 'User Profile',
|
||||||
|
'assets': assets,
|
||||||
|
'asset_groups': asset_groups,
|
||||||
|
'permissions': permissions
|
||||||
|
}
|
||||||
|
print assets
|
||||||
|
print asset_groups
|
||||||
|
print permissions
|
||||||
|
kwargs.update(context)
|
||||||
|
return super(UserProfileView, self).get_context_data(**kwargs)
|
||||||
|
|
Loading…
Reference in New Issue