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
695e4da8
Commit
695e4da8
authored
Apr 12, 2017
by
ibuler
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[Fixture] 完成批量更新
parent
2aa9aafd
Show whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
382 additions
and
248 deletions
+382
-248
forms.py
apps/assets/forms.py
+47
-11
asset.py
apps/assets/models/asset.py
+10
-5
asset_bulk_update.html
apps/assets/templates/assets/asset_bulk_update.html
+2
-48
asset_list.html
apps/assets/templates/assets/asset_list.html
+67
-65
asset.py
apps/assets/views/asset.py
+16
-58
forms.py
apps/users/forms.py
+35
-6
_user_bulk_update_modal.html
apps/users/templates/users/_user_bulk_update_modal.html
+60
-25
user_bulk_update.html
apps/users/templates/users/user_bulk_update.html
+69
-0
user_list.html
apps/users/templates/users/user_list.html
+20
-3
views_urls.py
apps/users/urls/views_urls.py
+15
-26
user.py
apps/users/views/user.py
+41
-1
No files found.
apps/assets/forms.py
View file @
695e4da8
...
...
@@ -13,19 +13,24 @@ class AssetCreateForm(forms.ModelForm):
class
Meta
:
model
=
Asset
fields
=
[
'hostname'
,
'ip'
,
'public_ip'
,
'port'
,
'type'
,
'comment'
,
'admin_user'
,
'idc'
,
'groups'
,
'status'
,
'env'
,
'is_active'
'hostname'
,
'ip'
,
'public_ip'
,
'port'
,
'type'
,
'comment'
,
'
admin_user'
,
'
idc'
,
'groups'
,
'status'
,
'env'
,
'is_active'
]
widgets
=
{
'groups'
:
forms
.
SelectMultiple
(
attrs
=
{
'class'
:
'select2'
,
'groups'
:
forms
.
SelectMultiple
(
attrs
=
{
'class'
:
'select2'
,
'data-placeholder'
:
_
(
'Select asset groups'
)}),
'admin_user'
:
forms
.
Select
(
attrs
=
{
'class'
:
'select2'
,
'data-placeholder'
:
_
(
'Select asset admin user'
)}),
'admin_user'
:
forms
.
Select
(
attrs
=
{
'class'
:
'select2'
,
'data-placeholder'
:
_
(
'Select asset admin user'
)}),
}
help_texts
=
{
'hostname'
:
'* required'
,
'ip'
:
'* required'
,
'system_users'
:
_
(
'System user will be granted for user to login assets (using ansible create automatic)'
),
'admin_user'
:
_
(
'Admin user should be exist on asset already, And have sudo ALL permission'
),
'system_users'
:
_
(
'System user will be granted for user to login '
'assets (using ansible create automatic)'
),
'admin_user'
:
_
(
'Admin user should be exist on asset already, '
'And have sudo ALL permission'
),
}
def
clean_admin_user
(
self
):
...
...
@@ -43,23 +48,43 @@ class AssetUpdateForm(forms.ModelForm):
'cabinet_pos'
,
'number'
,
'comment'
]
widgets
=
{
'groups'
:
forms
.
SelectMultiple
(
attrs
=
{
'class'
:
'select2'
,
'groups'
:
forms
.
SelectMultiple
(
attrs
=
{
'class'
:
'select2'
,
'data-placeholder'
:
_
(
'Select asset groups'
)}),
'admin_user'
:
forms
.
Select
(
attrs
=
{
'class'
:
'select2'
,
'data-placeholder'
:
_
(
'Select asset admin user'
)}),
'admin_user'
:
forms
.
Select
(
attrs
=
{
'class'
:
'select2'
,
'data-placeholder'
:
_
(
'Select asset admin user'
)}),
}
help_texts
=
{
'hostname'
:
'* required'
,
'ip'
:
'* required'
,
'system_users'
:
_
(
'System user will be granted for user to login assets (using ansible create automatic)'
),
'admin_user'
:
_
(
'Admin user should be exist on asset already, And have sudo ALL permission'
),
'system_users'
:
_
(
'System user will be granted for user '
'to login assets (using ansible create automatic)'
),
'admin_user'
:
_
(
'Admin user should be exist on asset '
'already, And have sudo ALL permission'
),
}
class
AssetBulkUpdateForm
(
forms
.
ModelForm
):
assets
=
forms
.
MultipleChoiceField
(
required
=
True
,
help_text
=
'* required'
,
label
=
_
(
'Select assets'
),
choices
=
[(
asset
.
id
,
asset
.
hostname
)
for
asset
in
Asset
.
objects
.
all
()],
widget
=
forms
.
SelectMultiple
(
attrs
=
{
'class'
:
'select2'
,
'data-placeholder'
:
_
(
'Select assets'
)
}
)
)
port
=
forms
.
IntegerField
(
min_value
=
1
,
max_value
=
65535
,
required
=
False
,
label
=
_
(
'Port'
))
class
Meta
:
model
=
Asset
fields
=
[
'port'
,
'groups'
,
'admin_user'
,
'idc'
,
'
assets'
,
'
port'
,
'groups'
,
'admin_user'
,
'idc'
,
'type'
,
'env'
,
'status'
,
]
widgets
=
{
...
...
@@ -71,6 +96,17 @@ class AssetBulkUpdateForm(forms.ModelForm):
'data-placeholder'
:
_
(
'Select asset admin user'
)}),
}
def
save
(
self
,
commit
=
True
):
cleaned_data
=
{
k
:
v
for
k
,
v
in
self
.
cleaned_data
.
items
()
if
v
is
not
None
}
assets_id
=
cleaned_data
.
pop
(
'assets'
)
groups
=
cleaned_data
.
pop
(
'groups'
)
assets
=
Asset
.
objects
.
filter
(
id__in
=
assets_id
)
assets
.
update
(
**
cleaned_data
)
if
groups
:
for
asset
in
assets
:
asset
.
groups
.
set
(
groups
)
return
assets
class
AssetGroupForm
(
forms
.
ModelForm
):
# See AdminUserForm comment same it
...
...
apps/assets/models/asset.py
View file @
695e4da8
...
...
@@ -41,10 +41,13 @@ class Asset(models.Model):
ip
=
models
.
GenericIPAddressField
(
max_length
=
32
,
verbose_name
=
_
(
'IP'
),
db_index
=
True
)
hostname
=
models
.
CharField
(
max_length
=
128
,
unique
=
True
,
verbose_name
=
_
(
'Hostname'
))
port
=
models
.
IntegerField
(
default
=
22
,
verbose_name
=
_
(
'Port'
))
groups
=
models
.
ManyToManyField
(
AssetGroup
,
blank
=
True
,
related_name
=
'assets'
,
verbose_name
=
_
(
'Asset groups'
))
groups
=
models
.
ManyToManyField
(
AssetGroup
,
blank
=
True
,
related_name
=
'assets'
,
verbose_name
=
_
(
'Asset groups'
))
admin_user
=
models
.
ForeignKey
(
AdminUser
,
null
=
True
,
blank
=
True
,
related_name
=
'assets'
,
on_delete
=
models
.
SET_NULL
,
verbose_name
=
_
(
"Admin user"
))
system_users
=
models
.
ManyToManyField
(
SystemUser
,
blank
=
True
,
related_name
=
'assets'
,
verbose_name
=
_
(
"System User"
))
system_users
=
models
.
ManyToManyField
(
SystemUser
,
blank
=
True
,
related_name
=
'assets'
,
verbose_name
=
_
(
"System User"
))
idc
=
models
.
ForeignKey
(
IDC
,
blank
=
True
,
null
=
True
,
related_name
=
'assets'
,
on_delete
=
models
.
SET_NULL
,
verbose_name
=
_
(
'IDC'
),)
is_active
=
models
.
BooleanField
(
default
=
True
,
verbose_name
=
_
(
'Is active'
))
...
...
@@ -52,12 +55,14 @@ class Asset(models.Model):
default
=
'Server'
,
verbose_name
=
_
(
'Asset type'
),)
env
=
models
.
CharField
(
choices
=
ENV_CHOICES
,
max_length
=
8
,
blank
=
True
,
null
=
True
,
default
=
'Prod'
,
verbose_name
=
_
(
'Asset environment'
),)
status
=
models
.
CharField
(
choices
=
STATUS_CHOICES
,
max_length
=
8
,
null
=
True
,
blank
=
True
,
status
=
models
.
CharField
(
choices
=
STATUS_CHOICES
,
max_length
=
12
,
null
=
True
,
blank
=
True
,
default
=
'In use'
,
verbose_name
=
_
(
'Asset status'
))
# Some information
public_ip
=
models
.
GenericIPAddressField
(
max_length
=
32
,
blank
=
True
,
null
=
True
,
verbose_name
=
_
(
'Public IP'
))
remote_card_ip
=
models
.
CharField
(
max_length
=
16
,
null
=
True
,
blank
=
True
,
verbose_name
=
_
(
'Remote control card IP'
))
public_ip
=
models
.
GenericIPAddressField
(
max_length
=
32
,
blank
=
True
,
null
=
True
,
verbose_name
=
_
(
'Public IP'
))
remote_card_ip
=
models
.
CharField
(
max_length
=
16
,
null
=
True
,
blank
=
True
,
verbose_name
=
_
(
'Remote control card IP'
))
cabinet_no
=
models
.
CharField
(
max_length
=
32
,
null
=
True
,
blank
=
True
,
verbose_name
=
_
(
'Cabinet number'
))
cabinet_pos
=
models
.
IntegerField
(
null
=
True
,
blank
=
True
,
verbose_name
=
_
(
'Cabinet position'
))
number
=
models
.
CharField
(
max_length
=
32
,
null
=
True
,
blank
=
True
,
verbose_name
=
_
(
'Asset number'
))
...
...
apps/assets/templates/assets/asset_bulk_update.html
View file @
695e4da8
...
...
@@ -9,32 +9,14 @@
<div
class=
"tagBtnList"
>
<a
class=
"label label-primary"
id=
"change_all"
value=
"1"
>
全选
</a>
{% for field in form %}
{% if field.name != 'assets' %}
<a
data-id=
"{{ field.id_for_label }}"
class=
"label label-default label-primary field-tag"
value=
"1"
>
{{ field.label }}
</a>
{% endif %}
{% endfor %}
</div>
</div>
{% if errors %}
<div
class=
"alert alert-danger"
>
{{ errors }}
</div>
{% endif %}
<form
method=
"post"
class=
"form-horizontal"
id=
"add_form"
>
{% csrf_token %}
<div
class=
"form-group abc"
>
<label
class=
"control-label col-sm-2 col-lg-2 "
id=
"asset_on_count"
>
{% trans 'Asset' %}
</label>
<div
class=
"col-sm-9"
>
<select
class=
"form-control select2"
multiple=
"multiple"
name=
"assets"
>
{% for asset in assets %}
{% if asset.id in assets_selected %}
<option
selected=
"selected"
value=
"{{ asset.id }}"
>
{{ asset.hostname }}
</option>
{% else %}
<option
value=
"{{ asset.id }}"
>
{{ asset.hostname }}
</option>
{% endif %}
{% endfor %}
</select>
<span
class=
"help-block"
>
* required
</span>
</div>
</div>
{% bootstrap_form form layout="horizontal" %}
<div
class=
"form-group abc"
>
<div
class=
"col-sm-4 col-sm-offset-2"
>
...
...
@@ -83,33 +65,5 @@
form_groups
.
filter
(
':has(#'
+
field_id
+
')'
).
hide
().
find
(
'select,input'
).
prop
(
'disabled'
,
true
)
}
}
function
fsubmit
(){
var
assets_id
=
document
.
getElementsByName
(
"assets"
);
var
oForm
=
document
.
getElementById
(
'add_form'
);
var
parentElem
=
document
.
getElementById
(
"add_form"
);
var
aDiv
=
parentElem
.
getElementsByClassName
(
'form-group'
);
if
(
assets_id
.
length
===
0
)
{
swal
({
title
:
"未选择需要修改的主机"
,
text
:
"请点击选择"
});
}
else
if
(
aDiv
.
length
===
1
)
{
swal
({
title
:
"未选需要修改的属性"
,
text
:
"请点击选择"
});
}
else
{
var
m
=
document
.
getElementsByName
(
'assets_ids'
);
alert
(
m
.
length
);
for
(
var
i
=
0
;
i
<
m
.
length
;
i
++
){
alert
(
m
[
0
].
value
);
oForm
.
appendChild
(
m
[
0
]);
}
action
=
"/assets/asset/"
+
assets_id
[
0
].
value
+
"/update"
;
oForm
.
action
=
action
;
oForm
.
submit
();
}
}
</script>
{% endblock %}
apps/assets/templates/assets/asset_list.html
View file @
695e4da8
...
...
@@ -88,6 +88,7 @@ function tagShow() {
}
//onload;
$
(
document
).
ready
(
function
(){
var
options
=
{
ele
:
$
(
'#asset_list_table'
),
...
...
@@ -125,6 +126,7 @@ $(document).ready(function(){
op_html
:
$
(
'#actions'
).
html
()
};
var
table
=
jumpserver
.
initDataTable
(
options
);
$
(
'.btn_export'
).
click
(
function
()
{
var
assets
=
[];
var
rows
=
table
.
rows
(
'.selected'
).
data
();
...
...
@@ -178,20 +180,18 @@ $(document).ready(function(){
$data_table
.
ajax
.
reload
();
},
3000
);
})
.
on
(
'click'
,
'#btn_bulk_update'
,
function
()
{
var
action
=
$
(
'#slct_bulk_update'
).
val
();
var
$data_table
=
$
(
'#asset_list_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
);
id_list
.
push
(
this
.
data
().
id
);
});
if
(
plain_
id_list
.
length
==
0
)
{
if
(
id_list
.
length
==
0
)
{
return
false
;
}
var
the_url
=
"{% url 'api-assets:asset-list' %}"
;
function
doDeactive
()
{
var
body
=
$
.
each
(
id_list
,
function
(
index
,
asset_object
)
{
asset_object
[
'is_active'
]
=
false
;
...
...
@@ -234,7 +234,9 @@ $(document).ready(function(){
});
}
function
doUpdate
()
{
$
(
'#asset_bulk_update_modal'
).
modal
(
'show'
);
var
id_list_string
=
id_list
.
join
(
','
);
var
url
=
"{% url 'assets:asset-bulk-update' %}?assets_id="
+
id_list_string
;
location
.
href
=
url
}
switch
(
action
)
{
case
'deactive'
:
...
...
@@ -252,66 +254,66 @@ $(document).ready(function(){
default
:
break
;
}
})
.
on
(
'click'
,
'#btn_asset_bulk_update'
,
function
()
{
var
json_data
=
$
(
"#fm_asset_bulk_update"
).
serializeObject
();
var
body
=
{};
body
.
enable_otp
=
(
json_data
.
enable_otp
===
'on'
)?
true
:
false
;
if
(
json_data
.
type
!=
''
)
{
body
.
type
=
json_data
.
type
;
}
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'
)
{
var
new_groups
=
body
.
groups
.
map
(
Number
);
body
.
groups
=
new_groups
;
}
if
(
json_data
.
system_users
!=
undefined
)
{
body
.
system_users
=
json_data
.
system_users
;
}
if
(
typeof
body
.
system_users
===
'string'
)
{
body
.
system_users
=
[
parseInt
(
body
.
system_users
)]
}
else
if
(
typeof
body
.
system_users
===
'array'
)
{
var
new_users
=
body
.
system_users
.
map
(
Number
);
body
.
system_users
=
new_users
;
}
if
(
json_data
.
tags
!=
undefined
)
{
body
.
tags
=
json_data
.
tags
;
}
if
(
typeof
body
.
tags
==
'string'
)
{
body
.
tags
=
[
parseInt
(
body
.
tags
)];
}
else
if
(
typeof
body
.
tags
===
'array'
)
{
var
new_tags
=
body
.
tags
.
map
(
Number
);
body
.
tags
=
new_tags
;
}
var
$data_table
=
$
(
'#asset_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 'api-assets:asset-list' %}"
;
var
success
=
function
()
{
var
msg
=
"{% trans 'The selected assets has been updated successfully.' %}"
;
swal
(
"{% trans 'Asset Updated' %}"
,
msg
,
"success"
);
$
(
'#asset_list_table'
).
DataTable
().
ajax
.
reload
();
jumpserver
.
checked
=
false
;
};
console
.
log
(
JSON
.
stringify
(
post_list
));
console
.
log
(
the_url
);
{
#
APIUpdateAttr
({
url
:
the_url
,
method
:
'PATCH'
,
body
:
JSON
.
stringify
(
post_list
),
success
:
success
});
#
}
$
(
'#asset_bulk_update_modal'
).
modal
(
'hide'
);
});
{
##
}
{
#
.
on
(
'click'
,
'#btn_asset_bulk_update'
,
function
()
{
#
}
{
#
var
json_data
=
$
(
"#fm_asset_bulk_update"
).
serializeObject
();
#
}
{
#
var
body
=
{};
#
}
{
#
body
.
enable_otp
=
(
json_data
.
enable_otp
===
'on'
)?
true
:
false
;
#
}
{
#
if
(
json_data
.
type
!=
''
)
{
#
}
{
#
body
.
type
=
json_data
.
type
;
#
}
{
#
}
#
}
{
#
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'
)
{
#
}
{
#
var
new_groups
=
body
.
groups
.
map
(
Number
);
#
}
{
#
body
.
groups
=
new_groups
;
#
}
{
#
}
#
}
{
##
}
{
#
if
(
json_data
.
system_users
!=
undefined
)
{
#
}
{
#
body
.
system_users
=
json_data
.
system_users
;
#
}
{
#
}
#
}
{
#
if
(
typeof
body
.
system_users
===
'string'
)
{
#
}
{
#
body
.
system_users
=
[
parseInt
(
body
.
system_users
)]
#
}
{
#
}
else
if
(
typeof
body
.
system_users
===
'array'
)
{
#
}
{
#
var
new_users
=
body
.
system_users
.
map
(
Number
);
#
}
{
#
body
.
system_users
=
new_users
;
#
}
{
#
}
#
}
{
##
}
{
#
if
(
json_data
.
tags
!=
undefined
)
{
#
}
{
#
body
.
tags
=
json_data
.
tags
;
#
}
{
#
}
#
}
{
#
if
(
typeof
body
.
tags
==
'string'
)
{
#
}
{
#
body
.
tags
=
[
parseInt
(
body
.
tags
)];
#
}
{
#
}
else
if
(
typeof
body
.
tags
===
'array'
)
{
#
}
{
#
var
new_tags
=
body
.
tags
.
map
(
Number
);
#
}
{
#
body
.
tags
=
new_tags
;
#
}
{
#
}
#
}
{
##
}
{
#
var
$data_table
=
$
(
'#asset_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 'api-assets:asset-list' %}"
;
#
}
{
#
var
success
=
function
()
{
#
}
{
#
var
msg
=
"{% trans 'The selected assets has been updated successfully.' %}"
;
#
}
{
#
swal
(
"{% trans 'Asset Updated' %}"
,
msg
,
"success"
);
#
}
{
#
$
(
'#asset_list_table'
).
DataTable
().
ajax
.
reload
();
#
}
{
#
jumpserver
.
checked
=
false
;
#
}
{
#
};
#
}
{
#
console
.
log
(
JSON
.
stringify
(
post_list
));
#
}
{
#
console
.
log
(
the_url
);
#
}
{
#
APIUpdateAttr
({
url
:
the_url
,
method
:
'PATCH'
,
body
:
JSON
.
stringify
(
post_list
),
success
:
success
});
#
}
{
#
$
(
'#asset_bulk_update_modal'
).
modal
(
'hide'
);
#
}
{
#
})
#
}
</script>
{% endblock %}
apps/assets/views/asset.py
View file @
695e4da8
...
...
@@ -20,7 +20,7 @@ from django.utils.decorators import method_decorator
from
django.core.cache
import
cache
from
django.utils
import
timezone
from
django.contrib.auth.mixins
import
LoginRequiredMixin
from
django.shortcuts
import
get_object_or_404
,
redirect
from
django.shortcuts
import
get_object_or_404
,
redirect
,
reverse
from
common.mixins
import
JSONResponseMixin
from
common.utils
import
get_object_or_none
...
...
@@ -43,7 +43,7 @@ class AssetListView(AdminUserRequiredMixin, TemplateView):
def
get_context_data
(
self
,
**
kwargs
):
context
=
{
'app'
:
'Assets'
,
'action'
:
'
a
sset list'
,
'action'
:
'
A
sset list'
,
'groups'
:
AssetGroup
.
objects
.
all
(),
'system_users'
:
SystemUser
.
objects
.
all
(),
# 'form': forms.AssetBulkUpdateForm(),
...
...
@@ -58,7 +58,7 @@ class UserAssetListView(LoginRequiredMixin, TemplateView):
def
get_context_data
(
self
,
**
kwargs
):
context
=
{
'app'
:
'Assets'
,
'action'
:
'
a
sset list'
,
'action'
:
'
A
sset list'
,
'system_users'
:
SystemUser
.
objects
.
all
(),
}
kwargs
.
update
(
context
)
...
...
@@ -118,62 +118,24 @@ class AssetBulkUpdateView(AdminUserRequiredMixin, ListView):
def
get
(
self
,
request
,
*
args
,
**
kwargs
):
assets_id
=
self
.
request
.
GET
.
get
(
'assets_id'
,
''
)
self
.
assets_id_list
=
[
int
(
i
)
for
i
in
assets_id
.
split
(
','
)
if
i
.
isdigit
()]
if
kwargs
.
get
(
'form'
):
self
.
form
=
kwargs
[
'form'
]
elif
assets_id
:
self
.
form
=
self
.
form_class
(
initial
=
{
'assets'
:
self
.
assets_id_list
}
)
else
:
self
.
form
=
self
.
form_class
()
self
.
errors
=
kwargs
.
get
(
'errors'
)
return
super
(
AssetBulkUpdateView
,
self
)
.
get
(
request
,
*
args
,
**
kwargs
)
def
post
(
self
,
request
,
*
args
,
**
kwargs
):
raw_data
=
request
.
POST
data
=
{}
errors
=
defaultdict
(
list
)
for
k
in
raw_data
:
if
not
hasattr
(
Asset
,
k
)
or
raw_data
.
get
(
k
)
==
''
:
if
k
not
in
[
'assets'
]:
continue
if
k
==
'assets'
:
v
=
Asset
.
objects
.
filter
(
id__in
=
raw_data
.
getlist
(
k
))
if
not
v
:
errors
[
'assets'
]
.
append
(
_
(
'Required'
))
elif
k
==
'port'
:
try
:
v
=
int
(
raw_data
.
get
(
k
))
except
ValueError
:
v
=
None
errors
[
'port'
]
.
append
(
_
(
'Integer required'
))
elif
k
==
'admin_user'
:
admin_user_id
=
raw_data
.
get
(
k
)
try
:
v
=
int
(
admin_user_id
)
except
ValueError
:
v
=
None
errors
[
'admin_user'
]
.
append
(
_
(
'Invalid admin user'
))
v
=
get_object_or_none
(
AdminUser
,
id
=
v
)
elif
k
==
'groups'
:
groups_id
=
raw_data
.
getlist
(
k
)
v
=
[
AssetGroup
.
objects
.
filter
(
id__in
=
groups_id
)]
elif
k
==
'idc'
:
idc_id
=
raw_data
.
get
(
k
)
try
:
v
=
int
(
idc_id
)
except
ValueError
:
v
=
None
errors
[
'idc'
]
.
append
(
_
(
'Integer required'
))
v
=
get_object_or_none
(
IDC
,
id
=
v
)
else
:
v
=
raw_data
.
get
(
k
)
data
[
k
]
=
v
if
not
errors
:
for
asset
in
data
[
'assets'
]:
for
k
,
v
in
data
.
items
():
if
k
==
'groups'
:
asset
.
groups
.
set
(
data
[
'groups'
])
else
:
setattr
(
asset
,
k
,
v
)
asset
.
save
()
return
redirect
(
reverse_lazy
(
'assets:asset-list'
))
form
=
self
.
form_class
(
request
.
POST
)
if
form
.
is_valid
():
form
.
save
()
return
redirect
(
self
.
success_url
)
else
:
return
self
.
get
(
request
,
errors
=
errors
,
*
args
,
**
kwargs
)
return
self
.
get
(
request
,
form
=
form
,
*
args
,
**
kwargs
)
def
get_context_data
(
self
,
**
kwargs
):
# assets_list = Asset.objects.filter(id__in=self.assets_id_list)
...
...
@@ -181,7 +143,6 @@ class AssetBulkUpdateView(AdminUserRequiredMixin, ListView):
'app'
:
'Assets'
,
'action'
:
'Bulk update asset'
,
'form'
:
self
.
form
,
'errors'
:
self
.
errors
,
'assets_selected'
:
self
.
assets_id_list
,
'assets'
:
Asset
.
objects
.
all
(),
}
...
...
@@ -236,9 +197,6 @@ class AssetDetailView(DetailView):
return
super
(
AssetDetailView
,
self
)
.
get_context_data
(
**
kwargs
)
@method_decorator
(
csrf_exempt
,
name
=
'dispatch'
)
class
AssetExportView
(
View
):
def
get
(
self
,
request
,
*
args
,
**
kwargs
):
...
...
apps/users/forms.py
View file @
695e4da8
...
...
@@ -114,15 +114,44 @@ class UserPublicKeyForm(forms.Form):
return
self
.
instance
# class UserBulkImportForm(forms.ModelForm):
# class Meta:
# model = User
# fields = ['username', 'email', 'enable_otp', 'role']
class
UserBulkUpdateForm
(
forms
.
ModelForm
):
role
=
forms
.
ChoiceField
(
label
=
_
(
'Role'
),
choices
=
[(
'Admin'
,
'Administrator'
),
(
'User'
,
'User'
)],
)
users
=
forms
.
MultipleChoiceField
(
required
=
True
,
help_text
=
'* required'
,
label
=
_
(
'Select users'
),
choices
=
[(
user
.
id
,
user
.
name
)
for
user
in
User
.
objects
.
all
()],
widget
=
forms
.
SelectMultiple
(
attrs
=
{
'class'
:
'select2'
,
'data-placeholder'
:
_
(
'Select users'
)
}
)
)
class
Meta
:
model
=
User
fields
=
[
'role'
,
'groups'
,
'date_expired'
,
'is_active'
,
'enable_otp'
]
fields
=
[
'users'
,
'role'
,
'groups'
,
'date_expired'
,
'is_active'
,
'enable_otp'
]
widgets
=
{
'groups'
:
forms
.
SelectMultiple
(
attrs
=
{
'class'
:
'select2'
,
'data-placeholder'
:
_
(
'Select user groups'
)}),
}
def
save
(
self
,
commit
=
True
):
cleaned_data
=
{
k
:
v
for
k
,
v
in
self
.
cleaned_data
.
items
()
if
v
is
not
None
}
users_id
=
cleaned_data
.
pop
(
'users'
)
groups
=
cleaned_data
.
pop
(
'groups'
)
users
=
User
.
objects
.
filter
(
id__in
=
users_id
)
users
.
update
(
**
cleaned_data
)
if
groups
:
for
user
in
users
:
user
.
groups
.
set
(
groups
)
return
users
class
UserGroupForm
(
forms
.
ModelForm
):
...
...
apps/users/templates/users/_user_bulk_update_modal.html
View file @
695e4da8
...
...
@@ -5,33 +5,68 @@
{% block modal_class %}modal-lg{% endblock %}
{% block modal_title%}{% trans "Update selected user" %}{% endblock %}
{% block modal_body %}
<div
class=
"ydxbd"
id=
"ydxbd"
style=
"display: block;"
>
<div
>
<p
id=
"tags_p"
>
<a
href=
"/assets/asset-by-tag/5
"
>
<span
class=
"label label-default"
>
三年质保(0)
</span
>
</a>
<a
href=
"/assets/asset-by-tag/5"
>
<span
class=
"label label-default"
>
三年质保(0)
</span
>
</a>
</p>
{% block form %}
<div
class=
"ydxbd"
id=
"formlists"
style=
"display: block;"
>
<p
id=
"tags_p"
class=
"mgl-5 c02"
>
选择需要修改属性
</p
>
<div
class=
"tagBtnList
"
>
<a
class=
"label label-primary"
id=
"change_all"
value=
"1"
>
全选
</a
>
{% for field in form %}
{# {% if field.name != 'assets' %}#}
<a
data-id=
"{{ field.id_for_label }}"
class=
"label label-default label-primary field-tag"
value=
"1"
>
{{ field.label }}
</a
>
{# {% endif %}#}
{% endfor %}
</div>
</div>
<form
method=
"post"
class=
"form-horizontal"
action=
""
id=
"fm_user_bulk_update"
>
{# {% for field in form %}#}
{#
<input
type=
"checkbox"
>
#}
{# {% bootstrap_field field layout='horizontal' %}#}
{# {% endfor %}#}
{% bootstrap_form form layout='horizontal' %}
{#
<div
class=
"form-group"
>
#}
{#
<div
class=
"col-sm-9 col-lg-9 col-sm-offset-2"
>
#}
{#
<div
class=
"checkbox"
>
#}
{#
<input
type=
"checkbox"
name=
"enable_otp"
checked
id=
"id_enable_otp"
disabled
><label
for=
"id_enable_otp"
>
{% trans 'Enable-OTP' %}
</label>
#}
{#
</div>
#}
{#
</div>
#}
{#
</div>
#}
<form
method=
"post"
class=
"form-horizontal"
id=
"add_form"
>
{% csrf_token %}
{% bootstrap_form form layout="horizontal" %}
<div
class=
"form-group abc"
>
<div
class=
"col-sm-4 col-sm-offset-2"
>
<button
class=
"btn btn-white"
type=
"reset"
>
{% trans 'Reset' %}
</button>
<button
class=
"btn btn-primary"
type=
"submit"
>
{% trans 'Submit' %}
</button>
</div>
</div>
</form>
{% endblock %}
{% block modal_confirm_id %}btn_user_bulk_update{% endblock %}
{% endblock %}
{#{% block custom_foot_js %}#}
{#
<script>
#
}
{
#
$
(
document
).
ready
(
function
()
{
#
}
{
#
$
(
'.select2'
).
select2
();
#
}
{
#
}).
on
(
'click'
,
'.field-tag'
,
function
()
{
#
}
{
#
changeField
(
this
);
#
}
{
#
}).
on
(
'click'
,
'#change_all'
,
function
()
{
#
}
{
#
var
tag_fields
=
$
(
'.field-tag'
);
#
}
{
#
var
$this
=
$
(
this
);
#
}
{
#
var
active
=
'1'
;
#
}
{
#
if
(
$this
.
attr
(
'value'
)
==
'0'
){
#
}
{
#
active
=
'0'
;
#
}
{
#
$this
.
attr
(
'value'
,
'1'
).
addClass
(
'label-primary'
)
#
}
{
#
}
else
{
#
}
{
#
active
=
'1'
;
#
}
{
#
$this
.
attr
(
'value'
,
'0'
).
removeClass
(
'label-primary'
)
#
}
{
#
}
#
}
{
#
$
.
each
(
tag_fields
,
function
(
k
,
v
)
{
#
}
{
#
changeField
(
v
,
active
)
#
}
{
#
})
#
}
{
#
});
#
}
{
##
}
{
#
function
changeField
(
obj
,
active
)
{
#
}
{
#
var
$this
=
$
(
obj
);
#
}
{
#
var
field_id
=
$this
.
data
(
'id'
);
#
}
{
#
if
(
!
active
)
{
#
}
{
#
active
=
$this
.
attr
(
'value'
);
#
}
{
#
}
#
}
{
#
if
(
active
==
'0'
)
{
#
}
{
#
$this
.
attr
(
'value'
,
'1'
).
addClass
(
'label-primary'
);
#
}
{
#
var
form_groups
=
$
(
'#add_form .form-group:not(.abc)'
);
#
}
{
#
form_groups
.
filter
(
':has(#'
+
field_id
+
')'
).
show
().
find
(
'select,input'
).
prop
(
'disabled'
,
false
)
#
}
{
#
}
else
{
#
}
{
#
$this
.
attr
(
'value'
,
'0'
).
removeClass
(
'label-primary'
);
#
}
{
#
var
form_groups
=
$
(
'#add_form .form-group:not(.abc)'
);
#
}
{
#
form_groups
.
filter
(
':has(#'
+
field_id
+
')'
).
hide
().
find
(
'select,input'
).
prop
(
'disabled'
,
true
)
#
}
{
#
}
#
}
{
#
}
#
}
{
#
</script>
#}
{#{% endblock %}#}
apps/users/templates/users/user_bulk_update.html
0 → 100644
View file @
695e4da8
{% extends '_base_create_update.html' %}
{% load static %}
{% load bootstrap3 %}
{% load i18n %}
{% block form %}
<div
class=
"ydxbd"
id=
"formlists"
style=
"display: block;"
>
<p
id=
"tags_p"
class=
"mgl-5 c02"
>
选择需要修改属性
</p>
<div
class=
"tagBtnList"
>
<a
class=
"label label-primary"
id=
"change_all"
value=
"1"
>
全选
</a>
{% for field in form %}
{% if field.name != 'users' %}
<a
data-id=
"{{ field.id_for_label }}"
class=
"label label-default label-primary field-tag"
value=
"1"
>
{{ field.label }}
</a>
{% endif %}
{% endfor %}
</div>
</div>
<form
method=
"post"
class=
"form-horizontal"
id=
"add_form"
>
{% csrf_token %}
{% bootstrap_form form layout="horizontal" %}
<div
class=
"form-group abc"
>
<div
class=
"col-sm-4 col-sm-offset-2"
>
<button
class=
"btn btn-white"
type=
"reset"
>
{% trans 'Reset' %}
</button>
<button
class=
"btn btn-primary"
type=
"submit"
>
{% trans 'Submit' %}
</button>
</div>
</div>
</form>
{% endblock %}
{% block custom_foot_js %}
<script>
$
(
document
).
ready
(
function
()
{
$
(
'.select2'
).
select2
();
}).
on
(
'click'
,
'.field-tag'
,
function
()
{
changeField
(
this
);
}).
on
(
'click'
,
'#change_all'
,
function
()
{
var
tag_fields
=
$
(
'.field-tag'
);
var
$this
=
$
(
this
);
var
active
=
'1'
;
if
(
$this
.
attr
(
'value'
)
==
'0'
){
active
=
'0'
;
$this
.
attr
(
'value'
,
'1'
).
addClass
(
'label-primary'
)
}
else
{
active
=
'1'
;
$this
.
attr
(
'value'
,
'0'
).
removeClass
(
'label-primary'
)
}
$
.
each
(
tag_fields
,
function
(
k
,
v
)
{
changeField
(
v
,
active
)
})
});
function
changeField
(
obj
,
active
)
{
var
$this
=
$
(
obj
);
var
field_id
=
$this
.
data
(
'id'
);
if
(
!
active
)
{
active
=
$this
.
attr
(
'value'
);
}
if
(
active
==
'0'
)
{
$this
.
attr
(
'value'
,
'1'
).
addClass
(
'label-primary'
);
var
form_groups
=
$
(
'#add_form .form-group'
);
form_groups
.
filter
(
':has(#'
+
field_id
+
')'
).
show
().
find
(
'select,input'
).
prop
(
'disabled'
,
false
)
}
else
{
$this
.
attr
(
'value'
,
'0'
).
removeClass
(
'label-primary'
);
var
form_groups
=
$
(
'#add_form .form-group'
);
form_groups
.
filter
(
':has(#'
+
field_id
+
')'
).
hide
().
find
(
'select,input'
).
prop
(
'disabled'
,
true
)
}
}
</script>
{% endblock %}
apps/users/templates/users/user_list.html
View file @
695e4da8
...
...
@@ -55,6 +55,22 @@
{% block custom_foot_js %}
<script
src=
"{% static 'js/jquery.form.min.js' %}"
></script>
<script>
function
changeField
(
obj
,
active
)
{
var
$this
=
$
(
obj
);
var
field_id
=
$this
.
data
(
'id'
);
if
(
!
active
)
{
active
=
$this
.
attr
(
'value'
);
}
if
(
active
==
'0'
)
{
$this
.
attr
(
'value'
,
'1'
).
addClass
(
'label-primary'
);
var
form_groups
=
$
(
'#add_form .form-group:not(.abc)'
);
form_groups
.
filter
(
':has(#'
+
field_id
+
')'
).
show
().
find
(
'select,input'
).
prop
(
'disabled'
,
false
)
}
else
{
$this
.
attr
(
'value'
,
'0'
).
removeClass
(
'label-primary'
);
var
form_groups
=
$
(
'#add_form .form-group:not(.abc)'
);
form_groups
.
filter
(
':has(#'
+
field_id
+
')'
).
hide
().
find
(
'select,input'
).
prop
(
'disabled'
,
true
)
}
}
function
renderTable
()
{
var
options
=
{
...
...
@@ -193,7 +209,9 @@ $(document).ready(function(){
});
}
function
doUpdate
()
{
$
(
'#user_bulk_update_modal'
).
modal
(
'show'
);
var
users_id
=
plain_id_list
.
join
(
','
);
var
url
=
"{% url 'users:user-bulk-update' %}?users_id="
+
users_id
;
location
.
href
=
url
}
switch
(
action
)
{
case
'deactive'
:
...
...
@@ -249,10 +267,9 @@ $(document).ready(function(){
$
(
'#user_list_table'
).
DataTable
().
ajax
.
reload
();
jumpserver
.
checked
=
false
;
};
console
.
log
(
body
);
{
#
APIUpdateAttr
({
url
:
the_url
,
method
:
'PATCH'
,
body
:
JSON
.
stringify
(
post_list
),
success
:
success
});
#
}
$
(
'#user_bulk_update_modal'
).
modal
(
'hide'
);
})
;
})
</script>
{% endblock %}
apps/users/urls/views_urls.py
View file @
695e4da8
...
...
@@ -22,14 +22,11 @@ urlpatterns = [
name
=
'reset-password-success'
),
# Profile
url
(
r'^profile/$'
,
views
.
UserProfileView
.
as_view
(),
url
(
r'^profile/$'
,
views
.
UserProfileView
.
as_view
(),
name
=
'user-profile'
),
url
(
r'^profile/update/$'
,
views
.
UserProfileUpdateView
.
as_view
(),
url
(
r'^profile/update/$'
,
views
.
UserProfileUpdateView
.
as_view
(),
name
=
'user-profile-update'
),
url
(
r'^profile/password/update/$'
,
views
.
UserPasswordUpdateView
.
as_view
(),
url
(
r'^profile/password/update/$'
,
views
.
UserPasswordUpdateView
.
as_view
(),
name
=
'user-password-update'
),
url
(
r'^profile/pubkey/update/$'
,
views
.
UserPublicKeyUpdateView
.
as_view
(),
...
...
@@ -48,37 +45,29 @@ urlpatterns = [
url
(
r'^user/(?P<pk>[0-9]+)/assets'
,
views
.
UserGrantedAssetView
.
as_view
(),
name
=
'user-granted-asset'
),
url
(
r'^user/(?P<pk>[0-9]+)/login-history'
,
views
.
UserDetailView
.
as_view
(),
url
(
r'^user/(?P<pk>[0-9]+)/login-history'
,
views
.
UserDetailView
.
as_view
(),
name
=
'user-login-history'
),
url
(
r'^user/export/'
,
views
.
UserExportView
.
as_view
(),
url
(
r'^user/export/'
,
views
.
UserExportView
.
as_view
(),
name
=
'user-export'
),
url
(
r'^first-login/$'
,
views
.
UserFirstLoginView
.
as_view
(),
url
(
r'^first-login/$'
,
views
.
UserFirstLoginView
.
as_view
(),
name
=
'user-first-login'
),
url
(
r'^user/import/$'
,
views
.
UserBulkImportView
.
as_view
(),
url
(
r'^user/import/$'
,
views
.
UserBulkImportView
.
as_view
(),
name
=
'user-import'
),
url
(
r'^user/create$'
,
views
.
UserCreateView
.
as_view
(),
url
(
r'^user/create$'
,
views
.
UserCreateView
.
as_view
(),
name
=
'user-create'
),
url
(
r'^user/(?P<pk>[0-9]+)/update$'
,
views
.
UserUpdateView
.
as_view
(),
url
(
r'^user/(?P<pk>[0-9]+)/update$'
,
views
.
UserUpdateView
.
as_view
(),
name
=
'user-update'
),
url
(
r'^user/update$'
,
views
.
UserBulkUpdateView
.
as_view
(),
name
=
'user-bulk-update'
),
# User group view
url
(
r'^user-group$'
,
views
.
UserGroupListView
.
as_view
(),
url
(
r'^user-group$'
,
views
.
UserGroupListView
.
as_view
(),
name
=
'user-group-list'
),
url
(
r'^user-group/(?P<pk>[0-9]+)$'
,
views
.
UserGroupDetailView
.
as_view
(),
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
(),
url
(
r'^user-group/create$'
,
views
.
UserGroupCreateView
.
as_view
(),
name
=
'user-group-create'
),
url
(
r'^user-group/(?P<pk>[0-9]+)/update$'
,
views
.
UserGroupUpdateView
.
as_view
(),
url
(
r'^user-group/(?P<pk>[0-9]+)/update$'
,
views
.
UserGroupUpdateView
.
as_view
(),
name
=
'user-group-update'
),
url
(
r'^user-group/(?P<pk>[0-9]+)/asset-permission$'
,
views
.
UserGroupAssetPermissionView
.
as_view
(),
...
...
apps/users/views/user.py
View file @
695e4da8
...
...
@@ -38,7 +38,7 @@ __all__ = ['UserListView', 'UserCreateView', 'UserDetailView',
'UserAssetPermissionView'
,
'UserGrantedAssetView'
,
'UserExportView'
,
'UserBulkImportView'
,
'UserProfileView'
,
'UserProfileUpdateView'
,
'UserPasswordUpdateView'
,
'UserPublicKeyUpdateView'
,
'UserPublicKeyUpdateView'
,
'UserBulkUpdateView'
,
]
logger
=
get_logger
(
__name__
)
...
...
@@ -107,6 +107,46 @@ class UserUpdateView(AdminUserRequiredMixin, UpdateView):
return
context
class
UserBulkUpdateView
(
AdminUserRequiredMixin
,
ListView
):
model
=
User
form_class
=
forms
.
UserBulkUpdateForm
template_name
=
'users/user_bulk_update.html'
success_url
=
reverse_lazy
(
'users:user-list'
)
def
get
(
self
,
request
,
*
args
,
**
kwargs
):
users_id
=
self
.
request
.
GET
.
get
(
'users_id'
,
''
)
self
.
id_list
=
[
int
(
i
)
for
i
in
users_id
.
split
(
','
)
if
i
.
isdigit
()]
if
kwargs
.
get
(
'form'
):
self
.
form
=
kwargs
[
'form'
]
elif
users_id
:
self
.
form
=
self
.
form_class
(
initial
=
{
'users'
:
self
.
id_list
}
)
else
:
self
.
form
=
self
.
form_class
()
return
super
(
UserBulkUpdateView
,
self
)
.
get
(
request
,
*
args
,
**
kwargs
)
def
post
(
self
,
request
,
*
args
,
**
kwargs
):
form
=
self
.
form_class
(
request
.
POST
)
if
form
.
is_valid
():
form
.
save
()
return
redirect
(
self
.
success_url
)
else
:
return
self
.
get
(
request
,
form
=
form
,
*
args
,
**
kwargs
)
def
get_context_data
(
self
,
**
kwargs
):
context
=
{
'app'
:
'Assets'
,
'action'
:
'Bulk update asset'
,
'form'
:
self
.
form
,
'users_selected'
:
self
.
id_list
,
'users'
:
User
.
objects
.
all
(),
}
kwargs
.
update
(
context
)
return
super
(
UserBulkUpdateView
,
self
)
.
get_context_data
(
**
kwargs
)
class
UserDetailView
(
AdminUserRequiredMixin
,
DetailView
):
model
=
User
template_name
=
'users/user_detail.html'
...
...
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