Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
J
jumpserver
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
ops
jumpserver
Commits
8d7759d2
Commit
8d7759d2
authored
Nov 09, 2016
by
ibuler
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
change user api
parent
ea3f8af1
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
231 additions
and
223 deletions
+231
-223
models.py
apps/assets/models.py
+1
-2
asset_create.html
apps/assets/templates/assets/asset_create.html
+3
-6
views.py
apps/assets/views.py
+3
-2
django.po
apps/locale/zh/LC_MESSAGES/django.po
+1
-1
jumpserver.js
apps/static/js/jumpserver.js
+3
-3
_base_create_update.html
apps/templates/_base_create_update.html
+8
-1
api.py
apps/users/api.py
+72
-73
models.py
apps/users/models.py
+1
-0
serializers.py
apps/users/serializers.py
+65
-40
_user.html
apps/users/templates/users/_user.html
+44
-74
user_detail.html
apps/users/templates/users/user_detail.html
+0
-0
user_list.html
apps/users/templates/users/user_list.html
+4
-4
urls.py
apps/users/urls.py
+21
-12
utils.py
apps/users/utils.py
+1
-1
views.py
apps/users/views.py
+4
-4
No files found.
apps/assets/models.py
View file @
8d7759d2
...
...
@@ -315,9 +315,8 @@ class Asset(models.Model):
admin_user
=
models
.
ForeignKey
(
AdminUser
,
null
=
True
,
blank
=
True
,
related_name
=
'assets'
,
on_delete
=
models
.
SET_NULL
,
verbose_name
=
_
(
"Admin user"
))
system_users
=
models
.
ManyToManyField
(
SystemUser
,
blank
=
True
,
related_name
=
'assets'
,
verbose_name
=
_
(
"System User"
))
idc
=
models
.
ForeignKey
(
IDC
,
null
=
True
,
related_name
=
'assets'
,
idc
=
models
.
ForeignKey
(
IDC
,
blank
=
True
,
null
=
True
,
related_name
=
'assets'
,
on_delete
=
models
.
SET_NULL
,
verbose_name
=
_
(
'IDC'
),)
# default=get_default_idc)
mac_address
=
models
.
CharField
(
max_length
=
20
,
null
=
True
,
blank
=
True
,
verbose_name
=
_
(
"Mac address"
))
brand
=
models
.
CharField
(
max_length
=
64
,
null
=
True
,
blank
=
True
,
verbose_name
=
_
(
'Brand'
))
cpu
=
models
.
CharField
(
max_length
=
64
,
null
=
True
,
blank
=
True
,
verbose_name
=
_
(
'CPU'
))
...
...
apps/assets/templates/assets/asset_create.html
View file @
8d7759d2
...
...
@@ -30,12 +30,11 @@
<div
class=
"hr-line-dashed"
></div>
<div
class=
"form-group"
>
<div
class=
"col-sm-4 col-sm-offset-2"
>
<button
class=
"btn btn-
white"
type=
"reset"
>
{% trans 'Reset' %}
</button>
<button
class=
"btn btn-
default"
type=
"reset"
>
{% trans 'Reset' %}
</button>
<button
id=
"submit_button"
class=
"btn btn-primary"
type=
"submit"
>
{% trans 'Submit' %}
</button>
</div>
</div>
</form>
</form>
{% endblock %}
{% block custom_foot_js %}
...
...
@@ -44,10 +43,9 @@
$
(
'.select2'
).
select2
();
$
(
"#id_tags"
).
select2
({
tags
:
true
,
maximumSelectionLength
:
8
,
//最多能够选择的个数
maximumSelectionLength
:
8
//最多能够选择的个数
//closeOnSelect: false
});
})
</script>
{% endblock %}
\ No newline at end of file
apps/assets/views.py
View file @
8d7759d2
...
...
@@ -44,7 +44,7 @@ class AssetListView(AdminUserRequiredMixin, ListView):
return
super
(
AssetListView
,
self
)
.
get_context_data
(
**
kwargs
)
class
AssetCreateView
(
AdminUserRequiredMixin
,
CreateAssetTagsMiXin
,
CreateView
):
class
AssetCreateView
(
AdminUserRequiredMixin
,
CreateAssetTagsMiXin
,
CreateView
):
model
=
Asset
tag_type
=
'asset'
form_class
=
AssetCreateForm
...
...
@@ -58,7 +58,8 @@ class AssetCreateView(AdminUserRequiredMixin,CreateAssetTagsMiXin,CreateView):
return
super
(
AssetCreateView
,
self
)
.
form_valid
(
form
)
def
form_invalid
(
self
,
form
):
print
(
form
.
errors
)
if
form
.
errors
.
get
(
'__all__'
):
form
.
errors
[
'all'
]
=
form
.
errors
.
get
(
'__all__'
)
return
super
(
AssetCreateView
,
self
)
.
form_invalid
(
form
)
def
get_context_data
(
self
,
**
kwargs
):
...
...
apps/locale/zh/LC_MESSAGES/django.po
View file @
8d7759d2
...
...
@@ -1610,7 +1610,7 @@ msgid ""
"here reset password</a>\n"
" </br>\n"
" This link is valid for 1 hour. After it expires, <a href=\"%"
"(forget_password_url)s?email=%(email)s\">request new one<
<
/a>\n"
"(forget_password_url)s?email=%(email)s\">request new one</a>\n"
"\n"
" </br>\n"
" ---\n"
...
...
apps/static/js/jumpserver.js
View file @
8d7759d2
...
...
@@ -189,9 +189,9 @@ function activeNav() {
function
APIUpdateAttr
(
props
)
{
// props = {url: .., body: , success: , error: , method: ,}
props
=
props
||
{};
success_message
=
props
.
success_message
||
'Update Successfully!'
;
fail_message
=
props
.
fail_message
||
'Error occurred while updating.'
;
var
success_message
=
props
.
success_message
||
'Update Successfully!'
;
var
fail_message
=
props
.
fail_message
||
'Error occurred while updating.'
;
console
.
log
(
props
.
body
);
$
.
ajax
({
url
:
props
.
url
,
type
:
props
.
method
||
"PATCH"
,
...
...
apps/templates/_base_create_update.html
View file @
8d7759d2
...
...
@@ -28,10 +28,17 @@
</div>
</div>
<div
class=
"ibox-content"
>
{% block form %} {% endblock %}
{% if form.errors.all %}
<div
class=
"alert alert-danger"
style=
"margin: 20px auto 0px"
>
{{ form.errors.all }}
</div>
{% endif %}
{% block form %}
{% endblock %}
</div>
</div>
</div>
</div>
</div>
{% endblock %}
apps/users/api.py
View file @
8d7759d2
...
...
@@ -6,120 +6,119 @@ import base64
from
django.shortcuts
import
get_object_or_404
from
django.core.cache
import
cache
from
django.conf
import
settings
from
rest_framework
import
generics
,
status
from
rest_framework
import
generics
,
status
,
viewsets
from
rest_framework.response
import
Response
from
rest_framework.views
import
APIView
from
rest_framework_bulk
import
ListBulkCreateUpdateDestroyAPIView
from
rest_framework_bulk
import
ListBulkCreateUpdateDestroyAPIView
,
BulkModelViewSet
from
rest_framework
import
authentication
from
common.mixins
import
BulkDeleteApiMixin
from
common.utils
import
get_logger
from
.utils
import
check_user_valid
,
token_gen
from
.models
import
User
,
UserGroup
from
.serializers
import
UserDetailSerializer
,
UserAndGroupSerializer
,
\
GroupDetailSerializer
,
UserPKUpdateSerializer
,
UserBulkUpdateSerializer
,
GroupBulkUpdateSerializer
from
.
import
serializers
from
.backends
import
IsSuperUser
,
IsTerminalUser
,
IsValidUser
,
IsSuperUserOrTerminalUser
logger
=
get_logger
(
__name__
)
class
User
DetailApi
(
generics
.
RetrieveUpdateDestroyAPIView
):
class
User
ViewSet
(
BulkModelViewSet
):
queryset
=
User
.
objects
.
all
()
serializer_class
=
UserDetail
Serializer
serializer_class
=
serializers
.
User
Serializer
permission_classes
=
(
IsSuperUser
,)
class
UserAndGroupEditApi
(
generics
.
RetrieveUpdateAPIView
):
queryset
=
User
.
objects
.
all
()
serializer_class
=
UserAndGroupSerializer
permission_classes
=
(
IsSuperUser
,)
#
class UserAndGroupEditApi(generics.RetrieveUpdateAPIView):
#
queryset = User.objects.all()
# serializer_class = serializers.
UserAndGroupSerializer
#
permission_classes = (IsSuperUser,)
class
UserResetPasswordApi
(
generics
.
UpdateAPIView
):
queryset
=
User
.
objects
.
all
()
serializer_class
=
UserDetail
Serializer
serializer_class
=
serializers
.
User
Serializer
def
perform_update
(
self
,
serializer
):
# Note: we are not updating the user object here.
# We just do the reset-password staff.
user
=
self
.
get_object
()
import
uuid
from
.utils
import
send_reset_password_mail
user
=
self
.
get_object
()
user
.
password_raw
=
str
(
uuid
.
uuid4
())
user
.
save
()
from
.utils
import
send_reset_password_mail
send_reset_password_mail
(
user
)
class
UserResetP
K
Api
(
generics
.
UpdateAPIView
):
class
UserResetP
ubKey
Api
(
generics
.
UpdateAPIView
):
queryset
=
User
.
objects
.
all
()
serializer_class
=
UserDetail
Serializer
serializer_class
=
serializers
.
User
Serializer
def
perform_update
(
self
,
serializer
):
from
.utils
import
send_reset_ssh_key_mail
user
=
self
.
get_object
()
user
.
is_public_key_valid
=
False
user
.
save
()
from
.utils
import
send_reset_ssh_key_mail
send_reset_ssh_key_mail
(
user
)
class
UserUpdatePKApi
(
generics
.
UpdateAPIView
):
queryset
=
User
.
objects
.
all
()
serializer_class
=
UserPKUpdateSerializer
def
perform_update
(
self
,
serializer
):
user
=
self
.
get_object
()
user
.
private_key
=
serializer
.
validated_data
[
'_public_key'
]
user
.
save
()
class
GroupDetailApi
(
generics
.
RetrieveUpdateDestroyAPIView
):
queryset
=
UserGroup
.
objects
.
all
()
serializer_class
=
GroupDetailSerializer
def
perform_update
(
self
,
serializer
):
users
=
serializer
.
validated_data
.
get
(
'users'
)
if
users
:
group
=
self
.
get_object
()
# Note: use `list` method to force hitting the db.
group_users
=
list
(
group
.
users
.
all
())
serializer
.
save
()
group
.
users
.
set
(
users
+
group_users
)
group
.
save
()
return
serializer
.
save
()
class
UserListUpdateApi
(
BulkDeleteApiMixin
,
ListBulkCreateUpdateDestroyAPIView
):
queryset
=
User
.
objects
.
all
()
serializer_class
=
UserBulkUpdateSerializer
permission_classes
=
(
IsSuperUserOrTerminalUser
,)
# def get(self, request, *args, **kwargs):
# return super(UserListUpdateApi, self).get(request, *args, **kwargs)
class
GroupListUpdateApi
(
BulkDeleteApiMixin
,
ListBulkCreateUpdateDestroyAPIView
):
queryset
=
UserGroup
.
objects
.
all
()
serializer_class
=
GroupBulkUpdateSerializer
class
DeleteUserFromGroupApi
(
generics
.
DestroyAPIView
):
queryset
=
UserGroup
.
objects
.
all
()
serializer_class
=
GroupDetailSerializer
def
destroy
(
self
,
request
,
*
args
,
**
kwargs
):
group
=
self
.
get_object
()
self
.
perform_destroy
(
group
,
**
kwargs
)
return
Response
(
status
=
status
.
HTTP_204_NO_CONTENT
)
def
perform_destroy
(
self
,
instance
,
**
kwargs
):
user_id
=
kwargs
.
get
(
'uid'
)
user
=
get_object_or_404
(
User
,
id
=
user_id
)
instance
.
users
.
remove
(
user
)
#
# class UserUpdatePKApi(generics.UpdateAPIView):
# queryset = User.objects.all()
# serializer_class = serializers.UserPKUpdateSerializer
#
# def perform_update(self, serializer):
# user = self.get_object()
# user.private_key = serializer.validated_data['_public_key']
# user.save()
#
#
# class GroupDetailApi(generics.RetrieveUpdateDestroyAPIView):
# queryset = UserGroup.objects.all()
# serializer_class = serializers.GroupDetailSerializer
#
# def perform_update(self, serializer):
# users = serializer.validated_data.get('users')
# if users:
# group = self.get_object()
# Note: use `list` method to force hitting the db.
# group_users = list(group.users.all())
# serializer.save()
# group.users.set(users + group_users)
# group.save()
# return
# serializer.save()
#
#
# class UserListUpdateApi(BulkDeleteApiMixin, ListBulkCreateUpdateDestroyAPIView):
# queryset = User.objects.all()
# serializer_class = serializers.UserBulkUpdateSerializer
# permission_classes = (IsSuperUserOrTerminalUser,)
#
# def get(self, request, *args, **kwargs):
# return super(UserListUpdateApi, self).get(request, *args, **kwargs)
#
#
# class GroupListUpdateApi(BulkDeleteApiMixin, ListBulkCreateUpdateDestroyAPIView):
# queryset = UserGroup.objects.all()
# serializer_class = serializers.GroupBulkUpdateSerializer
class
UserTokenApi
(
APIView
):
# class DeleteUserFromGroupApi(generics.DestroyAPIView):
# queryset = UserGroup.objects.all()
# serializer_class = serializers.GroupDetailSerializer
#
# def destroy(self, request, *args, **kwargs):
# group = self.get_object()
# self.perform_destroy(group, **kwargs)
# return Response(status=status.HTTP_204_NO_CONTENT)
#
# def perform_destroy(self, instance, **kwargs):
# user_id = kwargs.get('uid')
# user = get_object_or_404(User, id=user_id)
# instance.users.remove(user)
#
#
class
UserAuthApi
(
APIView
):
permission_classes
=
()
expiration
=
settings
.
CONFIG
.
TOKEN_EXPIRATION
or
3600
...
...
@@ -128,9 +127,9 @@ class UserTokenApi(APIView):
password
=
request
.
data
.
get
(
'password'
,
''
)
public_key
=
request
.
data
.
get
(
'public_key'
,
''
)
remote_addr
=
request
.
META
.
get
(
'REMOTE_ADDR'
,
''
)
remote_addr
=
base64
.
b64encode
(
remote_addr
)
.
replace
(
'='
,
''
)
user
=
check_user_valid
(
username
=
username
,
password
=
password
,
public_key
=
public_key
)
if
user
:
token
=
cache
.
get
(
'
%
s_
%
s'
%
(
user
.
id
,
remote_addr
))
if
not
token
:
...
...
apps/users/models.py
View file @
8d7759d2
...
...
@@ -3,6 +3,7 @@
from
__future__
import
unicode_literals
from
django.conf
import
settings
from
django.contrib.auth
import
logout
from
django.contrib.auth.hashers
import
make_password
from
django.contrib.auth.models
import
AbstractUser
from
django.core
import
signing
...
...
apps/users/serializers.py
View file @
8d7759d2
...
...
@@ -9,10 +9,35 @@ from common.utils import signer
from
.models
import
User
,
UserGroup
class
UserDetailSerializer
(
serializers
.
ModelSerializer
):
# class UserDetailSerializer(BulkSerializerMixin, serializers.ModelSerializer):
# class Meta:
# model = User
# fields = ['avatar', 'wechat', 'phone', 'enable_otp', 'comment', 'is_active', 'name']
class
UserSerializer
(
BulkSerializerMixin
,
serializers
.
ModelSerializer
):
group_display
=
serializers
.
SerializerMethodField
()
active_display
=
serializers
.
SerializerMethodField
()
groups
=
serializers
.
PrimaryKeyRelatedField
(
many
=
True
,
queryset
=
UserGroup
.
objects
.
all
())
class
Meta
:
model
=
User
fields
=
[
'avatar'
,
'wechat'
,
'phone'
,
'enable_otp'
,
'comment'
,
'is_active'
,
'name'
]
list_serializer_class
=
BulkListSerializer
exclude
=
[
'first_name'
,
'last_name'
,
'password'
,
'_private_key'
,
'_public_key'
]
def
get_field_names
(
self
,
declared_fields
,
info
):
fields
=
super
(
UserSerializer
,
self
)
.
get_field_names
(
declared_fields
,
info
)
fields
.
extend
([
'group_display'
,
'get_role_display'
])
return
fields
@staticmethod
def
get_group_display
(
obj
):
return
" "
.
join
([
group
.
name
for
group
in
obj
.
groups
.
all
()])
@staticmethod
def
get_active_display
(
obj
):
# TODO: user active state
return
not
(
obj
.
is_expired
and
obj
.
is_active
)
class
UserPKUpdateSerializer
(
serializers
.
ModelSerializer
):
...
...
@@ -44,43 +69,43 @@ class UserAndGroupSerializer(serializers.ModelSerializer):
fields
=
[
'id'
,
'groups'
]
class
GroupDetailSerializer
(
serializers
.
ModelSerializer
):
class
Meta
:
model
=
UserGroup
fields
=
[
'id'
,
'name'
,
'comment'
,
'date_created'
,
'created_by'
,
'users'
]
class
UserBulkUpdateSerializer
(
BulkSerializerMixin
,
serializers
.
ModelSerializer
):
group_display
=
serializers
.
SerializerMethodField
()
active_display
=
serializers
.
SerializerMethodField
()
groups
=
serializers
.
PrimaryKeyRelatedField
(
many
=
True
,
queryset
=
UserGroup
.
objects
.
all
())
# class GroupDetailSerializer(serializers.ModelSerializer):
# class Meta:
# model = UserGroup
# fields = ['id', 'name', 'comment', 'date_created', 'created_by', 'users']
class
Meta
(
object
):
model
=
User
list_serializer_class
=
BulkListSerializer
fields
=
[
'id'
,
'is_active'
,
'username'
,
'name'
,
'email'
,
'role'
,
'avatar'
,
'enable_otp'
,
'comment'
,
'groups'
,
'get_role_display'
,
'group_display'
,
'active_display'
]
@staticmethod
def
get_group_display
(
obj
):
return
" "
.
join
([
group
.
name
for
group
in
obj
.
groups
.
all
()])
@staticmethod
def
get_active_display
(
obj
):
# TODO: user active state
return
not
(
obj
.
is_expired
and
obj
.
is_active
)
class
GroupBulkUpdateSerializer
(
BulkSerializerMixin
,
serializers
.
ModelSerializer
):
user_amount
=
serializers
.
SerializerMethodField
()
class
Meta
:
model
=
UserGroup
list_serializer_class
=
BulkListSerializer
fields
=
[
'id'
,
'name'
,
'comment'
,
'user_amount'
]
@staticmethod
def
get_user_amount
(
obj
):
return
obj
.
users
.
count
()
# class UserBulkUpdateSerializer(BulkSerializerMixin, serializers.ModelSerializer):
# group_display = serializers.SerializerMethodField()
# active_display = serializers.SerializerMethodField()
# groups = serializers.PrimaryKeyRelatedField(many=True, queryset=UserGroup.objects.all())
#
# class Meta(object):
# model = User
# list_serializer_class = BulkListSerializer
# fields = ['id', 'is_active', 'username', 'name', 'email', 'role', 'avatar',
# 'enable_otp', 'comment', 'groups', 'get_role_display',
# 'group_display', 'active_display']
#
# @staticmethod
# def get_group_display(obj):
# return " ".join([group.name for group in obj.groups.all()])
#
# @staticmethod
# def get_active_display(obj):
# TODO: user active state
# return not (obj.is_expired and obj.is_active)
#
#
# class GroupBulkUpdateSerializer(BulkSerializerMixin, serializers.ModelSerializer):
# user_amount = serializers.SerializerMethodField()
#
# class Meta:
# model = UserGroup
# list_serializer_class = BulkListSerializer
# fields = ['id', 'name', 'comment', 'user_amount']
#
# @staticmethod
# def get_user_amount(obj):
# return obj.users.count()
#
apps/users/templates/users/_user.html
View file @
8d7759d2
{% extends '
bas
e.html' %}
{% extends '
_base_create_updat
e.html' %}
{% load i18n %}
{% load static %}
{% load bootstrap %}
{% block custom_head_css_js %}
<link
href=
"{% static "
css
/
plugins
/
select2
/
select2
.
min
.
css
"
%}"
rel=
"stylesheet"
>
<script
src=
"{% static "
js
/
plugins
/
select2
/
select2
.
full
.
min
.
js
"
%}"
></script>
<link
href=
"{% static "
css
/
plugins
/
datepicker
/
datepicker3
.
css
"
%}"
rel=
"stylesheet"
>
{% endblock %}
{% block content %}
<div
class=
"wrapper wrapper-content animated fadeInRight"
>
<div
class=
"row"
>
<div
class=
"col-sm-12"
>
<div
class=
"ibox float-e-margins"
>
<div
class=
"ibox-title"
>
<h5>
{% block user_template_title %}{% trans 'Create user' %}{% endblock %}
</h5>
<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>
<a
class=
"close-link"
>
<i
class=
"fa fa-times"
></i>
</a>
</div>
</div>
<div
class=
"ibox-content"
>
<form
method=
"post"
class=
"form-horizontal"
action=
""
enctype=
"multipart/form-data"
>
{% csrf_token %}
<h3>
{% trans 'Account' %}
</h3>
{% block username %} {% endblock %}
{{ form.name|bootstrap_horizontal }}
{{ form.email|bootstrap_horizontal }}
{{ form.groups|bootstrap_horizontal }}
{% block form %}
<form
method=
"post"
class=
"form-horizontal"
action=
""
enctype=
"multipart/form-data"
>
{% csrf_token %}
<h3>
{% trans 'Account' %}
</h3>
{% block username %} {% endblock %}
{{ form.name|bootstrap_horizontal }}
{{ form.email|bootstrap_horizontal }}
{{ form.groups|bootstrap_horizontal }}
<div
class=
"hr-line-dashed"
></div>
{% block password %} {% endblock %}
<div
class=
"hr-line-dashed"
></div>
{% block password %} {% endblock %}
<div
class=
"hr-line-dashed"
></div>
<h3>
{% trans 'Security and Role' %}
</h3>
{{ form.role|bootstrap_horizontal }}
<div
class=
"form-group {% if form.date_expired.errors %} has-error {% endif %}"
id=
"date_5"
>
<label
for=
"{{ form.date_expired.id_for_label }}"
class=
"col-sm-2 control-label"
>
{{ form.date_expired.label }}
</label>
<div
class=
"col-sm-9"
>
<div
class=
"input-group date"
>
<span
class=
"input-group-addon"
><i
class=
"fa fa-calendar"
></i></span>
<input
id=
"{{ form.date_expired.id_for_label }}"
name=
"{{ form.date_expired.html_name }}"
type=
"text"
class=
"form-control"
value=
"{{ form.date_expired.value|date:'Y-m-d' }}"
>
</div>
<span
class=
"help-block "
>
{{ form.date_expired.errors }}
</span>
</div>
</div>
{# {{ form.date_expired|bootstrap_horizontal }}#}
<div
class=
"form-group"
>
<label
for=
"{{ form.enable_otp.id_for_label }}"
class=
"col-sm-2 control-label"
>
{% trans 'Enable OTP' %}
</label>
<div
class=
"col-sm-8"
>
{{ form.enable_otp }}
</div>
</div>
<div
class=
"hr-line-dashed"
></div>
<h3>
{% trans 'Profile' %}
</h3>
{{ form.phone|bootstrap_horizontal }}
{{ form.wechat|bootstrap_horizontal }}
{{ form.comment|bootstrap_horizontal }}
<div
class=
"hr-line-dashed"
></div>
<div
class=
"form-group"
>
<div
class=
"col-sm-4 col-sm-offset-2"
>
<button
class=
"btn btn-white"
type=
"reset"
>
{% trans 'Reset' %}
</button>
<button
id=
"submit_button"
class=
"btn btn-primary"
type=
"submit"
>
{% trans 'Submit' %}
</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
<div
class=
"hr-line-dashed"
></div>
<h3>
{% trans 'Security and Role' %}
</h3>
{{ form.role|bootstrap_horizontal }}
<div
class=
"form-group {% if form.date_expired.errors %} has-error {% endif %}"
id=
"date_5"
>
<label
for=
"{{ form.date_expired.id_for_label }}"
class=
"col-sm-2 control-label"
>
{{ form.date_expired.label }}
</label>
<div
class=
"col-sm-9"
>
<div
class=
"input-group date"
>
<span
class=
"input-group-addon"
><i
class=
"fa fa-calendar"
></i></span>
<input
id=
"{{ form.date_expired.id_for_label }}"
name=
"{{ form.date_expired.html_name }}"
type=
"text"
class=
"form-control"
value=
"{{ form.date_expired.value|date:'Y-m-d' }}"
>
</div>
<span
class=
"help-block "
>
{{ form.date_expired.errors }}
</span>
</div>
</div>
{{ form.date_expired|bootstrap_horizontal }}#}
<div
class=
"form-group"
>
<label
for=
"{{ form.enable_otp.id_for_label }}"
class=
"col-sm-2 control-label"
>
{% trans 'Enable OTP' %}
</label>
<div
class=
"col-sm-8"
>
{{ form.enable_otp }}
</div>
</div>
<div
class=
"hr-line-dashed"
></div>
<h3>
{% trans 'Profile' %}
</h3>
{{ form.phone|bootstrap_horizontal }}
{{ form.wechat|bootstrap_horizontal }}
{{ form.comment|bootstrap_horizontal }}
<div
class=
"hr-line-dashed"
></div>
<div
class=
"form-group"
>
<div
class=
"col-sm-4 col-sm-offset-2"
>
<button
class=
"btn btn-white"
type=
"reset"
>
{% trans 'Reset' %}
</button>
<button
id=
"submit_button"
class=
"btn btn-primary"
type=
"submit"
>
{% trans 'Submit' %}
</button>
</div>
</div>
</form>
{% endblock %}
{% block custom_foot_js %}
<script
src=
"{% static 'js/plugins/datepicker/bootstrap-datepicker.js' %}"
></script>
...
...
apps/users/templates/users/user_detail.html
View file @
8d7759d2
This diff is collapsed.
Click to expand it.
apps/users/templates/users/user_list.html
View file @
8d7759d2
...
...
@@ -72,7 +72,7 @@ $(document).ready(function(){
$
(
td
).
html
(
update_btn
+
del_btn
)
}
}}],
ajax_url
:
'{% url "users:
user-bulk-update-api
" %}'
,
ajax_url
:
'{% url "users:
api-user-list
" %}'
,
columns
:
[{
data
:
function
(){
return
""
}},
{
data
:
"username"
},
{
data
:
"name"
},
{
data
:
"get_role_display"
},
{
data
:
"group_display"
},
{
data
:
function
(){
return
999
}},
{
data
:
"active_display"
},
{
data
:
"id"
}],
op_html
:
$
(
'#actions'
).
html
()
...
...
@@ -90,7 +90,7 @@ $(document).ready(function(){
if
(
id_list
===
[])
{
return
false
;
}
var
the_url
=
"{% url 'users:
user-bulk-update-api
' %}"
;
var
the_url
=
"{% url 'users:
api-user-list
' %}"
;
function
doDeactive
()
{
var
body
=
$
.
each
(
id_list
,
function
(
index
,
user_object
)
{
user_object
[
'is_active'
]
=
false
;
...
...
@@ -143,7 +143,7 @@ $(document).ready(function(){
var
$this
=
$
(
this
);
function
doDelete
()
{
var
uid
=
$this
.
data
(
'uid'
);
var
the_url
=
'{% url "users:
user-patch-api
" pk=99991937 %}'
.
replace
(
'99991937'
,
uid
);
var
the_url
=
'{% url "users:
api-user-detail
" pk=99991937 %}'
.
replace
(
'99991937'
,
uid
);
var
body
=
{};
var
success
=
function
()
{
var
msg
=
"{% trans 'User Deleted.' %}"
;
...
...
@@ -198,7 +198,7 @@ $(document).ready(function(){
if
(
post_list
===
[])
{
return
false
}
var
the_url
=
"{% url 'users:
user-bulk-update-api
' %}"
;
var
the_url
=
"{% url 'users:
api-user-list
' %}"
;
var
success
=
function
()
{
var
msg
=
"{% trans 'The selected users has been updated successfully.' %}"
;
swal
(
"{% trans 'User Updated' %}"
,
msg
,
"success"
);
...
...
apps/users/urls.py
View file @
8d7759d2
from
django.conf.urls
import
url
from
rest_framework_bulk.routes
import
BulkRouter
import
views
import
api
...
...
@@ -14,6 +14,7 @@ urlpatterns = [
url
(
r'^password/reset$'
,
views
.
UserResetPasswordView
.
as_view
(),
name
=
'reset-password'
),
url
(
r'^password/reset/success$'
,
views
.
UserResetPasswordSuccessView
.
as_view
(),
name
=
'reset-password-success'
),
# User view
url
(
r'^user$'
,
views
.
UserListView
.
as_view
(),
name
=
'user-list'
),
url
(
r'^user/(?P<pk>[0-9]+)$'
,
views
.
UserDetailView
.
as_view
(),
name
=
'user-detail'
),
url
(
r'^user/(?P<pk>[0-9]+)/asset-permission$'
,
views
.
UserAssetPermissionView
.
as_view
(),
...
...
@@ -27,6 +28,8 @@ urlpatterns = [
url
(
r'^user/(?P<pk>[0-9]+)/assets-perm$'
,
views
.
UserDetailView
.
as_view
(),
name
=
'user-detail'
),
url
(
r'^user/create$'
,
views
.
UserCreateView
.
as_view
(),
name
=
'user-create'
),
url
(
r'^user/(?P<pk>[0-9]+)/update$'
,
views
.
UserUpdateView
.
as_view
(),
name
=
'user-update'
),
# User group view
url
(
r'^user-group$'
,
views
.
UserGroupListView
.
as_view
(),
name
=
'user-group-list'
),
url
(
r'^user-group/(?P<pk>[0-9]+)$'
,
views
.
UserGroupDetailView
.
as_view
(),
name
=
'user-group-detail'
),
url
(
r'^user-group/create$'
,
views
.
UserGroupCreateView
.
as_view
(),
name
=
'user-group-create'
),
...
...
@@ -34,17 +37,23 @@ urlpatterns = [
]
router
=
BulkRouter
()
router
.
register
(
r'v1/users'
,
api
.
UserViewSet
,
'api-user'
)
# router.register(r'v1/user-groups', api.AssetViewSet, 'api-groups')
urlpatterns
+=
[
url
(
r'^v1/users/$'
,
api
.
UserListUpdateApi
.
as_view
(),
name
=
'user-bulk-update-api'
),
url
(
r'^v1/users/token/$'
,
api
.
UserTokenApi
.
as_view
(),
name
=
'user-token-api'
),
url
(
r'^v1/users/(?P<pk>\d+)/$'
,
api
.
UserDetailApi
.
as_view
(),
name
=
'user-patch-api'
),
# url(r'^v1/users/$', api.UserListUpdateApi.as_view(), name='user-bulk-update-api'),
url
(
r'^v1/users/token/$'
,
api
.
UserAuthApi
.
as_view
(),
name
=
'user-token-api'
),
url
(
r'^v1/users/(?P<pk>\d+)/reset-password/$'
,
api
.
UserResetPasswordApi
.
as_view
(),
name
=
'user-reset-password-api'
),
url
(
r'^v1/users/(?P<pk>\d+)/reset-pk/$'
,
api
.
UserResetPKApi
.
as_view
(),
name
=
'user-reset-pk-api'
),
url
(
r'^v1/users/(?P<pk>\d+)/update-pk/$'
,
api
.
UserUpdatePKApi
.
as_view
(),
name
=
'user-update-pk-api'
),
url
(
r'^v1/user-groups/$'
,
api
.
GroupListUpdateApi
.
as_view
(),
name
=
'user-group-bulk-update-api'
),
url
(
r'^v1/user-groups/(?P<pk>\d+)/$'
,
api
.
GroupDetailApi
.
as_view
(),
name
=
'user-group-detail-api'
),
url
(
r'^v1/user-groups/(?P<pk>\d+)/user/(?P<uid>\d+)/$'
,
api
.
DeleteUserFromGroupApi
.
as_view
(),
name
=
'delete-user-from-group-api'
),
url
(
r'^v1/user-groups/(?P<pk>\d+)/users/$'
,
api
.
UserAndGroupEditApi
.
as_view
(),
name
=
'group-user-edit-api'
),
#
url(r'^v1/users/(?P<pk>\d+)/reset-pk/$', api.UserResetPKApi.as_view(), name='user-reset-pk-api'),
#
url(r'^v1/users/(?P<pk>\d+)/update-pk/$', api.UserUpdatePKApi.as_view(), name='user-update-pk-api'),
#
url(r'^v1/user-groups/$', api.GroupListUpdateApi.as_view(), name='user-group-bulk-update-api'),
#
url(r'^v1/user-groups/(?P<pk>\d+)/$', api.GroupDetailApi.as_view(), name='user-group-detail-api'),
#
url(r'^v1/user-groups/(?P<pk>\d+)/user/(?P<uid>\d+)/$',
#
api.DeleteUserFromGroupApi.as_view(), name='delete-user-from-group-api'),
#
url(r'^v1/user-groups/(?P<pk>\d+)/users/$',
#
api.UserAndGroupEditApi.as_view(), name='group-user-edit-api'),
]
urlpatterns
+=
router
.
urls
apps/users/utils.py
View file @
8d7759d2
...
...
@@ -78,7 +78,7 @@ def send_reset_password_mail(user):
</br>
<a href="
%(rest_password_url)
s?token=
%(rest_password_token)
s">Click here reset password</a>
</br>
This link is valid for 1 hour. After it expires, <a href="
%(forget_password_url)
s?email=
%(email)
s">request new one<
<
/a>
This link is valid for 1 hour. After it expires, <a href="
%(forget_password_url)
s?email=
%(email)
s">request new one</a>
</br>
---
...
...
apps/users/views.py
View file @
8d7759d2
...
...
@@ -64,7 +64,7 @@ class UserLoginView(FormView):
@method_decorator
(
never_cache
,
name
=
'dispatch'
)
class
UserLogoutView
(
TemplateView
):
template_name
=
'
common/
flash_message_standalone.html'
template_name
=
'flash_message_standalone.html'
def
get
(
self
,
request
,
*
args
,
**
kwargs
):
auth_logout
(
request
)
...
...
@@ -142,7 +142,7 @@ class UserUpdateView(AdminUserRequiredMixin, UpdateView):
class
UserDetailView
(
AdminUserRequiredMixin
,
DetailView
):
model
=
User
template_name
=
'users/user_detail.html'
context_object_name
=
"user
_object
"
context_object_name
=
"user"
def
get_context_data
(
self
,
**
kwargs
):
groups
=
UserGroup
.
objects
.
exclude
(
id__in
=
self
.
object
.
groups
.
all
())
...
...
@@ -239,7 +239,7 @@ class UserForgotPasswordView(TemplateView):
class
UserForgotPasswordSendmailSuccessView
(
TemplateView
):
template_name
=
'
common/
flash_message_standalone.html'
template_name
=
'flash_message_standalone.html'
def
get_context_data
(
self
,
**
kwargs
):
context
=
{
...
...
@@ -252,7 +252,7 @@ class UserForgotPasswordSendmailSuccessView(TemplateView):
class
UserResetPasswordSuccessView
(
TemplateView
):
template_name
=
'
common/
flash_message_standalone.html'
template_name
=
'flash_message_standalone.html'
def
get_context_data
(
self
,
**
kwargs
):
context
=
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment