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
6751c5a6
Commit
6751c5a6
authored
Sep 13, 2016
by
xiaokong1937@gmail.com
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
reset user password and ssh pk implement
parent
00502ce3
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
160 additions
and
37 deletions
+160
-37
sweetalert.css
apps/static/css/plugins/sweetalert/sweetalert.css
+0
-0
jumpserver.js
apps/static/js/jumpserver.js
+20
-18
sweetalert.min.js
apps/static/js/plugins/sweetalert/sweetalert.min.js
+0
-0
_modal.html
apps/templates/_modal.html
+20
-0
api.py
apps/users/api.py
+23
-0
serializers.py
apps/users/serializers.py
+16
-0
_user_reset_pk_modal.html
apps/users/templates/users/_user_reset_pk_modal.html
+8
-0
user_detail.html
apps/users/templates/users/user_detail.html
+68
-19
urls.py
apps/users/urls.py
+2
-0
utils.py
apps/users/utils.py
+3
-0
No files found.
apps/static/css/plugins/sweetalert/sweetalert.css
0 → 100644
View file @
6751c5a6
This diff is collapsed.
Click to expand it.
apps/static/js/jumpserver.js
View file @
6751c5a6
...
...
@@ -4,10 +4,10 @@
var
checked
=
false
;
function
check_all
(
form
)
{
var
checkboxes
=
document
.
getElementById
(
form
);
if
(
checked
==
false
)
{
checked
=
true
if
(
checked
==
=
false
)
{
checked
=
true
;
}
else
{
checked
=
false
checked
=
false
;
}
for
(
var
i
=
0
;
i
<
checkboxes
.
elements
.
length
;
i
++
)
{
if
(
checkboxes
.
elements
[
i
].
type
==
"checkbox"
)
{
...
...
@@ -51,13 +51,13 @@ function GetRowData(row){
//此函数用于在多选提交时至少要选择一行
function
GetTableDataBox
()
{
var
tabProduct
=
document
.
getElementById
(
"editable"
);
var
tableData
=
new
Array
()
;
var
returnData
=
new
Array
()
;
var
tableData
=
[]
;
var
returnData
=
[]
;
var
checkboxes
=
document
.
getElementById
(
"contents_form"
);
var
id_list
=
new
Array
()
;
var
id_list
=
[]
;
len
=
checkboxes
.
elements
.
length
;
for
(
var
i
=
0
;
i
<
len
;
i
++
)
{
if
(
checkboxes
.
elements
[
i
].
type
==
"checkbox"
&&
checkboxes
.
elements
[
i
].
checked
==
true
&&
checkboxes
.
elements
[
i
].
value
!=
"checkall"
)
{
if
(
checkboxes
.
elements
[
i
].
type
==
"checkbox"
&&
checkboxes
.
elements
[
i
].
checked
==
=
true
&&
checkboxes
.
elements
[
i
].
value
!=
"checkall"
)
{
id_list
.
push
(
i
);
}
}
...
...
@@ -67,7 +67,7 @@ function GetTableDataBox() {
tableData
.
push
(
GetRowData
(
tabProduct
.
rows
[
id_list
[
i
]]));
}
if
(
id_list
.
length
==
0
){
if
(
id_list
.
length
==
=
0
){
alert
(
'请至少选择一行!'
);
}
returnData
.
push
(
tableData
);
...
...
@@ -77,7 +77,7 @@ function GetTableDataBox() {
function
move
(
from
,
to
,
from_o
,
to_o
)
{
$
(
"#"
+
from
+
" option"
).
each
(
function
()
{
if
(
$
(
this
).
prop
(
"selected"
)
==
true
)
{
if
(
$
(
this
).
prop
(
"selected"
)
==
=
true
)
{
$
(
"#"
+
to
).
append
(
this
);
if
(
typeof
from_o
!==
'undefined'
){
$
(
"#"
+
to_o
).
append
(
$
(
"#"
+
from_o
+
" option[value='"
+
this
.
value
+
"']"
));
...
...
@@ -88,7 +88,7 @@ function move(from, to, from_o, to_o) {
function
move_left
(
from
,
to
,
from_o
,
to_o
)
{
$
(
"#"
+
from
+
" option"
).
each
(
function
()
{
if
(
$
(
this
).
prop
(
"selected"
)
==
true
)
{
if
(
$
(
this
).
prop
(
"selected"
)
==
=
true
)
{
$
(
"#"
+
to
).
append
(
this
);
if
(
typeof
from_o
!==
'undefined'
){
$
(
"#"
+
to_o
).
append
(
$
(
"#"
+
from_o
+
" option[value='"
+
this
.
value
+
"']"
));
...
...
@@ -126,8 +126,8 @@ function move_left(from, to, from_o, to_o) {
function
selectAll
(){
// 选择该页面所有option
$
(
'option'
).
each
(
function
(){
$
(
this
).
attr
(
'selected'
,
true
)
})
$
(
this
).
attr
(
'selected'
,
true
)
;
})
;
}
...
...
@@ -156,6 +156,8 @@ function getIDall() {
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.'
;
$
.
ajax
({
url
:
props
.
url
,
type
:
props
.
method
||
"PATCH"
,
...
...
@@ -164,18 +166,18 @@ function APIUpdateAttr(props) {
dataType
:
props
.
data_type
||
"json"
,
}).
done
(
function
(
data
,
textStatue
,
jqXHR
)
{
if
(
typeof
props
.
success
===
'function'
)
{
return
props
.
success
(
data
)
return
props
.
success
(
data
)
;
}
else
{
toastr
.
success
(
'Update Success!'
)
toastr
.
success
(
success_message
);
}
}).
fail
(
function
(
jqXHR
,
textStatue
,
errorThrown
)
{
if
(
typeof
props
.
error
===
'function'
)
{
return
props
.
error
(
errorThrown
)
return
props
.
error
(
errorThrown
)
;
}
else
{
toastr
.
error
(
'Error occurred while updating.'
)
toastr
.
error
(
fail_message
);
}
})
})
;
return
true
;
}
var
jumpserver
=
new
Object
()
;
var
jumpserver
=
{}
;
apps/static/js/plugins/sweetalert/sweetalert.min.js
0 → 100644
View file @
6751c5a6
This diff is collapsed.
Click to expand it.
apps/templates/_modal.html
0 → 100644
View file @
6751c5a6
{% load i18n %}
<div
aria-hidden=
"true"
role=
"dialog"
tabindex=
"-1"
id=
"{% block modal_id %}{% endblock %}"
class=
"modal inmodal"
style=
"display: none;"
>
<div
class=
"modal-dialog"
>
<div
class=
"modal-content animated fadeIn"
>
<div
class=
"modal-header"
>
<button
data-dismiss=
"modal"
class=
"close"
type=
"button"
><span
aria-hidden=
"true"
>
×
</span><span
class=
"sr-only"
>
Close
</span></button>
<h4
class=
"modal-title"
>
{% block modal_title %}{% endblock %}
</h4>
<small>
{% block modal_comment %}{% endblock %}
</small>
</div>
<div
class=
"modal-body"
>
{% block modal_body %}
{% endblock %}
</div>
<div
class=
"modal-footer"
>
<button
data-dismiss=
"modal"
class=
"btn btn-white"
type=
"button"
>
{% trans "Close" %}
</button>
<button
class=
"btn btn-primary"
type=
"button"
id=
"{% block modal_confirm_id %}{% endblock %}"
>
{% trans 'Confirm' %}
</button>
</div>
</div>
</div>
</div>
apps/users/api.py
View file @
6751c5a6
...
...
@@ -6,6 +6,7 @@ import logging
from
rest_framework
import
generics
from
.serializers
import
UserSerializer
,
UserGroupSerializer
,
UserAttributeSerializer
,
UserGroupEditSerializer
from
.serializers
import
UserPKUpdateSerializer
from
.models
import
User
,
UserGroup
...
...
@@ -49,3 +50,25 @@ class UserAttributeApi(generics.RetrieveUpdateDestroyAPIView):
class
UserGroupEditApi
(
generics
.
RetrieveUpdateAPIView
):
queryset
=
User
.
objects
.
all
()
serializer_class
=
UserGroupEditSerializer
class
UserResetPasswordApi
(
generics
.
UpdateAPIView
):
queryset
=
User
.
objects
.
all
()
serializer_class
=
UserGroupEditSerializer
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
()
from
.utils
import
send_reset_password_mail
send_reset_password_mail
(
user
)
class
UserResetPKApi
(
generics
.
UpdateAPIView
):
queryset
=
User
.
objects
.
all
()
serializer_class
=
UserPKUpdateSerializer
def
perform_update
(
self
,
serializer
):
user
=
self
.
get_object
()
user
.
private_key
=
serializer
.
validated_data
[
'_private_key'
]
user
.
save
()
apps/users/serializers.py
View file @
6751c5a6
# -*- coding: utf-8 -*-
#
from
django.utils.translation
import
ugettext_lazy
as
_
from
rest_framework
import
serializers
from
.models
import
User
,
UserGroup
...
...
@@ -38,3 +40,17 @@ class UserGroupEditSerializer(serializers.ModelSerializer):
class
Meta
:
model
=
User
fields
=
[
'id'
,
'groups'
]
class
UserPKUpdateSerializer
(
serializers
.
ModelSerializer
):
class
Meta
:
model
=
User
fields
=
[
'id'
,
'_private_key'
]
def
validate__private_key
(
self
,
value
):
from
users.utils
import
validate_ssh_pk
checked
,
reason
=
validate_ssh_pk
(
value
)
if
not
checked
:
raise
serializers
.
ValidationError
(
_
(
'Not a valid ssh private key.'
))
return
value
apps/users/templates/users/_user_reset_pk_modal.html
0 → 100644
View file @
6751c5a6
{% extends '_modal.html' %}
{% load i18n %}
{% block modal_id %}user_reset_pk_modal{% endblock %}
{% block modal_title%}{% trans 'Reset User SSH Private Key' %}{% endblock %}
{% block modal_body %}
<textarea
id=
"txt_pk"
class=
"form-control"
cols=
"30"
rows=
"10"
placeholder=
"-----BEGIN RSA PRIVATE KEY-----"
></textarea>
{% endblock %}
{% block modal_confirm_id %}btn_user_reset_pk{% endblock %}
apps/users/templates/users/user_detail.html
View file @
6751c5a6
...
...
@@ -6,7 +6,9 @@
{% block custom_head_css_js %}
<link
href=
"{% static "
css
/
plugins
/
select2
/
select2
.
min
.
css
"
%}"
rel=
"stylesheet"
>
<link
href=
"{% static "
css
/
plugins
/
sweetalert
/
sweetalert
.
css
"
%}"
rel=
"stylesheet"
>
<script
src=
"{% static "
js
/
plugins
/
select2
/
select2
.
full
.
min
.
js
"
%}"
></script>
<script
src=
"{% static "
js
/
plugins
/
sweetalert
/
sweetalert
.
min
.
js
"
%}"
></script>
{% endblock %}
{% block content %}
<div
class=
"wrapper wrapper-content animated fadeInRight"
>
...
...
@@ -114,8 +116,8 @@
<table
class=
"table"
>
<tbody>
<tr
class=
"no-borders-tr"
>
<td
width=
"50%"
>
Active
:
</td>
<td><span
style=
"float:
right"
>
<td
width=
"50%"
>
{% trans 'Active' %}
:
</td>
<td><span
class=
"pull-
right"
>
<div
class=
"switch"
>
<div
class=
"onoffswitch"
>
<input
type=
"checkbox"
{%
if
user_object
.
is_active
%}
checked
{%
endif
%}
class=
"onoffswitch-checkbox"
id=
"is_active"
>
...
...
@@ -128,8 +130,8 @@
</span></td>
</tr>
<tr>
<td>
二次验证
:
</td>
<td><span
style=
"float:
right"
>
<td>
{% trans 'Enable OTP' %}
:
</td>
<td><span
class=
"pull-
right"
>
<div
class=
"switch"
>
<div
class=
"onoffswitch"
>
<input
type=
"checkbox"
class=
"onoffswitch-checkbox"
{%
if
user_object
.
enable_otp
%}
checked
{%
endif
%}
...
...
@@ -145,16 +147,16 @@
<tr>
<td>
{% trans 'Reset password' %}:
</td>
<td>
<span
style=
"float:
right"
>
<button
type=
"button"
class=
"btn btn-primary btn-xs"
style=
"width: 54px"
>
{% trans 'Reset' %}
</button>
<span
class=
"pull-
right"
>
<button
type=
"button"
class=
"btn btn-primary btn-xs"
id=
"btn_reset_password"
style=
"width: 54px"
>
{% trans 'Reset' %}
</button>
</span>
</td>
</tr>
<tr>
<td>
{% trans 'Reset ssh key' %}:
</td>
<td>
<span
style=
"float:
right"
>
<button
type=
"button"
class=
"btn btn-primary btn-xs"
style=
"width: 54px;
"
>
{% trans 'Reset' %}
</button>
<span
class=
"pull-
right"
>
<button
type=
"button"
class=
"btn btn-primary btn-xs"
id=
"btn_reset_pk"
style=
"width: 54px;"
data-toggle=
"modal"
data-target=
"#user_reset_pk_modal
"
>
{% trans 'Reset' %}
</button>
</span>
</td>
</tr>
...
...
@@ -191,7 +193,7 @@
<tr>
<td
><b
class=
"bdg_user_group"
data-gid=
{{
group
.
id
}}
>
{{ group.name }}
</b></td>
<td>
<button
class=
"btn btn-danger
btn-sm btn_delete_user_group"
type=
"button"
style=
"float: right;
"
><i
class=
"fa fa-minus"
></i></button>
<button
class=
"btn btn-danger
pull-right btn-sm btn_delete_user_group"
type=
"button
"
><i
class=
"fa fa-minus"
></i></button>
</td>
</tr>
{% endfor %}
...
...
@@ -205,6 +207,7 @@
</div>
</div>
</div>
{% include 'users/_user_reset_pk_modal.html' %}
{% endblock %}
{% block custom_foot_js %}
<script>
...
...
@@ -225,13 +228,13 @@ function updateUserGroups(user_groups) {
$
(
'.group_edit tbody'
).
append
(
'<tr>'
+
'<td><b class="bdg_user_group" data-gid="'
+
index
+
'">'
+
group_name
+
'</b></td>'
+
'<td><button class="btn btn-danger btn-sm
btn_delete_user_group" type="button" style="float: right;
"><i class="fa fa-minus"></i></button></td>'
+
'<td><button class="btn btn-danger btn-sm
pull-right btn_delete_user_group" type="button
"><i class="fa fa-minus"></i></button></td>'
+
'</tr>'
)
});
// clear jumpserver.selected_groups
jumpserver
.
selected_groups
=
{};
toastr
.
success
(
'{% trans "U
pdate s
uccess!" %}'
)
toastr
.
success
(
'{% trans "U
serGroup Update S
uccess!" %}'
)
};
APIUpdateAttr
({
url
:
the_url
,
body
:
JSON
.
stringify
(
body
),
success
:
success
,
method
:
'PUT'
});
...
...
@@ -249,18 +252,14 @@ $(document).ready(function () {
var
the_url
=
"{% url 'users:user-patch-api' pk=user_object.id %}"
;
var
checked
=
!
$
(
this
).
prop
(
'checked'
);
var
body
=
{
'is_active'
:
checked
};
var
success
=
function
()
{
toastr
.
success
(
'{% trans "Update success!" %}'
)
};
APIUpdateAttr
({
url
:
the_url
,
body
:
JSON
.
stringify
(
body
),
success
:
success
});
var
success
=
'{% trans "Update Successfully!" %}'
;
APIUpdateAttr
({
url
:
the_url
,
body
:
JSON
.
stringify
(
body
),
success_message
:
success
});
}).
on
(
'click'
,
'#enable_otp'
,
function
(){
var
the_url
=
"{% url 'users:user-patch-api' pk=user_object.id %}"
;
var
checked
=
!
$
(
this
).
prop
(
'checked'
);
var
body
=
{
'enable_otp'
:
checked
};
var
success
=
function
()
{
toastr
.
success
(
'{% trans "Update success!" %}'
)
};
APIUpdateAttr
({
url
:
the_url
,
body
:
JSON
.
stringify
(
body
),
success
:
success
});
var
success
=
'{% trans "Update Successfully!" %}'
;
APIUpdateAttr
({
url
:
the_url
,
body
:
JSON
.
stringify
(
body
),
success_message
:
success
});
}).
on
(
'click'
,
'#btn_add_user_group'
,
function
(){
if
(
Object
.
keys
(
jumpserver
.
selected_groups
).
length
===
0
)
{
return
false
;
...
...
@@ -287,6 +286,56 @@ $(document).ready(function () {
return
$
(
this
).
data
(
'gid'
);
}).
get
();
updateUserGroups
(
user_groups
)
}).
on
(
'click'
,
'#btn_reset_password'
,
function
(){
function
doReset
()
{
var
the_url
=
'{% url "users:user-reset-password-api" pk=user_object.id %}'
;
var
body
=
{};
var
success
=
function
()
{
var
msg
=
"{% trans 'E-mail sent successfully. An e-mail has been sent to the user
\
's mailbox.' %}"
;
swal
(
"{% trans 'Password-Reset' %}"
,
msg
,
"success"
);
}
APIUpdateAttr
({
url
:
the_url
,
body
:
JSON
.
stringify
(
body
),
success
:
success
});
}
swal
({
title
:
"{% trans 'Are you sure?' %}"
,
text
:
"{% trans 'This will reset the user
\
's password.' %}"
,
type
:
"warning"
,
showCancelButton
:
true
,
confirmButtonColor
:
"#DD6B55"
,
confirmButtonText
:
"{% trans 'Confirm' %}"
,
closeOnConfirm
:
false
},
function
()
{
doReset
();
}
);
}).
on
(
'click'
,
'#btn_user_reset_pk'
,
function
(){
var
$this
=
$
(
this
);
var
pk
=
$
(
'#txt_pk'
).
val
();
var
the_url
=
'{% url "users:user-reset-pk-api" pk=user_object.id %}'
;
var
body
=
{
'_private_key'
:
pk
};
var
success
=
function
()
{
$
(
'#txt_pk'
).
val
(
''
);
$this
.
closest
(
'.modal'
).
modal
(
'hide'
);
var
msg
=
"{% trans 'Successfully updated the SSH private key.' %}"
;
swal
(
"{% trans 'User SSH Private Key Reset' %}"
,
msg
,
"success"
);
};
var
fail
=
function
()
{
var
msg
=
"{% trans 'Failed to update the user
\
's SSH private key.' %}"
;
swal
({
title
:
"{% trans 'User SSH Private Key Reset' %}"
,
text
:
msg
,
type
:
"error"
,
showCancelButton
:
false
,
confirmButtonColor
:
"#DD6B55"
,
confirmButtonText
:
"{% trans 'Confirm' %}"
,
closeOnConfirm
:
true
},
function
()
{
$
(
'#txt_pk'
).
focus
();
}
);
}
APIUpdateAttr
({
url
:
the_url
,
body
:
JSON
.
stringify
(
body
),
success
:
success
,
error
:
fail
});
});
</script>
{% endblock %}
apps/users/urls.py
View file @
6751c5a6
...
...
@@ -35,6 +35,8 @@ urlpatterns += [
api
.
UserDetailDeleteUpdateApi
.
as_view
(),
name
=
'user-detail-api'
),
url
(
r'^v1/users/(?P<pk>[0-9]+)/patch$'
,
api
.
UserAttributeApi
.
as_view
(),
name
=
'user-patch-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/user-groups$'
,
api
.
UserGroupListAddApi
.
as_view
(),
name
=
'user-group-list-api'
),
url
(
r'^v1/user-groups/(?P<pk>[0-9]+)$'
,
api
.
UserGroupDetailDeleteUpdateApi
.
as_view
(),
name
=
'user-group-detail-api'
),
...
...
apps/users/utils.py
View file @
6751c5a6
...
...
@@ -5,6 +5,7 @@ import logging
import
os
import
re
from
django.conf
import
settings
from
django.contrib.auth.mixins
import
UserPassesTestMixin
from
django.urls
import
reverse_lazy
from
django.utils.translation
import
ugettext
as
_
...
...
@@ -121,6 +122,8 @@ def send_reset_password_mail(user):
'email'
:
user
.
email
,
'login_url'
:
reverse
(
'users:login'
,
external
=
True
),
}
if
settings
.
DEBUG
:
logger
.
debug
(
message
)
send_mail_async
.
delay
(
subject
,
message
,
recipient_list
,
html_message
=
message
)
...
...
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