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
a04d7725
Commit
a04d7725
authored
8 years ago
by
ibuler
Browse files
Options
Browse Files
Download
Plain Diff
Merge with master
parents
820d608b
f9b49605
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
779 additions
and
178 deletions
+779
-178
jumpserver.css
apps/static/css/jumpserver.css
+117
-0
awesome-bootstrap-checkbox.css
...awesome-bootstrap-checkbox/awesome-bootstrap-checkbox.css
+251
-0
select2.min.css
apps/static/css/plugins/select2/select2.min.css
+0
-0
jumpserver.js
apps/static/js/jumpserver.js
+107
-3
select2.full.min.js
apps/static/js/plugins/select2/select2.full.min.js
+0
-0
_base_list.html
apps/templates/_base_list.html
+3
-0
_head_css_js.html
apps/templates/_head_css_js.html
+0
-8
_modal.html
apps/templates/_modal.html
+2
-2
api.py
apps/users/api.py
+25
-12
models.py
apps/users/models.py
+9
-5
serializers.py
apps/users/serializers.py
+3
-2
_select_user_modal.html
apps/users/templates/users/_select_user_modal.html
+23
-0
_user_bulk_update_modal.html
apps/users/templates/users/_user_bulk_update_modal.html
+37
-0
user_detail.html
apps/users/templates/users/user_detail.html
+2
-2
user_group_detail.html
apps/users/templates/users/user_group_detail.html
+108
-30
user_group_list.html
apps/users/templates/users/user_group_list.html
+1
-1
user_list.html
apps/users/templates/users/user_list.html
+82
-68
urls.py
apps/users/urls.py
+6
-5
utils.py
apps/users/utils.py
+0
-1
views.py
apps/users/views.py
+3
-39
No files found.
apps/static/css/jumpserver.css
View file @
a04d7725
...
...
@@ -78,4 +78,121 @@ th a {
border-top
:
none
!important
;
}
table
.dataTable
tbody
>
tr
.selected
,
table
.dataTable
tbody
>
tr
>
.selected
{
background-color
:
#1ab394
;
}
table
.dataTable
tbody
tr
.selected
a
,
table
.dataTable
tbody
th
.selected
a
,
table
.dataTable
tbody
td
.selected
a
,
table
.dataTable
tbody
tr
.selected
td
i
.text-navy
,
table
.dataTable
tbody
th
.selected
td
i
.text-navy
,
table
.dataTable
tbody
td
.selected
td
i
.text-navy
{
color
:
white
;
}
.m-0
{
margin
:
0px
!important
;
}
.m-t-0
{
margin-top
:
0px
!important
;
}
.m-b-0
{
margin-bottom
:
0px
!important
;
}
.m-l-0
{
margin-left
:
0px
!important
;
}
.m-r-0
{
margin-right
:
0px
!important
;
}
.m-5
{
margin
:
5px
!important
;
}
.m-t-5
{
margin-top
:
5px
!important
;
}
.m-b-5
{
margin-bottom
:
5px
!important
;
}
.m-l-5
{
margin-left
:
5px
!important
;
}
.m-r-5
{
margin-right
:
5px
!important
;
}
.m-10
{
margin
:
10px
!important
;
}
.m-t-10
{
margin-top
:
10px
!important
;
}
.m-b-10
{
margin-bottom
:
10px
!important
;
}
.m-l-10
{
margin-left
:
10px
!important
;
}
.m-r-10
{
margin-right
:
10px
!important
;
}
.m-15
{
margin
:
15px
!important
;
}
.m-t-15
{
margin-top
:
15px
!important
;
}
.m-b-15
{
margin-bottom
:
15px
!important
;
}
.m-l-15
{
margin-left
:
15px
!important
;
}
.m-r-15
{
margin-right
:
15px
!important
;
}
.m-20
{
margin
:
20px
!important
;
}
.m-t-20
{
margin-top
:
20px
!important
;
}
.m-b-20
{
margin-bottom
:
20px
!important
;
}
.m-l-20
{
margin-left
:
20px
!important
;
}
.m-r-20
{
margin-right
:
20px
!important
;
}
.m-25
{
margin
:
25px
!important
;
}
.m-t-25
{
margin-top
:
25px
!important
;
}
.m-b-25
{
margin-bottom
:
25px
!important
;
}
.m-l-25
{
margin-left
:
25px
!important
;
}
.m-r-25
{
margin-right
:
25px
!important
;
}
.m-30
{
margin
:
30px
!important
;
}
.m-t-30
{
margin-top
:
30px
!important
;
}
.m-b-30
{
margin-bottom
:
30px
!important
;
}
.m-l-30
{
margin-left
:
30px
!important
;
}
.m-r-30
{
margin-right
:
30px
!important
;
}
This diff is collapsed.
Click to expand it.
apps/static/css/plugins/awesome-bootstrap-checkbox/awesome-bootstrap-checkbox.css
0 → 100644
View file @
a04d7725
.checkbox
{
padding-left
:
20px
;
}
.checkbox
label
{
display
:
inline-block
;
vertical-align
:
middle
;
position
:
relative
;
padding-left
:
5px
;
}
.checkbox
label
::before
{
content
:
""
;
display
:
inline-block
;
position
:
absolute
;
width
:
17px
;
height
:
17px
;
left
:
0
;
margin-left
:
-20px
;
border
:
1px
solid
#cccccc
;
border-radius
:
3px
;
background-color
:
#fff
;
-webkit-transition
:
border
0.15s
ease-in-out
,
color
0.15s
ease-in-out
;
-o-transition
:
border
0.15s
ease-in-out
,
color
0.15s
ease-in-out
;
transition
:
border
0.15s
ease-in-out
,
color
0.15s
ease-in-out
;
}
.checkbox
label
::after
{
display
:
inline-block
;
position
:
absolute
;
width
:
16px
;
height
:
16px
;
left
:
0
;
top
:
0
;
margin-left
:
-20px
;
padding-left
:
3px
;
padding-top
:
1px
;
font-size
:
11px
;
color
:
#555555
;
}
.checkbox
input
[
type
=
"checkbox"
],
.checkbox
input
[
type
=
"radio"
]
{
opacity
:
0
;
z-index
:
1
;
}
.checkbox
input
[
type
=
"checkbox"
]
:focus
+
label
::before
,
.checkbox
input
[
type
=
"radio"
]
:focus
+
label
::before
{
outline
:
thin
dotted
;
outline
:
5px
auto
-webkit-focus-ring-color
;
outline-offset
:
-2px
;
}
.checkbox
input
[
type
=
"checkbox"
]
:checked
+
label
::after
,
.checkbox
input
[
type
=
"radio"
]
:checked
+
label
::after
{
font-family
:
"FontAwesome"
;
content
:
"\f00c"
;
}
.checkbox
input
[
type
=
"checkbox"
]
:disabled
+
label
,
.checkbox
input
[
type
=
"radio"
]
:disabled
+
label
{
opacity
:
0.65
;
}
.checkbox
input
[
type
=
"checkbox"
]
:disabled
+
label
::before
,
.checkbox
input
[
type
=
"radio"
]
:disabled
+
label
::before
{
background-color
:
#eeeeee
;
cursor
:
not-allowed
;
}
.checkbox.checkbox-circle
label
::before
{
border-radius
:
50%
;
}
.checkbox.checkbox-inline
{
margin-top
:
0
;
}
.checkbox-primary
input
[
type
=
"checkbox"
]
:checked
+
label
::before
,
.checkbox-primary
input
[
type
=
"radio"
]
:checked
+
label
::before
{
background-color
:
#337ab7
;
border-color
:
#337ab7
;
}
.checkbox-primary
input
[
type
=
"checkbox"
]
:checked
+
label
::after
,
.checkbox-primary
input
[
type
=
"radio"
]
:checked
+
label
::after
{
color
:
#fff
;
}
.checkbox-danger
input
[
type
=
"checkbox"
]
:checked
+
label
::before
,
.checkbox-danger
input
[
type
=
"radio"
]
:checked
+
label
::before
{
background-color
:
#d9534f
;
border-color
:
#d9534f
;
}
.checkbox-danger
input
[
type
=
"checkbox"
]
:checked
+
label
::after
,
.checkbox-danger
input
[
type
=
"radio"
]
:checked
+
label
::after
{
color
:
#fff
;
}
.checkbox-info
input
[
type
=
"checkbox"
]
:checked
+
label
::before
,
.checkbox-info
input
[
type
=
"radio"
]
:checked
+
label
::before
{
background-color
:
#5bc0de
;
border-color
:
#5bc0de
;
}
.checkbox-info
input
[
type
=
"checkbox"
]
:checked
+
label
::after
,
.checkbox-info
input
[
type
=
"radio"
]
:checked
+
label
::after
{
color
:
#fff
;
}
.checkbox-warning
input
[
type
=
"checkbox"
]
:checked
+
label
::before
,
.checkbox-warning
input
[
type
=
"radio"
]
:checked
+
label
::before
{
background-color
:
#f0ad4e
;
border-color
:
#f0ad4e
;
}
.checkbox-warning
input
[
type
=
"checkbox"
]
:checked
+
label
::after
,
.checkbox-warning
input
[
type
=
"radio"
]
:checked
+
label
::after
{
color
:
#fff
;
}
.checkbox-success
input
[
type
=
"checkbox"
]
:checked
+
label
::before
,
.checkbox-success
input
[
type
=
"radio"
]
:checked
+
label
::before
{
background-color
:
#5cb85c
;
border-color
:
#5cb85c
;
}
.checkbox-success
input
[
type
=
"checkbox"
]
:checked
+
label
::after
,
.checkbox-success
input
[
type
=
"radio"
]
:checked
+
label
::after
{
color
:
#fff
;
}
.radio
{
padding-left
:
20px
;
}
.radio
label
{
display
:
inline-block
;
vertical-align
:
middle
;
position
:
relative
;
padding-left
:
5px
;
}
.radio
label
::before
{
content
:
""
;
display
:
inline-block
;
position
:
absolute
;
width
:
17px
;
height
:
17px
;
left
:
0
;
margin-left
:
-20px
;
border
:
1px
solid
#cccccc
;
border-radius
:
50%
;
background-color
:
#fff
;
-webkit-transition
:
border
0.15s
ease-in-out
;
-o-transition
:
border
0.15s
ease-in-out
;
transition
:
border
0.15s
ease-in-out
;
}
.radio
label
::after
{
display
:
inline-block
;
position
:
absolute
;
content
:
" "
;
width
:
11px
;
height
:
11px
;
left
:
3px
;
top
:
3px
;
margin-left
:
-20px
;
border-radius
:
50%
;
background-color
:
#555555
;
-webkit-transform
:
scale
(
0
,
0
);
-ms-transform
:
scale
(
0
,
0
);
-o-transform
:
scale
(
0
,
0
);
transform
:
scale
(
0
,
0
);
-webkit-transition
:
-webkit-transform
0.1s
cubic-bezier
(
0.8
,
-0.33
,
0.2
,
1.33
);
-moz-transition
:
-moz-transform
0.1s
cubic-bezier
(
0.8
,
-0.33
,
0.2
,
1.33
);
-o-transition
:
-o-transform
0.1s
cubic-bezier
(
0.8
,
-0.33
,
0.2
,
1.33
);
transition
:
transform
0.1s
cubic-bezier
(
0.8
,
-0.33
,
0.2
,
1.33
);
}
.radio
input
[
type
=
"radio"
]
{
opacity
:
0
;
z-index
:
1
;
}
.radio
input
[
type
=
"radio"
]
:focus
+
label
::before
{
outline
:
thin
dotted
;
outline
:
5px
auto
-webkit-focus-ring-color
;
outline-offset
:
-2px
;
}
.radio
input
[
type
=
"radio"
]
:checked
+
label
::after
{
-webkit-transform
:
scale
(
1
,
1
);
-ms-transform
:
scale
(
1
,
1
);
-o-transform
:
scale
(
1
,
1
);
transform
:
scale
(
1
,
1
);
}
.radio
input
[
type
=
"radio"
]
:disabled
+
label
{
opacity
:
0.65
;
}
.radio
input
[
type
=
"radio"
]
:disabled
+
label
::before
{
cursor
:
not-allowed
;
}
.radio.radio-inline
{
margin-top
:
0
;
}
.radio-primary
input
[
type
=
"radio"
]
+
label
::after
{
background-color
:
#337ab7
;
}
.radio-primary
input
[
type
=
"radio"
]
:checked
+
label
::before
{
border-color
:
#337ab7
;
}
.radio-primary
input
[
type
=
"radio"
]
:checked
+
label
::after
{
background-color
:
#337ab7
;
}
.radio-danger
input
[
type
=
"radio"
]
+
label
::after
{
background-color
:
#d9534f
;
}
.radio-danger
input
[
type
=
"radio"
]
:checked
+
label
::before
{
border-color
:
#d9534f
;
}
.radio-danger
input
[
type
=
"radio"
]
:checked
+
label
::after
{
background-color
:
#d9534f
;
}
.radio-info
input
[
type
=
"radio"
]
+
label
::after
{
background-color
:
#5bc0de
;
}
.radio-info
input
[
type
=
"radio"
]
:checked
+
label
::before
{
border-color
:
#5bc0de
;
}
.radio-info
input
[
type
=
"radio"
]
:checked
+
label
::after
{
background-color
:
#5bc0de
;
}
.radio-warning
input
[
type
=
"radio"
]
+
label
::after
{
background-color
:
#f0ad4e
;
}
.radio-warning
input
[
type
=
"radio"
]
:checked
+
label
::before
{
border-color
:
#f0ad4e
;
}
.radio-warning
input
[
type
=
"radio"
]
:checked
+
label
::after
{
background-color
:
#f0ad4e
;
}
.radio-success
input
[
type
=
"radio"
]
+
label
::after
{
background-color
:
#5cb85c
;
}
.radio-success
input
[
type
=
"radio"
]
:checked
+
label
::before
{
border-color
:
#5cb85c
;
}
.radio-success
input
[
type
=
"radio"
]
:checked
+
label
::after
{
background-color
:
#5cb85c
;
}
input
[
type
=
"checkbox"
]
.styled
:checked
+
label
:after
,
input
[
type
=
"radio"
]
.styled
:checked
+
label
:after
{
font-family
:
'FontAwesome'
;
content
:
"\f00c"
;
}
input
[
type
=
"checkbox"
]
.styled
:checked
+
label
::before
,
input
[
type
=
"radio"
]
.styled
:checked
+
label
::before
{
color
:
#fff
;
}
input
[
type
=
"checkbox"
]
.styled
:checked
+
label
::after
,
input
[
type
=
"radio"
]
.styled
:checked
+
label
::after
{
color
:
#fff
;
}
This diff is collapsed.
Click to expand it.
apps/static/css/plugins/select2/select2.min.css
View file @
a04d7725
This diff is collapsed.
Click to expand it.
apps/static/js/jumpserver.js
View file @
a04d7725
...
...
@@ -178,8 +178,8 @@ function activeNav() {
var
url_array
=
document
.
location
.
pathname
.
split
(
"/"
);
var
app
=
url_array
[
1
];
var
resource
=
url_array
[
2
];
if
(
app
==
''
){
$
(
'#index'
).
addClass
(
'active'
)
if
(
app
==
=
''
){
$
(
'#index'
).
addClass
(
'active'
)
;
}
else
{
$
(
"#"
+
app
).
addClass
(
'active'
);
$
(
'#'
+
app
+
' #'
+
resource
).
addClass
(
'active'
);
...
...
@@ -236,8 +236,112 @@ function objectDelete(obj, name, url){
swal
(
'Deleted!'
,
"【"
+
name
+
"】"
+
"has been deleted."
,
"success"
);
$
(
obj
).
parent
().
parent
().
remove
();
}
})
})
;
});
}
$
.
fn
.
serializeObject
=
function
()
{
var
o
=
{};
var
a
=
this
.
serializeArray
();
$
.
each
(
a
,
function
()
{
if
(
o
[
this
.
name
]
!==
undefined
)
{
if
(
!
o
[
this
.
name
].
push
)
{
o
[
this
.
name
]
=
[
o
[
this
.
name
]];
}
o
[
this
.
name
].
push
(
this
.
value
||
''
);
}
else
{
o
[
this
.
name
]
=
this
.
value
||
''
;
}
});
return
o
;
};
var
jumpserver
=
{};
jumpserver
.
checked
=
false
;
jumpserver
.
initDataTable
=
function
(
options
)
{
// options = {
// ele *: $('#dataTable_id'),
// ajax_url *: '{% url 'users:user-list-api' %}',
// columns *: [{data: ''}, ....],
// dom: 'fltip',
// i18n_url: '{% static "js/...../en-us.json" %}',
// order: [[1, 'asc'], [2, 'asc'], ...],
// buttons: ['excel', 'pdf', 'print'],
// columnDefs: [{target: 0, createdCell: ()=>{}}, ...],
// uc_html: '<a>header button</a>',
// op_html: 'div.btn-group?'
// }
var
ele
=
options
.
ele
||
$
(
'.dataTable'
);
var
columnDefs
=
[
{
targets
:
0
,
orderable
:
false
,
createdCell
:
function
(
td
)
{
$
(
td
).
html
(
'<div class="checkbox checkbox-default"><input type="checkbox" class="ipt_check"><label></label></div>'
);
}
},
{
className
:
'text-center'
,
targets
:
'_all'
},
];
columnDefs
=
options
.
columnDefs
?
options
.
columnDefs
.
concat
(
columnDefs
)
:
columnDefs
;
var
table
=
ele
.
DataTable
({
pageLength
:
options
.
pageLength
||
25
,
dom
:
options
.
dom
||
'<"#uc.pull-left"><"html5buttons"B>flti<"row m-t"<"#op.col-md-6"><"col-md-6"p>>'
,
language
:
{
url
:
options
.
i18n_url
||
"/static/js/plugins/dataTables/i18n/zh-hans.json"
},
order
:
options
.
order
||
[[
1
,
'asc'
]],
buttons
:
options
.
buttons
||
[
{
extend
:
'excel'
,
exportOptions
:
{
modifier
:
{
selected
:
true
}
}
},
{
extend
:
'pdf'
,
exportOptions
:
{
modifier
:
{
selected
:
true
}
}
},
{
extend
:
'print'
,
customize
:
function
(
win
){
$
(
win
.
document
.
body
).
addClass
(
'white-bg'
);
$
(
win
.
document
.
body
).
css
(
'font-size'
,
'10px'
);
$
(
win
.
document
.
body
).
find
(
'table'
)
.
addClass
(
'compact'
)
.
css
(
'font-size'
,
'inherit'
);
}
}
],
columnDefs
:
columnDefs
,
select
:
options
.
select
||
{
style
:
'multi'
},
ajax
:
{
url
:
options
.
ajax_url
,
dataSrc
:
""
},
columns
:
options
.
columns
||
[]
});
table
.
on
(
'select'
,
function
(
e
,
dt
,
type
,
indexes
)
{
var
$node
=
table
[
type
](
indexes
).
nodes
().
to$
();
$node
.
find
(
'input.ipt_check'
).
prop
(
'checked'
,
true
);
}).
on
(
'deselect'
,
function
(
e
,
dt
,
type
,
indexes
)
{
var
$node
=
table
[
type
](
indexes
).
nodes
().
to$
();
$node
.
find
(
'input.ipt_check'
).
prop
(
'checked'
,
false
);
}).
on
(
'draw'
,
function
(){
$
(
'#op'
).
html
(
options
.
op_html
||
''
);
$
(
'#uc'
).
html
(
options
.
uc_html
||
''
);
});
$
(
'.ipt_check_all'
).
on
(
'click'
,
function
()
{
if
(
!
jumpserver
.
checked
)
{
$
(
this
).
closest
(
'table'
).
find
(
'.ipt_check'
).
prop
(
'checked'
,
true
);
jumpserver
.
checked
=
true
;
table
.
rows
().
select
();
}
else
{
$
(
this
).
closest
(
'table'
).
find
(
'.ipt_check'
).
prop
(
'checked'
,
false
);
jumpserver
.
checked
=
false
;
table
.
rows
().
deselect
();
}
})
return
table
;
}
This diff is collapsed.
Click to expand it.
apps/static/js/plugins/select2/select2.full.min.js
View file @
a04d7725
This source diff could not be displayed because it is too large. You can
view the blob
instead.
This diff is collapsed.
Click to expand it.
apps/templates/_base_list.html
View file @
a04d7725
...
...
@@ -3,6 +3,9 @@
{% load common_tags %}
{% block custom_head_css_js %}
<link
href=
"{% static "
css
/
plugins
/
dataTables
/
dataTables
.
min
.
css
"
%}"
rel=
"stylesheet"
>
<link
href=
"{% static "
css
/
plugins
/
awesome-bootstrap-checkbox
/
awesome-bootstrap-checkbox
.
css
"
%}"
rel=
"stylesheet"
>
<link
href=
"{% static "
css
/
plugins
/
select2
/
select2
.
min
.
css
"
%}"
rel=
"stylesheet"
>
<script
src=
"{% static "
js
/
plugins
/
select2
/
select2
.
full
.
min
.
js
"
%}"
></script>
<script
src=
"{% static "
js
/
plugins
/
dataTables
/
dataTables
.
min
.
js
"
%}"
></script>
{% endblock %}
{% block content %}
...
...
This diff is collapsed.
Click to expand it.
apps/templates/_head_css_js.html
View file @
a04d7725
...
...
@@ -7,17 +7,9 @@
<link
href=
"{% static "
css
/
plugins
/
sweetalert
/
sweetalert
.
css
"
%}"
rel=
"stylesheet"
>
<link
href=
"{% static "
css
/
style
.
css
"
%}"
rel=
"stylesheet"
>
<link
href=
"{% static "
css
/
plugins
/
vaildator
/
jquery
.
validator
.
css
"
%}"
rel=
"stylesheet"
>
<!-- scripts -->
<script
src=
"{% static 'js/jquery-2.1.1.js' %}"
></script>
<!-- Sweet alert -->
<script
src=
"{% static 'js/plugins/sweetalert/sweetalert.min.js' %}"
></script>
<script
src=
"{% static 'js/bootstrap.min.js' %}"
></script>
This diff is collapsed.
Click to expand it.
apps/templates/_modal.html
View file @
a04d7725
{% 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
aria-hidden=
"true"
role=
"dialog"
id=
"{% block modal_id %}{% endblock %}"
class=
"modal inmodal
"
>
<div
class=
"modal-dialog
{% block modal_class %}{% endblock %}
"
>
<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>
...
...
This diff is collapsed.
Click to expand it.
apps/users/api.py
View file @
a04d7725
...
...
@@ -3,10 +3,13 @@
import
logging
from
rest_framework
import
generics
from
django.shortcuts
import
get_object_or_404
from
rest_framework
import
generics
,
status
from
rest_framework.response
import
Response
from
rest_framework_bulk
import
ListBulkCreateUpdateDestroyAPIView
from
.serializers
import
UserSerializer
,
UserGroupSerializer
,
UserAttributeSerializer
,
UserGroup
EditSerializer
,
\
from
.serializers
import
UserSerializer
,
UserGroupSerializer
,
UserAttributeSerializer
,
GroupUser
EditSerializer
,
\
GroupEditSerializer
,
UserPKUpdateSerializer
,
UserBulkUpdateSerializer
from
.models
import
User
,
UserGroup
...
...
@@ -27,11 +30,6 @@ class UserDetailDeleteUpdateApi(generics.RetrieveUpdateDestroyAPIView):
print
(
self
.
request
.
data
)
return
super
(
UserDetailDeleteUpdateApi
,
self
)
.
delete
(
request
,
*
args
,
**
kwargs
)
# def get(self, request, *args, **kwargs):
# print("hello world")
# print(request.user)
# return super(UserDetailDeleteUpdateApi, self).get(request, *args, **kwargs)
class
UserGroupListAddApi
(
generics
.
ListCreateAPIView
):
queryset
=
UserGroup
.
objects
.
all
()
...
...
@@ -48,14 +46,14 @@ class UserAttributeApi(generics.RetrieveUpdateDestroyAPIView):
serializer_class
=
UserAttributeSerializer
class
UserGroup
EditApi
(
generics
.
RetrieveUpdateAPIView
):
class
GroupUser
EditApi
(
generics
.
RetrieveUpdateAPIView
):
queryset
=
User
.
objects
.
all
()
serializer_class
=
UserGroup
EditSerializer
serializer_class
=
GroupUser
EditSerializer
class
UserResetPasswordApi
(
generics
.
UpdateAPIView
):
queryset
=
User
.
objects
.
all
()
serializer_class
=
UserGroup
EditSerializer
serializer_class
=
GroupUser
EditSerializer
def
perform_update
(
self
,
serializer
):
# Note: we are not updating the user object here.
...
...
@@ -70,7 +68,7 @@ class UserResetPasswordApi(generics.UpdateAPIView):
class
UserResetPKApi
(
generics
.
UpdateAPIView
):
queryset
=
User
.
objects
.
all
()
serializer_class
=
UserGroup
EditSerializer
serializer_class
=
GroupUser
EditSerializer
def
perform_update
(
self
,
serializer
):
user
=
self
.
get_object
()
...
...
@@ -90,7 +88,7 @@ class UserUpdatePKApi(generics.UpdateAPIView):
user
.
save
()
class
Group
DeleteApi
(
generics
.
DestroyAPIView
):
class
Group
EditApi
(
generics
.
RetrieveUpdate
DestroyAPIView
):
queryset
=
UserGroup
.
objects
.
all
()
serializer_class
=
GroupEditSerializer
...
...
@@ -111,3 +109,18 @@ class UserBulkUpdateApi(ListBulkCreateUpdateDestroyAPIView):
if
isinstance
(
ids
,
list
):
queryset
=
queryset
.
filter
(
id__in
=
ids
)
return
queryset
class
DeleteUserFromGroupApi
(
generics
.
DestroyAPIView
):
queryset
=
UserGroup
.
objects
.
all
()
serializer_class
=
GroupEditSerializer
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
)
This diff is collapsed.
Click to expand it.
apps/users/models.py
View file @
a04d7725
...
...
@@ -4,14 +4,14 @@ from __future__ import unicode_literals
from
django.conf
import
settings
from
django.contrib.auth.hashers
import
make_password
from
django.utils
import
timezone
from
django.db
import
models
from
django.contrib.auth.models
import
AbstractUser
from
django.core
import
signing
from
django.db
import
models
,
IntegrityError
from
django.db.models.signals
import
post_save
from
django.dispatch
import
receiver
from
django.db
import
IntegrityError
from
django.utils.translation
import
ugettext_lazy
as
_
from
django.core
import
signing
from
django.utils
import
timezone
from
django.shortcuts
import
reverse
from
rest_framework.authtoken.models
import
Token
...
...
@@ -102,6 +102,9 @@ class User(AbstractUser):
def
password_raw
(
self
,
password_raw_
):
self
.
set_password
(
password_raw_
)
def
get_absolute_url
(
self
):
return
reverse
(
'users:user-detail'
,
args
=
(
self
.
id
,))
@property
def
is_expired
(
self
):
if
self
.
date_expired
>
timezone
.
now
():
...
...
@@ -162,6 +165,7 @@ class User(AbstractUser):
super
(
User
,
self
)
.
save
(
*
args
,
**
kwargs
)
# Add the current user to the default group.
if
not
self
.
groups
.
count
():
group
=
UserGroup
.
initial
()
self
.
groups
.
add
(
group
)
...
...
@@ -222,7 +226,7 @@ class User(AbstractUser):
user
.
groups
.
add
(
UserGroup
.
initial
())
def
delete
(
self
):
if
self
.
is_superuser
:
if
self
.
pk
==
1
:
return
return
super
(
User
,
self
)
.
delete
()
...
...
This diff is collapsed.
Click to expand it.
apps/users/serializers.py
View file @
a04d7725
...
...
@@ -31,7 +31,7 @@ class GroupEditSerializer(serializers.ModelSerializer):
class
Meta
:
model
=
UserGroup
fields
=
[
'id'
,
'name'
,
'comment'
,
'date_created'
,
'created_by'
]
fields
=
[
'id'
,
'name'
,
'comment'
,
'date_created'
,
'created_by'
,
'users'
]
class
UserAttributeSerializer
(
serializers
.
ModelSerializer
):
...
...
@@ -41,7 +41,7 @@ class UserAttributeSerializer(serializers.ModelSerializer):
fields
=
[
'avatar'
,
'wechat'
,
'phone'
,
'enable_otp'
,
'comment'
,
'is_active'
,
'name'
]
class
UserGroup
EditSerializer
(
serializers
.
ModelSerializer
):
class
GroupUser
EditSerializer
(
serializers
.
ModelSerializer
):
groups
=
serializers
.
PrimaryKeyRelatedField
(
many
=
True
,
queryset
=
UserGroup
.
objects
.
all
())
class
Meta
:
...
...
@@ -73,6 +73,7 @@ class UserPKUpdateSerializer(serializers.ModelSerializer):
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
...
...
This diff is collapsed.
Click to expand it.
apps/users/templates/users/_select_user_modal.html
0 → 100644
View file @
a04d7725
{% extends '_modal.html' %}
{% load i18n %}
{% block modal_class %}modal-lg{% endblock %}
{% block modal_id %}select_user_modal{% endblock %}
{% block modal_title%}{% trans "Please Select User" %}{% endblock %}
{% block modal_body %}
<table
class=
"table table-striped table-bordered table-hover "
id=
"select_user_table"
>
<thead>
<tr>
<th
class=
"text-center"
>
<div
class=
"checkbox checkbox-default"
><input
id=
""
type=
"checkbox"
class=
"ipt_check_all"
><label></label></div>
</th>
<th
class=
"text-center"
>
{% trans 'Name' %}
</a></th>
<th
class=
"text-center"
>
{% trans 'Username' %}
</a></th>
<th
class=
"text-center"
>
{% trans 'Role' %}
</th>
<th
class=
"text-center"
>
{% trans 'User group' %}
</th>
<th
class=
"text-center"
>
{% trans 'Asset num' %}
</th>
<th
class=
"text-center"
>
{% trans 'Active' %}
</a></th>
</tr>
</thead>
</table>
{% endblock %}
{% block modal_confirm_id %}btn_select_user{% endblock %}
This diff is collapsed.
Click to expand it.
apps/users/templates/users/_user_bulk_update_modal.html
0 → 100644
View file @
a04d7725
{% extends '_modal.html' %}
{% load i18n %}
{% block modal_id %}user_bulk_update_modal{% endblock %}
{% block modal_title%}{% trans "Update User" %}{% endblock %}
{% block modal_body %}
<p
class=
"text-success text-center"
>
{% trans "Hint: only change the field you want to update." %}
</p>
<form
method=
"post"
class=
"form-horizontal"
action=
""
id=
"fm_user_bulk_update"
>
<div
class=
"form-group"
>
<label
class=
"control-label col-sm-2 col-lg-2 "
for=
"id_role"
>
{% trans "Role" %}
</label>
<div
class=
" col-sm-9 col-lg-9 "
>
<select
class=
" form-control"
id=
"id_role"
name=
"role"
>
<option
value=
""
>
---------
</option>
<option
value=
"Admin"
>
{% trans "Admin" %}
</option>
<option
value=
"User"
>
{% trans "User" %}
</option>
</select>
</div>
</div>
<div
class=
"form-group"
>
<label
for=
"groups"
class=
"col-sm-2 control-label"
>
{% trans 'Groups' %}
</label>
<div
class=
"col-sm-9"
id=
"select2-container"
>
<select
name=
"groups"
id=
"select2_groups"
data-placeholder=
"{% trans 'Select Group' %}"
class=
"select2 form-control m-b"
multiple
>
{% for group in groups %}
<option
value=
"{{ group.id }}"
>
{{ group.name }}
</option>
{% endfor %}
</select>
</div>
</div>
<div
class=
"form-group"
>
<div
class=
"col-sm-9 col-lg-9 col-sm-offset-2"
>
<div
class=
"checkbox checkbox-success"
>
<input
type=
"checkbox"
name=
"enable_otp"
checked
id=
"id_enable_otp"
><label
for=
"id_enable_otp"
>
{% trans 'Enable-OTP' %}
</label>
</div>
</div>
</div>
</form>
{% endblock %}
{% block modal_confirm_id %}btn_user_bulk_update{% endblock %}
This diff is collapsed.
Click to expand it.
apps/users/templates/users/user_detail.html
View file @
a04d7725
...
...
@@ -222,7 +222,7 @@
jumpserver
.
selected_groups
=
{};
function
updateUserGroups
(
user_groups
)
{
var
the_url
=
"{% url 'users:
user-group
-edit-api' pk=user_object.id %}"
;
var
the_url
=
"{% url 'users:
group-user
-edit-api' pk=user_object.id %}"
;
var
body
=
{
id
:
{{
user_object
.
id
}},
groups
:
Object
.
assign
([],
user_groups
)
...
...
@@ -237,7 +237,7 @@ 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
pull-right btn_delete_user_group" type="button"><i class="fa fa-minus"></i></button></td>'
+
'<td><button class="btn btn-danger btn-
xs
pull-right btn_delete_user_group" type="button"><i class="fa fa-minus"></i></button></td>'
+
'</tr>'
)
});
...
...
This diff is collapsed.
Click to expand it.
apps/users/templates/users/user_group_detail.html
View file @
a04d7725
...
...
@@ -5,8 +5,23 @@
{% 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"
>
<link
href=
"{% static "
css
/
plugins
/
dataTables
/
dataTables
.
min
.
css
"
%}"
rel=
"stylesheet"
>
<link
href=
"{% static "
css
/
plugins
/
awesome-bootstrap-checkbox
/
awesome-bootstrap-checkbox
.
css
"
%}"
rel=
"stylesheet"
>
<script
src=
"{% static "
js
/
plugins
/
select2
/
select2
.
full
.
min
.
js
"
%}"
></script>
<script
src=
"{% static "
js
/
plugins
/
sweetalert
/
sweetalert
.
min
.
js
"
%}"
></script>
<script
src=
"{% static "
js
/
plugins
/
dataTables
/
dataTables
.
min
.
js
"
%}"
></script>
<style>
.label
{
font-size
:
14px
;
line-height
:
2.5
;
}
.label
.remove
{
color
:
#fff
;
}
.label
span
{
color
:
#5e5e5e
;
}
</style>
{% endblock %}
{% block content %}
<div
class=
"wrapper wrapper-content animated fadeInRight"
>
...
...
@@ -46,9 +61,17 @@
<td><b>
{{ object.comment }}
</b></td>
</tr>
<tr>
<td>
{% trans 'Created at
:
' %}:
</td>
<td>
{% trans 'Created at' %}:
</td>
<td><b>
{{ object.date_created }}
</b></td>
</tr>
<tr>
<td>
{% trans 'Users' %}:
</td>
<td
style=
"line-height: 2"
>
{% for user in object.users.all %}
<span
class=
"label m-l-xs"
><a
href=
"{{ user.get_absolute_url }}"
><span>
{{ user.name }}
</span></a><a
data-uid=
"{{ user.id }}"
class=
"btn_remove"
><i
class=
"remove fa fa-times-circle"
></i></a></span>
{% endfor %}
</td>
</tr>
</table>
</div>
</div>
...
...
@@ -61,40 +84,19 @@
<div
class=
"panel-body"
>
<table
class=
"table"
>
<tbody>
<tr
class=
"no-borders-tr"
>
<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"
>
<label
class=
"onoffswitch-label"
for=
"is_active"
>
<span
class=
"onoffswitch-inner"
></span>
<span
class=
"onoffswitch-switch"
></span>
</label>
</div>
</div>
</span></td>
</tr>
<tr>
<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
%}
id=
"enable_otp"
>
<label
class=
"onoffswitch-label"
for=
"enable_otp"
>
<span
class=
"onoffswitch-inner"
></span>
<span
class=
"onoffswitch-switch"
></span>
</label>
</div>
</div>
</span></td>
<td>
{% trans 'Add User' %}:
</td>
<td>
<span
class=
"pull-right"
>
<button
type=
"button"
class=
"btn btn-primary btn-xs"
id=
"btn_group_add_user"
style=
"width: 54px"
data-toggle=
"modal"
data-target=
"#select_user_modal"
>
{% trans 'Add' %}
</button>
</span>
</td>
</tr>
<tr>
<td>
{% trans 'Reset password
' %}:
</td>
<td>
{% trans 'Delete
' %}:
</td>
<td>
<span
class=
"pull-right"
>
<button
type=
"button"
class=
"btn btn-primary btn-xs"
id=
"btn_reset_password"
style=
"width: 54px"
>
{% trans 'Reset
' %}
</button>
<button
type=
"button"
class=
"btn btn-danger btn-xs"
id=
"btn_group_delete"
style=
"width: 54px"
>
{% trans 'Delete
' %}
</button>
</span>
</td>
</tr>
...
...
@@ -108,4 +110,80 @@
</div>
</div>
</div>
{% include "users/_select_user_modal.html" %}
{% endblock %}
{% block custom_foot_js %}
<script>
$
(
document
).
on
(
'click'
,
'.btn_remove'
,
function
(){
var
$this
=
$
(
this
);
var
uid
=
$this
.
data
(
'uid'
);
var
the_url
=
'{% url "users:delete-user-from-group-api" pk=object.id uid=99991937 %}'
.
replace
(
'99991937'
,
uid
);
var
success
=
function
(){
$this
.
closest
(
'.label'
).
remove
();
};
var
error
=
function
(){};
APIUpdateAttr
({
url
:
the_url
,
body
:
"{}"
,
method
:
"DELETE"
,
success
:
success
,
error
:
error
});
return
false
;
}).
on
(
'click'
,
'#btn_group_delete'
,
function
()
{
function
doDelete
()
{
var
the_url
=
'{% url "users:user-group-detail-api" pk=object.id %}'
;
var
success
=
function
()
{
window
.
location
.
href
=
'{% url "users:user-group-list" %}'
;
};
APIUpdateAttr
({
url
:
the_url
,
body
:
"{}"
,
method
:
"DELETE"
,
success
:
success
});
}
swal
({
title
:
"{% trans 'Are you sure?' %}"
,
text
:
"{% trans 'This will delete the current group, but will not delete any user of it.' %}"
,
type
:
"warning"
,
showCancelButton
:
true
,
confirmButtonColor
:
"#DD6B55"
,
confirmButtonText
:
"{% trans 'Confirm' %}"
,
closeOnConfirm
:
false
},
function
()
{
doDelete
();
});
}).
on
(
'shown.bs.modal'
,
'#select_user_modal'
,
function
()
{
if
(
$
.
fn
.
dataTable
.
isDataTable
(
'#select_user_table'
))
{
return
true
;
}
var
options
=
{
ele
:
$
(
'#select_user_table'
),
pageLength
:
10
,
buttons
:
[],
columnDefs
:
[
{
targets
:
6
,
createdCell
:
function
(
td
,
cellData
)
{
if
(
!
cellData
)
{
$
(
td
).
html
(
'<i class="fa fa-times text-danger"></i>'
)
}
else
{
$
(
td
).
html
(
'<i class="fa fa-check text-navy"></i>'
)
}
}},
],
ajax_url
:
'{% url "users:user-bulk-update-api" %}'
,
columns
:
[{
data
:
function
(){
return
""
}},
{
data
:
"username"
},
{
data
:
"name"
},
{
data
:
"get_role_display"
},
{
data
:
"group_display"
},
{
data
:
function
(){
return
999
}},
{
data
:
"active_display"
}],
};
jumpserver
.
initDataTable
(
options
);
}).
on
(
'click'
,
'#btn_select_user'
,
function
()
{
var
$data_table
=
$
(
'#select_user_table'
).
DataTable
();
var
id_list
=
[];
var
plain_id_list
=
[];
$data_table
.
rows
({
selected
:
true
}).
every
(
function
(){
id_list
.
push
({
id
:
this
.
data
().
id
});
plain_id_list
.
push
(
this
.
data
().
id
);
});
if
(
id_list
===
[])
{
return
false
;
};
console
.
log
(
id_list
);
console
.
log
(
plain_id_list
);
var
body
=
{
id
:
{{
object
.
id
}},
users
:
plain_id_list
.
map
(
Number
)
};
console
.
log
(
body
);
$
(
'#select_user_modal'
).
modal
(
'hide'
);
})
</script>
{% endblock %}
This diff is collapsed.
Click to expand it.
apps/users/templates/users/user_group_list.html
View file @
a04d7725
...
...
@@ -65,7 +65,7 @@ $(document).on('click', '.btn_delete_user_group', function(){
var
$this
=
$
(
this
);
function
doDelete
()
{
var
group_id
=
$this
.
data
(
'gid'
);
var
the_url
=
"{% url 'users:user-group-
delete
-api' 99991937 %}"
.
replace
(
'99991937'
,
group_id
);
var
the_url
=
"{% url 'users:user-group-
edit
-api' 99991937 %}"
.
replace
(
'99991937'
,
group_id
);
var
body
=
{};
var
success
=
function
()
{
var
msg
=
"{% trans 'Group Deleted.' %}"
;
...
...
This diff is collapsed.
Click to expand it.
apps/users/templates/users/user_list.html
View file @
a04d7725
...
...
@@ -2,15 +2,28 @@
{% load i18n static %}
{% get_current_language as LANGUAGE_CODE %}
{% load common_tags %}
{% block content_left_head %}
<a
href=
"{% url 'users:user-create' %}"
class=
"btn btn-sm btn-primary "
>
{% trans "Create user" %}
</a>
{% block custom_head_css_js %}
{{ block.super }}
<style>
div
.dataTables_wrapper
div
.dataTables_filter
,
.dataTables_length
{
float
:
right
!important
;
}
div
.dataTables_wrapper
div
.dataTables_filter
{
margin-left
:
15px
;
}
</style>
{% endblock %}
{% block table_search %}{% endblock %}
{% block table_container %}
<div
class=
"uc pull-left"
><a
href=
"{% url "
users:user-create
"
%}"
class=
"btn btn-sm btn-primary"
>
{% trans "Create user" %}
</a></div>
<table
class=
"table table-striped table-bordered table-hover "
id=
"user_list_table"
>
<thead>
<tr>
<th></th>
<th
class=
"text-center"
>
<div
class=
"checkbox checkbox-default"
><input
id=
""
type=
"checkbox"
class=
"ipt_check_all"
><label></label></div>
</th>
<th
class=
"text-center"
>
{% trans 'Name' %}
</a></th>
<th
class=
"text-center"
>
{% trans 'Username' %}
</a></th>
<th
class=
"text-center"
>
{% trans 'Role' %}
</th>
...
...
@@ -23,8 +36,7 @@
<tbody>
</tbody>
</table>
{% endblock %}
{% block content_bottom_left %}
<div
id=
"actions"
class=
"hide"
>
<div
class=
"input-group"
>
<select
class=
"form-control m-b"
style=
"width: auto"
id=
"slct_bulk_update"
>
<option
value=
"delete"
>
{% trans 'Delete selected' %}
</option>
...
...
@@ -37,79 +49,43 @@
</button>
</div>
</div>
</div>
{% include "users/_user_bulk_update_modal.html" %}
{% endblock %}
{% block content_bottom_left %}
{% endblock %}
{% block custom_foot_js %}
<script>
$
(
document
).
ready
(
function
(){
$
(
'#user_list_table'
).
DataTable
({
dom
:
'<"html5buttons"B>lftip'
,
language
:
{
url
:
"{% static 'js/plugins/dataTables/i18n/language_code.json' %}"
.
replace
(
'language_code'
,
'{{ LANGUAGE_CODE }}'
)
},
buttons
:
[
{
extend
:
'excel'
,
exportOptions
:
{
modifier
:
{
selected
:
true
}
}
},
{
extend
:
'pdf'
,
exportOptions
:
{
modifier
:
{
selected
:
true
}
}
},
{
extend
:
'print'
,
customize
:
function
(
win
){
$
(
win
.
document
.
body
).
addClass
(
'white-bg'
);
$
(
win
.
document
.
body
).
css
(
'font-size'
,
'10px'
);
$
(
win
.
document
.
body
).
find
(
'table'
)
.
addClass
(
'compact'
)
.
css
(
'font-size'
,
'inherit'
);
}
}
],
var
options
=
{
ele
:
$
(
'#user_list_table'
),
columnDefs
:
[
{
orderable
:
false
,
className
:
'select-checkbox'
,
targets
:
0
},
{
className
:
'text-center'
,
targets
:
[
1
,
2
,
3
,
4
,
5
,
6
,
7
]},
{
targets
:
7
,
createdCell
:
function
(
td
,
cellData
,
rowData
)
{
{
targets
:
1
,
createdCell
:
function
(
td
,
cellData
,
rowData
)
{
var
detail_btn
=
'<a href="{% url "users:user-detail" pk=99991937 %}">'
+
cellData
+
'</a>'
;
$
(
td
).
html
(
detail_btn
.
replace
(
'99991937'
,
rowData
.
id
));
}},
{
targets
:
6
,
createdCell
:
function
(
td
,
cellData
)
{
if
(
!
cellData
)
{
$
(
td
).
html
(
'<i class="fa fa-times text-danger"></i>'
)
}
else
{
$
(
td
).
html
(
'<i class="fa fa-check text-navy"></i>'
)
}
}},
{
targets
:
7
,
createdCell
:
function
(
td
,
cellData
,
rowData
)
{
var
update_btn
=
'<a href="{% url "users:user-update" pk=99991937 %}" class="btn btn-xs btn-info">{% trans "Update" %}</a>'
.
replace
(
'99991937'
,
cellData
);
var
del_btn
=
'<a class="btn btn-xs btn-danger m-l-xs btn_user_delete" data-uid="99991937">{% trans "Delete" %}</a>'
.
replace
(
'99991937'
,
cellData
);
if
(
rowData
.
role
===
'Admin'
)
{
if
(
rowData
.
id
===
1
)
{
$
(
td
).
html
(
update_btn
)
}
else
{
$
(
td
).
html
(
update_btn
+
del_btn
)
}
}
},
{
targets
:
6
,
createdCell
:
function
(
td
,
cellData
)
{
if
(
!
cellData
)
{
$
(
td
).
html
(
'<i class="fa fa-times text-danger"></i>'
)
}
else
{
$
(
td
).
html
(
'<i class="fa fa-check text-navy"></i>'
)
}
}}
],
select
:
{
style
:
'multi'
},
ajax
:
{
url
:
'{% url "users:user-bulk-update-api" %}'
,
dataSrc
:
""
},
columns
:
[
{
data
:
function
(){
return
""
}
},
{
data
:
"name"
},
{
data
:
"username"
},
{
data
:
"get_role_display"
},
{
data
:
"group_display"
},
{
data
:
function
(){
return
999
}
},
{
data
:
"active_display"
},
{
data
:
"id"
}
]
});
}}],
ajax_url
:
'{% url "users:user-bulk-update-api" %}'
,
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
()
};
jumpserver
.
initDataTable
(
options
);
}).
on
(
'click'
,
'#btn_bulk_update'
,
function
(){
var
action
=
$
(
'#slct_bulk_update'
).
val
();
var
$data_table
=
$
(
'#user_list_table'
).
DataTable
()
...
...
@@ -129,6 +105,7 @@ $(document).ready(function(){
});
APIUpdateAttr
({
url
:
the_url
,
method
:
'PATCH'
,
body
:
JSON
.
stringify
(
body
)});
$data_table
.
ajax
.
reload
();
jumpserver
.
checked
=
false
;
}
function
doDelete
()
{
swal
({
...
...
@@ -151,9 +128,12 @@ $(document).ready(function(){
};
var
url_delete
=
the_url
+
'?id__in='
+
JSON
.
stringify
(
plain_id_list
);
APIUpdateAttr
({
url
:
url_delete
,
method
:
'DELETE'
,
success
:
success
,
error
:
fail
});
jumpserver
.
checked
=
false
;
});
}
function
doUpdate
()
{}
function
doUpdate
()
{
$
(
'#user_bulk_update_modal'
).
modal
(
'show'
);
}
switch
(
action
)
{
case
'deactive'
:
doDeactive
();
...
...
@@ -201,6 +181,40 @@ $(document).ready(function(){
},
function
()
{
doDelete
();
});
}).
on
(
'click'
,
'#btn_user_bulk_update'
,
function
(){
var
json_data
=
$
(
'#fm_user_bulk_update'
).
serializeObject
();
var
body
=
{};
body
.
enable_otp
=
(
json_data
.
enable_otp
===
'on'
)?
true
:
false
;
if
(
json_data
.
role
!=
''
)
{
body
.
role
=
json_data
.
role
;
}
if
(
json_data
.
groups
!=
undefined
)
{
body
.
groups
=
json_data
.
groups
;
}
if
(
typeof
body
.
groups
===
'string'
)
{
body
.
groups
=
[
parseInt
(
body
.
groups
)]
}
else
if
(
typeof
body
.
groups
===
'array'
)
{
new_groups
=
body
.
groups
.
map
(
Number
);
body
.
groups
=
new_groups
;
}
var
$data_table
=
$
(
'#user_list_table'
).
DataTable
()
var
post_list
=
[];
$data_table
.
rows
({
selected
:
true
}).
every
(
function
(){
var
content
=
Object
.
assign
({
id
:
this
.
data
().
id
},
body
);
post_list
.
push
(
content
);
});
if
(
post_list
===
[])
{
return
false
;
};
var
the_url
=
"{% url 'users:user-bulk-update-api' %}"
;
var
success
=
function
()
{
var
msg
=
"{% trans 'The selected users has been updated successfully.' %}"
;
swal
(
"{% trans 'User Updated' %}"
,
msg
,
"success"
);
$
(
'#user_list_table'
).
DataTable
().
ajax
.
reload
();
jumpserver
.
checked
=
false
;
}
APIUpdateAttr
({
url
:
the_url
,
method
:
'PATCH'
,
body
:
JSON
.
stringify
(
post_list
),
success
:
success
});
$
(
'#user_bulk_update_modal'
).
modal
(
'hide'
);
})
</script>
{% endblock %}
...
...
This diff is collapsed.
Click to expand it.
apps/users/urls.py
View file @
a04d7725
...
...
@@ -26,7 +26,6 @@ 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'
),
url
(
r'^user/(?P<pk>[0-9]+)/delete$'
,
views
.
UserDeleteView
.
as_view
(),
name
=
'user-delete'
),
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'
),
...
...
@@ -47,8 +46,10 @@ urlpatterns += [
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'
),
url
(
r'^v1/user-groups/(?P<pk>[0-9]+)/edit$'
,
api
.
UserGroupEditApi
.
as_view
(),
name
=
'user-group-edit-api'
),
url
(
r'^v1/user-groups/(?P<pk>[0-9]+)/delete/$'
,
api
.
GroupDeleteApi
.
as_view
(),
name
=
'user-group-delete-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>[0-9]+)/users/$'
,
api
.
GroupUserEditApi
.
as_view
(),
name
=
'group-user-edit-api'
),
url
(
r'^v1/user-groups/(?P<pk>[0-9]+)/edit/$'
,
api
.
GroupEditApi
.
as_view
(),
name
=
'user-group-edit-api'
),
]
This diff is collapsed.
Click to expand it.
apps/users/utils.py
View file @
a04d7725
...
...
@@ -3,7 +3,6 @@
from
__future__
import
unicode_literals
import
logging
import
os
import
re
from
django.conf
import
settings
from
django.contrib.auth.mixins
import
UserPassesTestMixin
...
...
This diff is collapsed.
Click to expand it.
apps/users/views.py
View file @
a04d7725
...
...
@@ -7,7 +7,6 @@ from django.contrib.auth import login as auth_login, logout as auth_logout
from
django.contrib.auth.mixins
import
LoginRequiredMixin
from
django.contrib.messages.views
import
SuccessMessageMixin
from
django.core.files.storage
import
default_storage
from
django.db.models
import
Q
from
django.http
import
HttpResponseRedirect
from
django.shortcuts
import
reverse
,
redirect
from
django.utils.decorators
import
method_decorator
...
...
@@ -80,27 +79,12 @@ class UserLogoutView(TemplateView):
return
super
(
UserLogoutView
,
self
)
.
get_context_data
(
**
kwargs
)
class
UserListView
(
AdminUserRequiredMixin
,
ListView
):
model
=
User
paginate_by
=
settings
.
CONFIG
.
DISPLAY_PER_PAGE
context_object_name
=
'user_list'
template_name
=
'users/asset_permission_list.html'
ordering
=
'-date_joined'
def
get_queryset
(
self
):
self
.
queryset
=
super
(
UserListView
,
self
)
.
get_queryset
()
self
.
keyword
=
keyword
=
self
.
request
.
GET
.
get
(
'keyword'
,
''
)
self
.
sort
=
sort
=
self
.
request
.
GET
.
get
(
'sort'
)
if
keyword
:
self
.
queryset
=
self
.
queryset
.
filter
(
Q
(
username__icontains
=
keyword
)
|
Q
(
name__icontains
=
keyword
))
if
sort
:
self
.
queryset
=
self
.
queryset
.
order_by
(
sort
)
return
self
.
queryset
class
UserListView
(
AdminUserRequiredMixin
,
TemplateView
):
template_name
=
'users/user_list.html'
def
get_context_data
(
self
,
**
kwargs
):
context
=
super
(
UserListView
,
self
)
.
get_context_data
(
**
kwargs
)
context
.
update
({
'app'
:
_
(
'Users'
),
'action'
:
_
(
'User list'
),
'
keyword'
:
self
.
keyword
})
context
.
update
({
'app'
:
_
(
'Users'
),
'action'
:
_
(
'User list'
),
'
groups'
:
UserGroup
.
objects
.
all
()
})
return
context
...
...
@@ -153,26 +137,6 @@ class UserUpdateView(AdminUserRequiredMixin, UpdateView):
return
context
class
UserDeleteView
(
AdminUserRequiredMixin
,
DeleteView
):
model
=
User
success_url
=
reverse_lazy
(
'users:user-list'
)
template_name
=
'users/user_delete_confirm.html'
def
delete
(
self
,
request
,
*
args
,
**
kwargs
):
"""
Calls the delete() method on the fetched object and then
redirects to the success URL.
"""
self
.
object
=
self
.
get_object
()
success_url
=
self
.
get_success_url
()
if
self
.
object
.
name
==
"admin"
or
self
.
object
.
id
==
request
.
session
.
get
(
'_auth_user_id'
):
pass
else
:
self
.
object
.
delete
()
return
HttpResponseRedirect
(
success_url
)
class
UserDetailView
(
AdminUserRequiredMixin
,
DetailView
):
model
=
User
template_name
=
'users/user_detail.html'
...
...
This diff is collapsed.
Click to expand it.
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