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
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
877 additions
and
37 deletions
+877
-37
sweetalert.css
apps/static/css/plugins/sweetalert/sweetalert.css
+715
-0
jumpserver.js
apps/static/js/jumpserver.js
+20
-18
sweetalert.min.js
apps/static/js/plugins/sweetalert/sweetalert.min.js
+2
-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
body
.stop-scrolling
{
height
:
100%
;
overflow
:
hidden
;
}
.sweet-overlay
{
background-color
:
black
;
/* IE8 */
-ms-filter
:
"progid:DXImageTransform.Microsoft.Alpha(Opacity=40)"
;
/* IE8 */
background-color
:
rgba
(
0
,
0
,
0
,
0.4
);
position
:
fixed
;
left
:
0
;
right
:
0
;
top
:
0
;
bottom
:
0
;
display
:
none
;
z-index
:
10000
;
}
.sweet-alert
{
background-color
:
white
;
font-family
:
'Open Sans'
,
'Helvetica Neue'
,
Helvetica
,
Arial
,
sans-serif
;
width
:
478px
;
padding
:
17px
;
border-radius
:
5px
;
text-align
:
center
;
position
:
fixed
;
left
:
50%
;
top
:
50%
;
margin-left
:
-256px
;
margin-top
:
-200px
;
overflow
:
hidden
;
display
:
none
;
z-index
:
99999
;
}
@media
all
and
(
max-width
:
540px
)
{
.sweet-alert
{
width
:
auto
;
margin-left
:
0
;
margin-right
:
0
;
left
:
15px
;
right
:
15px
;
}
}
.sweet-alert
h2
{
color
:
#575757
;
font-size
:
30px
;
text-align
:
center
;
font-weight
:
600
;
text-transform
:
none
;
position
:
relative
;
margin
:
25px
0
;
padding
:
0
;
line-height
:
40px
;
display
:
block
;
}
.sweet-alert
p
{
color
:
#797979
;
font-size
:
16px
;
text-align
:
center
;
font-weight
:
300
;
position
:
relative
;
text-align
:
inherit
;
float
:
none
;
margin
:
0
;
padding
:
0
;
line-height
:
normal
;
}
.sweet-alert
fieldset
{
border
:
none
;
position
:
relative
;
}
.sweet-alert
.sa-error-container
{
background-color
:
#f1f1f1
;
margin-left
:
-17px
;
margin-right
:
-17px
;
overflow
:
hidden
;
padding
:
0
10px
;
max-height
:
0
;
webkit-transition
:
padding
0.15s
,
max-height
0.15s
;
transition
:
padding
0.15s
,
max-height
0.15s
;
}
.sweet-alert
.sa-error-container.show
{
padding
:
10px
0
;
max-height
:
100px
;
webkit-transition
:
padding
0.2s
,
max-height
0.2s
;
transition
:
padding
0.25s
,
max-height
0.25s
;
}
.sweet-alert
.sa-error-container
.icon
{
display
:
inline-block
;
width
:
24px
;
height
:
24px
;
border-radius
:
50%
;
background-color
:
#ea7d7d
;
color
:
white
;
line-height
:
24px
;
text-align
:
center
;
margin-right
:
3px
;
}
.sweet-alert
.sa-error-container
p
{
display
:
inline-block
;
}
.sweet-alert
.sa-input-error
{
position
:
absolute
;
top
:
29px
;
right
:
26px
;
width
:
20px
;
height
:
20px
;
opacity
:
0
;
-webkit-transform
:
scale
(
0.5
);
transform
:
scale
(
0.5
);
-webkit-transform-origin
:
50%
50%
;
transform-origin
:
50%
50%
;
-webkit-transition
:
all
0.1s
;
transition
:
all
0.1s
;
}
.sweet-alert
.sa-input-error
::before
,
.sweet-alert
.sa-input-error
::after
{
content
:
""
;
width
:
20px
;
height
:
6px
;
background-color
:
#f06e57
;
border-radius
:
3px
;
position
:
absolute
;
top
:
50%
;
margin-top
:
-4px
;
left
:
50%
;
margin-left
:
-9px
;
}
.sweet-alert
.sa-input-error
::before
{
-webkit-transform
:
rotate
(
-45deg
);
transform
:
rotate
(
-45deg
);
}
.sweet-alert
.sa-input-error
::after
{
-webkit-transform
:
rotate
(
45deg
);
transform
:
rotate
(
45deg
);
}
.sweet-alert
.sa-input-error.show
{
opacity
:
1
;
-webkit-transform
:
scale
(
1
);
transform
:
scale
(
1
);
}
.sweet-alert
input
{
width
:
100%
;
box-sizing
:
border-box
;
border-radius
:
3px
;
border
:
1px
solid
#d7d7d7
;
height
:
43px
;
margin-top
:
10px
;
margin-bottom
:
17px
;
font-size
:
18px
;
box-shadow
:
inset
0px
1px
1px
rgba
(
0
,
0
,
0
,
0.06
);
padding
:
0
12px
;
display
:
none
;
-webkit-transition
:
all
0.3s
;
transition
:
all
0.3s
;
}
.sweet-alert
input
:focus
{
outline
:
none
;
box-shadow
:
0px
0px
3px
#c4e6f5
;
border
:
1px
solid
#b4dbed
;
}
.sweet-alert
input
:focus::-moz-placeholder
{
transition
:
opacity
0.3s
0.03s
ease
;
opacity
:
0.5
;
}
.sweet-alert
input
:focus:-ms-input-placeholder
{
transition
:
opacity
0.3s
0.03s
ease
;
opacity
:
0.5
;
}
.sweet-alert
input
:focus::-webkit-input-placeholder
{
transition
:
opacity
0.3s
0.03s
ease
;
opacity
:
0.5
;
}
.sweet-alert
input
::-moz-placeholder
{
color
:
#bdbdbd
;
}
.sweet-alert
input
:-ms-input-placeholder
{
color
:
#bdbdbd
;
}
.sweet-alert
input
::-webkit-input-placeholder
{
color
:
#bdbdbd
;
}
.sweet-alert.show-input
input
{
display
:
block
;
}
.sweet-alert
button
{
background-color
:
#AEDEF4
;
color
:
white
;
border
:
none
;
box-shadow
:
none
;
font-size
:
17px
;
font-weight
:
500
;
-webkit-border-radius
:
4px
;
border-radius
:
5px
;
padding
:
10px
32px
;
margin
:
26px
5px
0
5px
;
cursor
:
pointer
;
}
.sweet-alert
button
:focus
{
outline
:
none
;
box-shadow
:
0
0
2px
rgba
(
128
,
179
,
235
,
0.5
),
inset
0
0
0
1px
rgba
(
0
,
0
,
0
,
0.05
);
}
.sweet-alert
button
:hover
{
background-color
:
#a1d9f2
;
}
.sweet-alert
button
:active
{
background-color
:
#81ccee
;
}
.sweet-alert
button
.cancel
{
background-color
:
#D0D0D0
;
}
.sweet-alert
button
.cancel
:hover
{
background-color
:
#c8c8c8
;
}
.sweet-alert
button
.cancel
:active
{
background-color
:
#b6b6b6
;
}
.sweet-alert
button
.cancel
:focus
{
box-shadow
:
rgba
(
197
,
205
,
211
,
0.8
)
0px
0px
2px
,
rgba
(
0
,
0
,
0
,
0.0470588
)
0px
0px
0px
1px
inset
!important
;
}
.sweet-alert
button
::-moz-focus-inner
{
border
:
0
;
}
.sweet-alert
[
data-has-cancel-button
=
false
]
button
{
box-shadow
:
none
!important
;
}
.sweet-alert
[
data-has-confirm-button
=
false
][
data-has-cancel-button
=
false
]
{
padding-bottom
:
40px
;
}
.sweet-alert
.sa-icon
{
width
:
80px
;
height
:
80px
;
border
:
4px
solid
gray
;
-webkit-border-radius
:
40px
;
border-radius
:
40px
;
border-radius
:
50%
;
margin
:
20px
auto
;
padding
:
0
;
position
:
relative
;
box-sizing
:
content-box
;
}
.sweet-alert
.sa-icon.sa-error
{
border-color
:
#F27474
;
}
.sweet-alert
.sa-icon.sa-error
.sa-x-mark
{
position
:
relative
;
display
:
block
;
}
.sweet-alert
.sa-icon.sa-error
.sa-line
{
position
:
absolute
;
height
:
5px
;
width
:
47px
;
background-color
:
#F27474
;
display
:
block
;
top
:
37px
;
border-radius
:
2px
;
}
.sweet-alert
.sa-icon.sa-error
.sa-line.sa-left
{
-webkit-transform
:
rotate
(
45deg
);
transform
:
rotate
(
45deg
);
left
:
17px
;
}
.sweet-alert
.sa-icon.sa-error
.sa-line.sa-right
{
-webkit-transform
:
rotate
(
-45deg
);
transform
:
rotate
(
-45deg
);
right
:
16px
;
}
.sweet-alert
.sa-icon.sa-warning
{
border-color
:
#F8BB86
;
}
.sweet-alert
.sa-icon.sa-warning
.sa-body
{
position
:
absolute
;
width
:
5px
;
height
:
47px
;
left
:
50%
;
top
:
10px
;
-webkit-border-radius
:
2px
;
border-radius
:
2px
;
margin-left
:
-2px
;
background-color
:
#F8BB86
;
}
.sweet-alert
.sa-icon.sa-warning
.sa-dot
{
position
:
absolute
;
width
:
7px
;
height
:
7px
;
-webkit-border-radius
:
50%
;
border-radius
:
50%
;
margin-left
:
-3px
;
left
:
50%
;
bottom
:
10px
;
background-color
:
#F8BB86
;
}
.sweet-alert
.sa-icon.sa-info
{
border-color
:
#C9DAE1
;
}
.sweet-alert
.sa-icon.sa-info
::before
{
content
:
""
;
position
:
absolute
;
width
:
5px
;
height
:
29px
;
left
:
50%
;
bottom
:
17px
;
border-radius
:
2px
;
margin-left
:
-2px
;
background-color
:
#C9DAE1
;
}
.sweet-alert
.sa-icon.sa-info
::after
{
content
:
""
;
position
:
absolute
;
width
:
7px
;
height
:
7px
;
border-radius
:
50%
;
margin-left
:
-3px
;
top
:
19px
;
background-color
:
#C9DAE1
;
}
.sweet-alert
.sa-icon.sa-success
{
border-color
:
#A5DC86
;
}
.sweet-alert
.sa-icon.sa-success
::before
,
.sweet-alert
.sa-icon.sa-success
::after
{
content
:
''
;
-webkit-border-radius
:
40px
;
border-radius
:
40px
;
border-radius
:
50%
;
position
:
absolute
;
width
:
60px
;
height
:
120px
;
background
:
white
;
-webkit-transform
:
rotate
(
45deg
);
transform
:
rotate
(
45deg
);
}
.sweet-alert
.sa-icon.sa-success
::before
{
-webkit-border-radius
:
120px
0
0
120px
;
border-radius
:
120px
0
0
120px
;
top
:
-7px
;
left
:
-33px
;
-webkit-transform
:
rotate
(
-45deg
);
transform
:
rotate
(
-45deg
);
-webkit-transform-origin
:
60px
60px
;
transform-origin
:
60px
60px
;
}
.sweet-alert
.sa-icon.sa-success
::after
{
-webkit-border-radius
:
0
120px
120px
0
;
border-radius
:
0
120px
120px
0
;
top
:
-11px
;
left
:
30px
;
-webkit-transform
:
rotate
(
-45deg
);
transform
:
rotate
(
-45deg
);
-webkit-transform-origin
:
0px
60px
;
transform-origin
:
0px
60px
;
}
.sweet-alert
.sa-icon.sa-success
.sa-placeholder
{
width
:
80px
;
height
:
80px
;
border
:
4px
solid
rgba
(
165
,
220
,
134
,
0.2
);
-webkit-border-radius
:
40px
;
border-radius
:
40px
;
border-radius
:
50%
;
box-sizing
:
content-box
;
position
:
absolute
;
left
:
-4px
;
top
:
-4px
;
z-index
:
2
;
}
.sweet-alert
.sa-icon.sa-success
.sa-fix
{
width
:
5px
;
height
:
90px
;
background-color
:
white
;
position
:
absolute
;
left
:
28px
;
top
:
8px
;
z-index
:
1
;
-webkit-transform
:
rotate
(
-45deg
);
transform
:
rotate
(
-45deg
);
}
.sweet-alert
.sa-icon.sa-success
.sa-line
{
height
:
5px
;
background-color
:
#A5DC86
;
display
:
block
;
border-radius
:
2px
;
position
:
absolute
;
z-index
:
2
;
}
.sweet-alert
.sa-icon.sa-success
.sa-line.sa-tip
{
width
:
25px
;
left
:
14px
;
top
:
46px
;
-webkit-transform
:
rotate
(
45deg
);
transform
:
rotate
(
45deg
);
}
.sweet-alert
.sa-icon.sa-success
.sa-line.sa-long
{
width
:
47px
;
right
:
8px
;
top
:
38px
;
-webkit-transform
:
rotate
(
-45deg
);
transform
:
rotate
(
-45deg
);
}
.sweet-alert
.sa-icon.sa-custom
{
background-size
:
contain
;
border-radius
:
0
;
border
:
none
;
background-position
:
center
center
;
background-repeat
:
no-repeat
;
}
/*
* Animations
*/
@-webkit-keyframes
showSweetAlert
{
0
%
{
transform
:
scale
(
0.7
);
-webkit-transform
:
scale
(
0.7
);
}
45
%
{
transform
:
scale
(
1.05
);
-webkit-transform
:
scale
(
1.05
);
}
80
%
{
transform
:
scale
(
0.95
);
-webkit-transform
:
scale
(
0.95
);
}
100
%
{
transform
:
scale
(
1
);
-webkit-transform
:
scale
(
1
);
}
}
@keyframes
showSweetAlert
{
0
%
{
transform
:
scale
(
0.7
);
-webkit-transform
:
scale
(
0.7
);
}
45
%
{
transform
:
scale
(
1.05
);
-webkit-transform
:
scale
(
1.05
);
}
80
%
{
transform
:
scale
(
0.95
);
-webkit-transform
:
scale
(
0.95
);
}
100
%
{
transform
:
scale
(
1
);
-webkit-transform
:
scale
(
1
);
}
}
@-webkit-keyframes
hideSweetAlert
{
0
%
{
transform
:
scale
(
1
);
-webkit-transform
:
scale
(
1
);
}
100
%
{
transform
:
scale
(
0.5
);
-webkit-transform
:
scale
(
0.5
);
}
}
@keyframes
hideSweetAlert
{
0
%
{
transform
:
scale
(
1
);
-webkit-transform
:
scale
(
1
);
}
100
%
{
transform
:
scale
(
0.5
);
-webkit-transform
:
scale
(
0.5
);
}
}
@-webkit-keyframes
slideFromTop
{
0
%
{
top
:
0%
;
}
100
%
{
top
:
50%
;
}
}
@keyframes
slideFromTop
{
0
%
{
top
:
0%
;
}
100
%
{
top
:
50%
;
}
}
@-webkit-keyframes
slideToTop
{
0
%
{
top
:
50%
;
}
100
%
{
top
:
0%
;
}
}
@keyframes
slideToTop
{
0
%
{
top
:
50%
;
}
100
%
{
top
:
0%
;
}
}
@-webkit-keyframes
slideFromBottom
{
0
%
{
top
:
70%
;
}
100
%
{
top
:
50%
;
}
}
@keyframes
slideFromBottom
{
0
%
{
top
:
70%
;
}
100
%
{
top
:
50%
;
}
}
@-webkit-keyframes
slideToBottom
{
0
%
{
top
:
50%
;
}
100
%
{
top
:
70%
;
}
}
@keyframes
slideToBottom
{
0
%
{
top
:
50%
;
}
100
%
{
top
:
70%
;
}
}
.showSweetAlert
[
data-animation
=
pop
]
{
-webkit-animation
:
showSweetAlert
0.3s
;
animation
:
showSweetAlert
0.3s
;
}
.showSweetAlert
[
data-animation
=
none
]
{
-webkit-animation
:
none
;
animation
:
none
;
}
.showSweetAlert
[
data-animation
=
slide-from-top
]
{
-webkit-animation
:
slideFromTop
0.3s
;
animation
:
slideFromTop
0.3s
;
}
.showSweetAlert
[
data-animation
=
slide-from-bottom
]
{
-webkit-animation
:
slideFromBottom
0.3s
;
animation
:
slideFromBottom
0.3s
;
}
.hideSweetAlert
[
data-animation
=
pop
]
{
-webkit-animation
:
hideSweetAlert
0.2s
;
animation
:
hideSweetAlert
0.2s
;
}
.hideSweetAlert
[
data-animation
=
none
]
{
-webkit-animation
:
none
;
animation
:
none
;
}
.hideSweetAlert
[
data-animation
=
slide-from-top
]
{
-webkit-animation
:
slideToTop
0.4s
;
animation
:
slideToTop
0.4s
;
}
.hideSweetAlert
[
data-animation
=
slide-from-bottom
]
{
-webkit-animation
:
slideToBottom
0.3s
;
animation
:
slideToBottom
0.3s
;
}
@-webkit-keyframes
animateSuccessTip
{
0
%
{
width
:
0
;
left
:
1px
;
top
:
19px
;
}
54
%
{
width
:
0
;
left
:
1px
;
top
:
19px
;
}
70
%
{
width
:
50px
;
left
:
-8px
;
top
:
37px
;
}
84
%
{
width
:
17px
;
left
:
21px
;
top
:
48px
;
}
100
%
{
width
:
25px
;
left
:
14px
;
top
:
45px
;
}
}
@keyframes
animateSuccessTip
{
0
%
{
width
:
0
;
left
:
1px
;
top
:
19px
;
}
54
%
{
width
:
0
;
left
:
1px
;
top
:
19px
;
}
70
%
{
width
:
50px
;
left
:
-8px
;
top
:
37px
;
}
84
%
{
width
:
17px
;
left
:
21px
;
top
:
48px
;
}
100
%
{
width
:
25px
;
left
:
14px
;
top
:
45px
;
}
}
@-webkit-keyframes
animateSuccessLong
{
0
%
{
width
:
0
;
right
:
46px
;
top
:
54px
;
}
65
%
{
width
:
0
;
right
:
46px
;
top
:
54px
;
}
84
%
{
width
:
55px
;
right
:
0px
;
top
:
35px
;
}
100
%
{
width
:
47px
;
right
:
8px
;
top
:
38px
;
}
}
@keyframes
animateSuccessLong
{
0
%
{
width
:
0
;
right
:
46px
;
top
:
54px
;
}
65
%
{
width
:
0
;
right
:
46px
;
top
:
54px
;
}
84
%
{
width
:
55px
;
right
:
0px
;
top
:
35px
;
}
100
%
{
width
:
47px
;
right
:
8px
;
top
:
38px
;
}
}
@-webkit-keyframes
rotatePlaceholder
{
0
%
{
transform
:
rotate
(
-45deg
);
-webkit-transform
:
rotate
(
-45deg
);
}
5
%
{
transform
:
rotate
(
-45deg
);
-webkit-transform
:
rotate
(
-45deg
);
}
12
%
{
transform
:
rotate
(
-405deg
);
-webkit-transform
:
rotate
(
-405deg
);
}
100
%
{
transform
:
rotate
(
-405deg
);
-webkit-transform
:
rotate
(
-405deg
);
}
}
@keyframes
rotatePlaceholder
{
0
%
{
transform
:
rotate
(
-45deg
);
-webkit-transform
:
rotate
(
-45deg
);
}
5
%
{
transform
:
rotate
(
-45deg
);
-webkit-transform
:
rotate
(
-45deg
);
}
12
%
{
transform
:
rotate
(
-405deg
);
-webkit-transform
:
rotate
(
-405deg
);
}
100
%
{
transform
:
rotate
(
-405deg
);
-webkit-transform
:
rotate
(
-405deg
);
}
}
.animateSuccessTip
{
-webkit-animation
:
animateSuccessTip
0.75s
;
animation
:
animateSuccessTip
0.75s
;
}
.animateSuccessLong
{
-webkit-animation
:
animateSuccessLong
0.75s
;
animation
:
animateSuccessLong
0.75s
;
}
.sa-icon.sa-success.animate
::after
{
-webkit-animation
:
rotatePlaceholder
4.25s
ease-in
;
animation
:
rotatePlaceholder
4.25s
ease-in
;
}
@-webkit-keyframes
animateErrorIcon
{
0
%
{
transform
:
rotateX
(
100deg
);
-webkit-transform
:
rotateX
(
100deg
);
opacity
:
0
;
}
100
%
{
transform
:
rotateX
(
0deg
);
-webkit-transform
:
rotateX
(
0deg
);
opacity
:
1
;
}
}
@keyframes
animateErrorIcon
{
0
%
{
transform
:
rotateX
(
100deg
);
-webkit-transform
:
rotateX
(
100deg
);
opacity
:
0
;
}
100
%
{
transform
:
rotateX
(
0deg
);
-webkit-transform
:
rotateX
(
0deg
);
opacity
:
1
;
}
}
.animateErrorIcon
{
-webkit-animation
:
animateErrorIcon
0.5s
;
animation
:
animateErrorIcon
0.5s
;
}
@-webkit-keyframes
animateXMark
{
0
%
{
transform
:
scale
(
0.4
);
-webkit-transform
:
scale
(
0.4
);
margin-top
:
26px
;
opacity
:
0
;
}
50
%
{
transform
:
scale
(
0.4
);
-webkit-transform
:
scale
(
0.4
);
margin-top
:
26px
;
opacity
:
0
;
}
80
%
{
transform
:
scale
(
1.15
);
-webkit-transform
:
scale
(
1.15
);
margin-top
:
-6px
;
}
100
%
{
transform
:
scale
(
1
);
-webkit-transform
:
scale
(
1
);
margin-top
:
0
;
opacity
:
1
;
}
}
@keyframes
animateXMark
{
0
%
{
transform
:
scale
(
0.4
);
-webkit-transform
:
scale
(
0.4
);
margin-top
:
26px
;
opacity
:
0
;
}
50
%
{
transform
:
scale
(
0.4
);
-webkit-transform
:
scale
(
0.4
);
margin-top
:
26px
;
opacity
:
0
;
}
80
%
{
transform
:
scale
(
1.15
);
-webkit-transform
:
scale
(
1.15
);
margin-top
:
-6px
;
}
100
%
{
transform
:
scale
(
1
);
-webkit-transform
:
scale
(
1
);
margin-top
:
0
;
opacity
:
1
;
}
}
.animateXMark
{
-webkit-animation
:
animateXMark
0.5s
;
animation
:
animateXMark
0.5s
;
}
@-webkit-keyframes
pulseWarning
{
0
%
{
border-color
:
#F8D486
;
}
100
%
{
border-color
:
#F8BB86
;
}
}
@keyframes
pulseWarning
{
0
%
{
border-color
:
#F8D486
;
}
100
%
{
border-color
:
#F8BB86
;
}
}
.pulseWarning
{
-webkit-animation
:
pulseWarning
0.75s
infinite
alternate
;
animation
:
pulseWarning
0.75s
infinite
alternate
;
}
@-webkit-keyframes
pulseWarningIns
{
0
%
{
background-color
:
#F8D486
;
}
100
%
{
background-color
:
#F8BB86
;
}
}
@keyframes
pulseWarningIns
{
0
%
{
background-color
:
#F8D486
;
}
100
%
{
background-color
:
#F8BB86
;
}
}
.pulseWarningIns
{
-webkit-animation
:
pulseWarningIns
0.75s
infinite
alternate
;
animation
:
pulseWarningIns
0.75s
infinite
alternate
;
}
/* Internet Explorer 9 has some special quirks that are fixed here */
/* The icons are not animated. */
/* This file is automatically merged into sweet-alert.min.js through Gulp */
/* Error icon */
.sweet-alert
.sa-icon.sa-error
.sa-line.sa-left
{
-ms-transform
:
rotate
(
45deg
)
\
9
;
}
.sweet-alert
.sa-icon.sa-error
.sa-line.sa-right
{
-ms-transform
:
rotate
(
-45deg
)
\
9
;
}
/* Success icon */
.sweet-alert
.sa-icon.sa-success
{
border-color
:
transparent
\
9
;
}
.sweet-alert
.sa-icon.sa-success
.sa-line.sa-tip
{
-ms-transform
:
rotate
(
45deg
)
\
9
;
}
.sweet-alert
.sa-icon.sa-success
.sa-line.sa-long
{
-ms-transform
:
rotate
(
-45deg
)
\
9
;
}
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
!
function
(
e
,
t
,
n
){
"use strict"
;
!
function
o
(
e
,
t
,
n
){
function
a
(
s
,
l
){
if
(
!
t
[
s
]){
if
(
!
e
[
s
]){
var
i
=
"function"
==
typeof
require
&&
require
;
if
(
!
l
&&
i
)
return
i
(
s
,
!
0
);
if
(
r
)
return
r
(
s
,
!
0
);
var
u
=
new
Error
(
"Cannot find module '"
+
s
+
"'"
);
throw
u
.
code
=
"MODULE_NOT_FOUND"
,
u
}
var
c
=
t
[
s
]
=
{
exports
:{}};
e
[
s
][
0
].
call
(
c
.
exports
,
function
(
t
){
var
n
=
e
[
s
][
1
][
t
];
return
a
(
n
?
n
:
t
)},
c
,
c
.
exports
,
o
,
e
,
t
,
n
)}
return
t
[
s
].
exports
}
for
(
var
r
=
"function"
==
typeof
require
&&
require
,
s
=
0
;
s
<
n
.
length
;
s
++
)
a
(
n
[
s
]);
return
a
}({
1
:[
function
(
o
){
var
a
,
r
,
s
,
l
,
i
=
function
(
e
){
return
e
&&
e
.
__esModule
?
e
:{
"default"
:
e
}},
u
=
o
(
"./modules/handle-dom"
),
c
=
o
(
"./modules/utils"
),
d
=
o
(
"./modules/handle-swal-dom"
),
f
=
o
(
"./modules/handle-click"
),
p
=
o
(
"./modules/handle-key"
),
m
=
i
(
p
),
v
=
o
(
"./modules/default-params"
),
y
=
i
(
v
),
h
=
o
(
"./modules/set-params"
),
g
=
i
(
h
);
s
=
l
=
function
(){
function
o
(
e
){
var
t
=
s
;
return
t
[
e
]
===
n
?
y
[
"default"
][
e
]:
t
[
e
]}
var
s
=
arguments
[
0
];
if
(
u
.
addClass
(
t
.
body
,
"stop-scrolling"
),
d
.
resetInput
(),
s
===
n
)
return
c
.
logStr
(
"SweetAlert expects at least 1 attribute!"
),
!
1
;
var
l
=
c
.
extend
({},
y
[
"default"
]);
switch
(
typeof
s
){
case
"string"
:
l
.
title
=
s
,
l
.
text
=
arguments
[
1
]
||
""
,
l
.
type
=
arguments
[
2
]
||
""
;
break
;
case
"object"
:
if
(
s
.
title
===
n
)
return
c
.
logStr
(
'Missing "title" argument!'
),
!
1
;
l
.
title
=
s
.
title
;
for
(
var
i
in
y
[
"default"
])
l
[
i
]
=
o
(
i
);
l
.
confirmButtonText
=
l
.
showCancelButton
?
"Confirm"
:
y
[
"default"
].
confirmButtonText
,
l
.
confirmButtonText
=
o
(
"confirmButtonText"
),
l
.
doneFunction
=
arguments
[
1
]
||
null
;
break
;
default
:
return
c
.
logStr
(
'Unexpected type of argument! Expected "string" or "object", got '
+
typeof
s
),
!
1
}
g
[
"default"
](
l
),
d
.
fixVerticalPosition
(),
d
.
openModal
(
arguments
[
1
]);
for
(
var
p
=
d
.
getModal
(),
v
=
p
.
querySelectorAll
(
"button"
),
h
=
[
"onclick"
,
"onmouseover"
,
"onmouseout"
,
"onmousedown"
,
"onmouseup"
,
"onfocus"
],
b
=
function
(
e
){
return
f
.
handleButton
(
e
,
l
,
p
)},
w
=
0
;
w
<
v
.
length
;
w
++
)
for
(
var
C
=
0
;
C
<
h
.
length
;
C
++
){
var
S
=
h
[
C
];
v
[
w
][
S
]
=
b
}
d
.
getOverlay
().
onclick
=
b
,
a
=
e
.
onkeydown
;
var
x
=
function
(
e
){
return
m
[
"default"
](
e
,
l
,
p
)};
e
.
onkeydown
=
x
,
e
.
onfocus
=
function
(){
setTimeout
(
function
(){
r
!==
n
&&
(
r
.
focus
(),
r
=
n
)},
0
)}},
s
.
setDefaults
=
l
.
setDefaults
=
function
(
e
){
if
(
!
e
)
throw
new
Error
(
"userParams is required"
);
if
(
"object"
!=
typeof
e
)
throw
new
Error
(
"userParams has to be a object"
);
c
.
extend
(
y
[
"default"
],
e
)},
s
.
close
=
l
.
close
=
function
(){
var
o
=
d
.
getModal
();
u
.
fadeOut
(
d
.
getOverlay
(),
5
),
u
.
fadeOut
(
o
,
5
),
u
.
removeClass
(
o
,
"showSweetAlert"
),
u
.
addClass
(
o
,
"hideSweetAlert"
),
u
.
removeClass
(
o
,
"visible"
);
var
s
=
o
.
querySelector
(
".sa-icon.sa-success"
);
u
.
removeClass
(
s
,
"animate"
),
u
.
removeClass
(
s
.
querySelector
(
".sa-tip"
),
"animateSuccessTip"
),
u
.
removeClass
(
s
.
querySelector
(
".sa-long"
),
"animateSuccessLong"
);
var
l
=
o
.
querySelector
(
".sa-icon.sa-error"
);
u
.
removeClass
(
l
,
"animateErrorIcon"
),
u
.
removeClass
(
l
.
querySelector
(
".sa-x-mark"
),
"animateXMark"
);
var
i
=
o
.
querySelector
(
".sa-icon.sa-warning"
);
return
u
.
removeClass
(
i
,
"pulseWarning"
),
u
.
removeClass
(
i
.
querySelector
(
".sa-body"
),
"pulseWarningIns"
),
u
.
removeClass
(
i
.
querySelector
(
".sa-dot"
),
"pulseWarningIns"
),
setTimeout
(
function
(){
var
e
=
o
.
getAttribute
(
"data-custom-class"
);
u
.
removeClass
(
o
,
e
)},
300
),
u
.
removeClass
(
t
.
body
,
"stop-scrolling"
),
e
.
onkeydown
=
a
,
e
.
previousActiveElement
&&
e
.
previousActiveElement
.
focus
(),
r
=
n
,
clearTimeout
(
o
.
timeout
),
!
0
},
s
.
showInputError
=
l
.
showInputError
=
function
(
e
){
var
t
=
d
.
getModal
(),
n
=
t
.
querySelector
(
".sa-input-error"
);
u
.
addClass
(
n
,
"show"
);
var
o
=
t
.
querySelector
(
".sa-error-container"
);
u
.
addClass
(
o
,
"show"
),
o
.
querySelector
(
"p"
).
innerHTML
=
e
,
t
.
querySelector
(
"input"
).
focus
()},
s
.
resetInputError
=
l
.
resetInputError
=
function
(
e
){
if
(
e
&&
13
===
e
.
keyCode
)
return
!
1
;
var
t
=
d
.
getModal
(),
n
=
t
.
querySelector
(
".sa-input-error"
);
u
.
removeClass
(
n
,
"show"
);
var
o
=
t
.
querySelector
(
".sa-error-container"
);
u
.
removeClass
(
o
,
"show"
)},
"undefined"
!=
typeof
e
?
e
.
sweetAlert
=
e
.
swal
=
s
:
c
.
logStr
(
"SweetAlert is a frontend module!"
)},{
"./modules/default-params"
:
2
,
"./modules/handle-click"
:
3
,
"./modules/handle-dom"
:
4
,
"./modules/handle-key"
:
5
,
"./modules/handle-swal-dom"
:
6
,
"./modules/set-params"
:
8
,
"./modules/utils"
:
9
}],
2
:[
function
(
e
,
t
,
n
){
Object
.
defineProperty
(
n
,
"__esModule"
,{
value
:
!
0
});
var
o
=
{
title
:
""
,
text
:
""
,
type
:
null
,
allowOutsideClick
:
!
1
,
showConfirmButton
:
!
0
,
showCancelButton
:
!
1
,
closeOnConfirm
:
!
0
,
closeOnCancel
:
!
0
,
confirmButtonText
:
"OK"
,
confirmButtonColor
:
"#AEDEF4"
,
cancelButtonText
:
"Cancel"
,
imageUrl
:
null
,
imageSize
:
null
,
timer
:
null
,
customClass
:
""
,
html
:
!
1
,
animation
:
!
0
,
allowEscapeKey
:
!
0
,
inputType
:
"text"
,
inputPlaceholder
:
""
,
inputValue
:
""
};
n
[
"default"
]
=
o
,
t
.
exports
=
n
[
"default"
]},{}],
3
:[
function
(
t
,
n
,
o
){
Object
.
defineProperty
(
o
,
"__esModule"
,{
value
:
!
0
});
var
a
=
t
(
"./utils"
),
r
=
(
t
(
"./handle-swal-dom"
),
t
(
"./handle-dom"
)),
s
=
function
(
t
,
n
,
o
){
function
s
(
e
){
m
&&
n
.
confirmButtonColor
&&
(
p
.
style
.
backgroundColor
=
e
)}
var
u
,
c
,
d
,
f
=
t
||
e
.
event
,
p
=
f
.
target
||
f
.
srcElement
,
m
=-
1
!==
p
.
className
.
indexOf
(
"confirm"
),
v
=-
1
!==
p
.
className
.
indexOf
(
"sweet-overlay"
),
y
=
r
.
hasClass
(
o
,
"visible"
),
h
=
n
.
doneFunction
&&
"true"
===
o
.
getAttribute
(
"data-has-done-function"
);
switch
(
m
&&
n
.
confirmButtonColor
&&
(
u
=
n
.
confirmButtonColor
,
c
=
a
.
colorLuminance
(
u
,
-
.
04
),
d
=
a
.
colorLuminance
(
u
,
-
.
14
)),
f
.
type
){
case
"mouseover"
:
s
(
c
);
break
;
case
"mouseout"
:
s
(
u
);
break
;
case
"mousedown"
:
s
(
d
);
break
;
case
"mouseup"
:
s
(
c
);
break
;
case
"focus"
:
var
g
=
o
.
querySelector
(
"button.confirm"
),
b
=
o
.
querySelector
(
"button.cancel"
);
m
?
b
.
style
.
boxShadow
=
"none"
:
g
.
style
.
boxShadow
=
"none"
;
break
;
case
"click"
:
var
w
=
o
===
p
,
C
=
r
.
isDescendant
(
o
,
p
);
if
(
!
w
&&!
C
&&
y
&&!
n
.
allowOutsideClick
)
break
;
m
&&
h
&&
y
?
l
(
o
,
n
):
h
&&
y
||
v
?
i
(
o
,
n
):
r
.
isDescendant
(
o
,
p
)
&&
"BUTTON"
===
p
.
tagName
&&
sweetAlert
.
close
()}},
l
=
function
(
e
,
t
){
var
n
=!
0
;
r
.
hasClass
(
e
,
"show-input"
)
&&
(
n
=
e
.
querySelector
(
"input"
).
value
,
n
||
(
n
=
""
)),
t
.
doneFunction
(
n
),
t
.
closeOnConfirm
&&
sweetAlert
.
close
()},
i
=
function
(
e
,
t
){
var
n
=
String
(
t
.
doneFunction
).
replace
(
/
\s
/g
,
""
),
o
=
"function("
===
n
.
substring
(
0
,
9
)
&&
")"
!==
n
.
substring
(
9
,
10
);
o
&&
t
.
doneFunction
(
!
1
),
t
.
closeOnCancel
&&
sweetAlert
.
close
()};
o
[
"default"
]
=
{
handleButton
:
s
,
handleConfirm
:
l
,
handleCancel
:
i
},
n
.
exports
=
o
[
"default"
]},{
"./handle-dom"
:
4
,
"./handle-swal-dom"
:
6
,
"./utils"
:
9
}],
4
:[
function
(
n
,
o
,
a
){
Object
.
defineProperty
(
a
,
"__esModule"
,{
value
:
!
0
});
var
r
=
function
(
e
,
t
){
return
new
RegExp
(
" "
+
t
+
" "
).
test
(
" "
+
e
.
className
+
" "
)},
s
=
function
(
e
,
t
){
r
(
e
,
t
)
||
(
e
.
className
+=
" "
+
t
)},
l
=
function
(
e
,
t
){
var
n
=
" "
+
e
.
className
.
replace
(
/
[\t\r\n]
/g
,
" "
)
+
" "
;
if
(
r
(
e
,
t
)){
for
(;
n
.
indexOf
(
" "
+
t
+
" "
)
>=
0
;)
n
=
n
.
replace
(
" "
+
t
+
" "
,
" "
);
e
.
className
=
n
.
replace
(
/^
\s
+|
\s
+$/g
,
""
)}},
i
=
function
(
e
){
var
n
=
t
.
createElement
(
"div"
);
return
n
.
appendChild
(
t
.
createTextNode
(
e
)),
n
.
innerHTML
},
u
=
function
(
e
){
e
.
style
.
opacity
=
""
,
e
.
style
.
display
=
"block"
},
c
=
function
(
e
){
if
(
e
&&!
e
.
length
)
return
u
(
e
);
for
(
var
t
=
0
;
t
<
e
.
length
;
++
t
)
u
(
e
[
t
])},
d
=
function
(
e
){
e
.
style
.
opacity
=
""
,
e
.
style
.
display
=
"none"
},
f
=
function
(
e
){
if
(
e
&&!
e
.
length
)
return
d
(
e
);
for
(
var
t
=
0
;
t
<
e
.
length
;
++
t
)
d
(
e
[
t
])},
p
=
function
(
e
,
t
){
for
(
var
n
=
t
.
parentNode
;
null
!==
n
;){
if
(
n
===
e
)
return
!
0
;
n
=
n
.
parentNode
}
return
!
1
},
m
=
function
(
e
){
e
.
style
.
left
=
"-9999px"
,
e
.
style
.
display
=
"block"
;
var
t
,
n
=
e
.
clientHeight
;
return
t
=
"undefined"
!=
typeof
getComputedStyle
?
parseInt
(
getComputedStyle
(
e
).
getPropertyValue
(
"padding-top"
),
10
):
parseInt
(
e
.
currentStyle
.
padding
),
e
.
style
.
left
=
""
,
e
.
style
.
display
=
"none"
,
"-"
+
parseInt
((
n
+
t
)
/
2
)
+
"px"
},
v
=
function
(
e
,
t
){
if
(
+
e
.
style
.
opacity
<
1
){
t
=
t
||
16
,
e
.
style
.
opacity
=
0
,
e
.
style
.
display
=
"block"
;
var
n
=+
new
Date
,
o
=
function
(
e
){
function
t
(){
return
e
.
apply
(
this
,
arguments
)}
return
t
.
toString
=
function
(){
return
e
.
toString
()},
t
}(
function
(){
e
.
style
.
opacity
=+
e
.
style
.
opacity
+
(
new
Date
-
n
)
/
100
,
n
=+
new
Date
,
+
e
.
style
.
opacity
<
1
&&
setTimeout
(
o
,
t
)});
o
()}
e
.
style
.
display
=
"block"
},
y
=
function
(
e
,
t
){
t
=
t
||
16
,
e
.
style
.
opacity
=
1
;
var
n
=+
new
Date
,
o
=
function
(
e
){
function
t
(){
return
e
.
apply
(
this
,
arguments
)}
return
t
.
toString
=
function
(){
return
e
.
toString
()},
t
}(
function
(){
e
.
style
.
opacity
=+
e
.
style
.
opacity
-
(
new
Date
-
n
)
/
100
,
n
=+
new
Date
,
+
e
.
style
.
opacity
>
0
?
setTimeout
(
o
,
t
):
e
.
style
.
display
=
"none"
});
o
()},
h
=
function
(
n
){
if
(
"function"
==
typeof
MouseEvent
){
var
o
=
new
MouseEvent
(
"click"
,{
view
:
e
,
bubbles
:
!
1
,
cancelable
:
!
0
});
n
.
dispatchEvent
(
o
)}
else
if
(
t
.
createEvent
){
var
a
=
t
.
createEvent
(
"MouseEvents"
);
a
.
initEvent
(
"click"
,
!
1
,
!
1
),
n
.
dispatchEvent
(
a
)}
else
t
.
createEventObject
?
n
.
fireEvent
(
"onclick"
):
"function"
==
typeof
n
.
onclick
&&
n
.
onclick
()},
g
=
function
(
t
){
"function"
==
typeof
t
.
stopPropagation
?(
t
.
stopPropagation
(),
t
.
preventDefault
()):
e
.
event
&&
e
.
event
.
hasOwnProperty
(
"cancelBubble"
)
&&
(
e
.
event
.
cancelBubble
=!
0
)};
a
.
hasClass
=
r
,
a
.
addClass
=
s
,
a
.
removeClass
=
l
,
a
.
escapeHtml
=
i
,
a
.
_show
=
u
,
a
.
show
=
c
,
a
.
_hide
=
d
,
a
.
hide
=
f
,
a
.
isDescendant
=
p
,
a
.
getTopMargin
=
m
,
a
.
fadeIn
=
v
,
a
.
fadeOut
=
y
,
a
.
fireClick
=
h
,
a
.
stopEventPropagation
=
g
},{}],
5
:[
function
(
t
,
o
,
a
){
Object
.
defineProperty
(
a
,
"__esModule"
,{
value
:
!
0
});
var
r
=
t
(
"./handle-dom"
),
s
=
t
(
"./handle-swal-dom"
),
l
=
function
(
t
,
o
,
a
){
var
l
=
t
||
e
.
event
,
i
=
l
.
keyCode
||
l
.
which
,
u
=
a
.
querySelector
(
"button.confirm"
),
c
=
a
.
querySelector
(
"button.cancel"
),
d
=
a
.
querySelectorAll
(
"button[tabindex]"
);
if
(
-
1
!==
[
9
,
13
,
32
,
27
].
indexOf
(
i
)){
for
(
var
f
=
l
.
target
||
l
.
srcElement
,
p
=-
1
,
m
=
0
;
m
<
d
.
length
;
m
++
)
if
(
f
===
d
[
m
]){
p
=
m
;
break
}
9
===
i
?(
f
=-
1
===
p
?
u
:
p
===
d
.
length
-
1
?
d
[
0
]:
d
[
p
+
1
],
r
.
stopEventPropagation
(
l
),
f
.
focus
(),
o
.
confirmButtonColor
&&
s
.
setFocusStyle
(
f
,
o
.
confirmButtonColor
)):
13
===
i
?(
"INPUT"
===
f
.
tagName
&&
(
f
=
u
,
u
.
focus
()),
f
=-
1
===
p
?
u
:
n
):
27
===
i
&&
o
.
allowEscapeKey
===!
0
?(
f
=
c
,
r
.
fireClick
(
f
,
l
)):
f
=
n
}};
a
[
"default"
]
=
l
,
o
.
exports
=
a
[
"default"
]},{
"./handle-dom"
:
4
,
"./handle-swal-dom"
:
6
}],
6
:[
function
(
n
,
o
,
a
){
var
r
=
function
(
e
){
return
e
&&
e
.
__esModule
?
e
:{
"default"
:
e
}};
Object
.
defineProperty
(
a
,
"__esModule"
,{
value
:
!
0
});
var
s
=
n
(
"./utils"
),
l
=
n
(
"./handle-dom"
),
i
=
n
(
"./default-params"
),
u
=
r
(
i
),
c
=
n
(
"./injected-html"
),
d
=
r
(
c
),
f
=
".sweet-alert"
,
p
=
".sweet-overlay"
,
m
=
function
(){
var
e
=
t
.
createElement
(
"div"
);
for
(
e
.
innerHTML
=
d
[
"default"
];
e
.
firstChild
;)
t
.
body
.
appendChild
(
e
.
firstChild
)},
v
=
function
(
e
){
function
t
(){
return
e
.
apply
(
this
,
arguments
)}
return
t
.
toString
=
function
(){
return
e
.
toString
()},
t
}(
function
(){
var
e
=
t
.
querySelector
(
f
);
return
e
||
(
m
(),
e
=
v
()),
e
}),
y
=
function
(){
var
e
=
v
();
return
e
?
e
.
querySelector
(
"input"
):
void
0
},
h
=
function
(){
return
t
.
querySelector
(
p
)},
g
=
function
(
e
,
t
){
var
n
=
s
.
hexToRgb
(
t
);
e
.
style
.
boxShadow
=
"0 0 2px rgba("
+
n
+
", 0.8), inset 0 0 0 1px rgba(0, 0, 0, 0.05)"
},
b
=
function
(
n
){
var
o
=
v
();
l
.
fadeIn
(
h
(),
10
),
l
.
show
(
o
),
l
.
addClass
(
o
,
"showSweetAlert"
),
l
.
removeClass
(
o
,
"hideSweetAlert"
),
e
.
previousActiveElement
=
t
.
activeElement
;
var
a
=
o
.
querySelector
(
"button.confirm"
);
a
.
focus
(),
setTimeout
(
function
(){
l
.
addClass
(
o
,
"visible"
)},
500
);
var
r
=
o
.
getAttribute
(
"data-timer"
);
if
(
"null"
!==
r
&&
""
!==
r
){
var
s
=
n
;
o
.
timeout
=
setTimeout
(
function
(){
var
e
=
(
s
||
null
)
&&
"true"
===
o
.
getAttribute
(
"data-has-done-function"
);
e
?
s
(
null
):
sweetAlert
.
close
()},
r
)}},
w
=
function
(){
var
e
=
v
(),
t
=
y
();
l
.
removeClass
(
e
,
"show-input"
),
t
.
value
=
u
[
"default"
].
inputValue
,
t
.
setAttribute
(
"type"
,
u
[
"default"
].
inputType
),
t
.
setAttribute
(
"placeholder"
,
u
[
"default"
].
inputPlaceholder
),
C
()},
C
=
function
(
e
){
if
(
e
&&
13
===
e
.
keyCode
)
return
!
1
;
var
t
=
v
(),
n
=
t
.
querySelector
(
".sa-input-error"
);
l
.
removeClass
(
n
,
"show"
);
var
o
=
t
.
querySelector
(
".sa-error-container"
);
l
.
removeClass
(
o
,
"show"
)},
S
=
function
(){
var
e
=
v
();
e
.
style
.
marginTop
=
l
.
getTopMargin
(
v
())};
a
.
sweetAlertInitialize
=
m
,
a
.
getModal
=
v
,
a
.
getOverlay
=
h
,
a
.
getInput
=
y
,
a
.
setFocusStyle
=
g
,
a
.
openModal
=
b
,
a
.
resetInput
=
w
,
a
.
resetInputError
=
C
,
a
.
fixVerticalPosition
=
S
},{
"./default-params"
:
2
,
"./handle-dom"
:
4
,
"./injected-html"
:
7
,
"./utils"
:
9
}],
7
:[
function
(
e
,
t
,
n
){
Object
.
defineProperty
(
n
,
"__esModule"
,{
value
:
!
0
});
var
o
=
'<div class="sweet-overlay" tabIndex="-1"></div><div class="sweet-alert"><div class="sa-icon sa-error">
\
n <span class="sa-x-mark">
\
n <span class="sa-line sa-left"></span>
\
n <span class="sa-line sa-right"></span>
\
n </span>
\
n </div><div class="sa-icon sa-warning">
\
n <span class="sa-body"></span>
\
n <span class="sa-dot"></span>
\
n </div><div class="sa-icon sa-info"></div><div class="sa-icon sa-success">
\
n <span class="sa-line sa-tip"></span>
\
n <span class="sa-line sa-long"></span>
\
n
\
n <div class="sa-placeholder"></div>
\
n <div class="sa-fix"></div>
\
n </div><div class="sa-icon sa-custom"></div><h2>Title</h2>
\
n <p>Text</p>
\
n <fieldset>
\
n <input type="text" tabIndex="3" />
\
n <div class="sa-input-error"></div>
\
n </fieldset><div class="sa-error-container">
\
n <div class="icon">!</div>
\
n <p>Not valid!</p>
\
n </div><div class="sa-button-container">
\
n <button class="cancel" tabIndex="2">Cancel</button>
\
n <button class="confirm" tabIndex="1">OK</button>
\
n </div></div>'
;
n
[
"default"
]
=
o
,
t
.
exports
=
n
[
"default"
]},{}],
8
:[
function
(
e
,
t
,
o
){
Object
.
defineProperty
(
o
,
"__esModule"
,{
value
:
!
0
});
var
a
=
e
(
"./utils"
),
r
=
e
(
"./handle-swal-dom"
),
s
=
e
(
"./handle-dom"
),
l
=
[
"error"
,
"warning"
,
"info"
,
"success"
,
"input"
,
"prompt"
],
i
=
function
(
e
){
var
t
=
r
.
getModal
(),
o
=
t
.
querySelector
(
"h2"
),
i
=
t
.
querySelector
(
"p"
),
u
=
t
.
querySelector
(
"button.cancel"
),
c
=
t
.
querySelector
(
"button.confirm"
);
if
(
o
.
innerHTML
=
e
.
html
?
e
.
title
:
s
.
escapeHtml
(
e
.
title
).
split
(
"
\n
"
).
join
(
"<br>"
),
i
.
innerHTML
=
e
.
html
?
e
.
text
:
s
.
escapeHtml
(
e
.
text
||
""
).
split
(
"
\n
"
).
join
(
"<br>"
),
e
.
text
&&
s
.
show
(
i
),
e
.
customClass
)
s
.
addClass
(
t
,
e
.
customClass
),
t
.
setAttribute
(
"data-custom-class"
,
e
.
customClass
);
else
{
var
d
=
t
.
getAttribute
(
"data-custom-class"
);
s
.
removeClass
(
t
,
d
),
t
.
setAttribute
(
"data-custom-class"
,
""
)}
if
(
s
.
hide
(
t
.
querySelectorAll
(
".sa-icon"
)),
e
.
type
&&!
a
.
isIE8
()){
var
f
=
function
(){
for
(
var
o
=!
1
,
a
=
0
;
a
<
l
.
length
;
a
++
)
if
(
e
.
type
===
l
[
a
]){
o
=!
0
;
break
}
if
(
!
o
)
return
logStr
(
"Unknown alert type: "
+
e
.
type
),{
v
:
!
1
};
var
i
=
[
"success"
,
"error"
,
"warning"
,
"info"
],
u
=
n
;
-
1
!==
i
.
indexOf
(
e
.
type
)
&&
(
u
=
t
.
querySelector
(
".sa-icon.sa-"
+
e
.
type
),
s
.
show
(
u
));
var
c
=
r
.
getInput
();
switch
(
e
.
type
){
case
"success"
:
s
.
addClass
(
u
,
"animate"
),
s
.
addClass
(
u
.
querySelector
(
".sa-tip"
),
"animateSuccessTip"
),
s
.
addClass
(
u
.
querySelector
(
".sa-long"
),
"animateSuccessLong"
);
break
;
case
"error"
:
s
.
addClass
(
u
,
"animateErrorIcon"
),
s
.
addClass
(
u
.
querySelector
(
".sa-x-mark"
),
"animateXMark"
);
break
;
case
"warning"
:
s
.
addClass
(
u
,
"pulseWarning"
),
s
.
addClass
(
u
.
querySelector
(
".sa-body"
),
"pulseWarningIns"
),
s
.
addClass
(
u
.
querySelector
(
".sa-dot"
),
"pulseWarningIns"
);
break
;
case
"input"
:
case
"prompt"
:
c
.
setAttribute
(
"type"
,
e
.
inputType
),
c
.
value
=
e
.
inputValue
,
c
.
setAttribute
(
"placeholder"
,
e
.
inputPlaceholder
),
s
.
addClass
(
t
,
"show-input"
),
setTimeout
(
function
(){
c
.
focus
(),
c
.
addEventListener
(
"keyup"
,
swal
.
resetInputError
)},
400
)}}();
if
(
"object"
==
typeof
f
)
return
f
.
v
}
if
(
e
.
imageUrl
){
var
p
=
t
.
querySelector
(
".sa-icon.sa-custom"
);
p
.
style
.
backgroundImage
=
"url("
+
e
.
imageUrl
+
")"
,
s
.
show
(
p
);
var
m
=
80
,
v
=
80
;
if
(
e
.
imageSize
){
var
y
=
e
.
imageSize
.
toString
().
split
(
"x"
),
h
=
y
[
0
],
g
=
y
[
1
];
h
&&
g
?(
m
=
h
,
v
=
g
):
logStr
(
"Parameter imageSize expects value with format WIDTHxHEIGHT, got "
+
e
.
imageSize
)}
p
.
setAttribute
(
"style"
,
p
.
getAttribute
(
"style"
)
+
"width:"
+
m
+
"px; height:"
+
v
+
"px"
)}
t
.
setAttribute
(
"data-has-cancel-button"
,
e
.
showCancelButton
),
e
.
showCancelButton
?
u
.
style
.
display
=
"inline-block"
:
s
.
hide
(
u
),
t
.
setAttribute
(
"data-has-confirm-button"
,
e
.
showConfirmButton
),
e
.
showConfirmButton
?
c
.
style
.
display
=
"inline-block"
:
s
.
hide
(
c
),
e
.
cancelButtonText
&&
(
u
.
innerHTML
=
s
.
escapeHtml
(
e
.
cancelButtonText
)),
e
.
confirmButtonText
&&
(
c
.
innerHTML
=
s
.
escapeHtml
(
e
.
confirmButtonText
)),
e
.
confirmButtonColor
&&
(
c
.
style
.
backgroundColor
=
e
.
confirmButtonColor
,
r
.
setFocusStyle
(
c
,
e
.
confirmButtonColor
)),
t
.
setAttribute
(
"data-allow-outside-click"
,
e
.
allowOutsideClick
);
var
b
=
e
.
doneFunction
?
!
0
:
!
1
;
t
.
setAttribute
(
"data-has-done-function"
,
b
),
e
.
animation
?
"string"
==
typeof
e
.
animation
?
t
.
setAttribute
(
"data-animation"
,
e
.
animation
):
t
.
setAttribute
(
"data-animation"
,
"pop"
):
t
.
setAttribute
(
"data-animation"
,
"none"
),
t
.
setAttribute
(
"data-timer"
,
e
.
timer
)};
o
[
"default"
]
=
i
,
t
.
exports
=
o
[
"default"
]},{
"./handle-dom"
:
4
,
"./handle-swal-dom"
:
6
,
"./utils"
:
9
}],
9
:[
function
(
t
,
n
,
o
){
Object
.
defineProperty
(
o
,
"__esModule"
,{
value
:
!
0
});
var
a
=
function
(
e
,
t
){
for
(
var
n
in
t
)
t
.
hasOwnProperty
(
n
)
&&
(
e
[
n
]
=
t
[
n
]);
return
e
},
r
=
function
(
e
){
var
t
=
/^#
?([
a-f
\d]{2})([
a-f
\d]{2})([
a-f
\d]{2})
$/i
.
exec
(
e
);
return
t
?
parseInt
(
t
[
1
],
16
)
+
", "
+
parseInt
(
t
[
2
],
16
)
+
", "
+
parseInt
(
t
[
3
],
16
):
null
},
s
=
function
(){
return
e
.
attachEvent
&&!
e
.
addEventListener
},
l
=
function
(
t
){
e
.
console
&&
e
.
console
.
log
(
"SweetAlert: "
+
t
)},
i
=
function
(
e
,
t
){
e
=
String
(
e
).
replace
(
/
[^
0-9a-f
]
/gi
,
""
),
e
.
length
<
6
&&
(
e
=
e
[
0
]
+
e
[
0
]
+
e
[
1
]
+
e
[
1
]
+
e
[
2
]
+
e
[
2
]),
t
=
t
||
0
;
var
n
,
o
,
a
=
"#"
;
for
(
o
=
0
;
3
>
o
;
o
++
)
n
=
parseInt
(
e
.
substr
(
2
*
o
,
2
),
16
),
n
=
Math
.
round
(
Math
.
min
(
Math
.
max
(
0
,
n
+
n
*
t
),
255
)).
toString
(
16
),
a
+=
(
"00"
+
n
).
substr
(
n
.
length
);
return
a
};
o
.
extend
=
a
,
o
.
hexToRgb
=
r
,
o
.
isIE8
=
s
,
o
.
logStr
=
l
,
o
.
colorLuminance
=
i
},{}]},{},[
1
]),
"function"
==
typeof
define
&&
define
.
amd
?
define
(
function
(){
return
sweetAlert
}):
"undefined"
!=
typeof
module
&&
module
.
exports
&&
(
module
.
exports
=
sweetAlert
)}(
window
,
document
);
\ No newline at end of file
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