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
43fe9851
Commit
43fe9851
authored
9 years ago
by
Administrator
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
添加组授权
parent
699046da
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
372 additions
and
68 deletions
+372
-68
perm_api.py
jperm/perm_api.py
+60
-51
urls.py
jperm/urls.py
+2
-0
views.py
jperm/views.py
+0
-0
mytags.py
jumpserver/templatetags/mytags.py
+51
-2
models.py
juser/models.py
+2
-0
user_perm.yaml
playbook/user_perm.yaml
+13
-11
perm_group_edit.html
templates/jperm/perm_group_edit.html
+156
-0
perm_group_list.html
templates/jperm/perm_group_list.html
+82
-0
perm_user_list.html
templates/jperm/perm_user_list.html
+5
-3
nav.html
templates/nav.html
+1
-1
No files found.
jperm/perm_api.py
View file @
43fe9851
...
...
@@ -11,6 +11,7 @@ from jumpserver.models import Setting
def
get_object_list
(
model
,
id_list
):
"""根据id列表获取对象列表"""
object_list
=
[]
for
object_id
in
id_list
:
if
object_id
:
...
...
@@ -19,51 +20,69 @@ def get_object_list(model, id_list):
return
object_list
def
perm_user_handle
(
user
,
asset_new
,
asset_del
,
group_new
,
group_del
):
username
=
user
.
name
asset_group_new
=
get_object_list
(
AssetGroup
,
group_new
)
asset_group_del
=
get_object_list
(
AssetGroup
,
group_del
)
for
asset_group
in
asset_group_new
:
asset_new
.
extend
([
asset
.
ip
for
asset
in
asset_group
.
asset_set
.
all
()])
for
asset_group
in
asset_group_del
:
asset_del
.
extend
(
asset
.
ip
for
asset
in
asset_group
.
asset_set
.
all
())
def
get_rand_file_path
(
base_dir
=
os
.
path
.
join
(
BASE_DIR
,
'tmp'
)):
"""获取随机文件路径"""
filename
=
uuid
.
uuid1
()
.
hex
return
os
.
path
.
join
(
base_dir
,
filename
)
def
get_inventory
(
host_group
):
"""生成资产表库存清单"""
path
=
get_rand_file_path
()
f
=
open
(
path
,
'w'
)
for
group
,
host_list
in
host_group
.
items
():
f
.
write
(
'[
%
s]
\n
'
%
group
)
for
ip
in
host_list
:
asset
=
get_object
(
Asset
,
ip
=
ip
)
if
asset
.
use_default
_auth
:
f
.
write
(
'
%
s
ansbile_ssh_port=
%
s
\n
'
%
(
ip
,
asset
.
port
)
)
if
asset
.
use_default
:
f
.
write
(
'
%
s
\n
'
%
ip
)
else
:
f
.
write
(
'
%
s ansible_ssh_port=
%
s ansible_ssh_user=
%
s ans
bile_ssh_pass=
%
s
\n
'
%
(
ip
,
asset
.
port
,
asset
.
username
,
CRYPTOR
.
decrypt
(
asset
.
password
)))
f
.
write
(
'
%
s ansible_ssh_port=
%
s ansible_ssh_user=
%
s ans
ible_ssh_pass=
%
s
\n
'
%
(
ip
,
asset
.
port
,
asset
.
username
,
CRYPTOR
.
decrypt
(
asset
.
password
)))
f
.
close
()
return
path
def
get_playbook
(
tempate
,
var
):
str_playbook
=
open
(
tempate
)
.
read
()
def
get_playbook
(
template
,
var
):
"""根据playbook模板,生成playbook"""
str_playbook
=
open
(
template
)
.
read
()
for
k
,
v
in
var
.
items
():
str_playbook
=
re
.
sub
(
r'
%
s'
%
k
,
v
,
str_playbook
)
str_playbook
=
re
.
sub
(
r'
%
s'
%
k
,
v
,
str_playbook
)
# 正则来替换传入的字符
path
=
get_rand_file_path
()
f
=
open
(
path
,
'w'
)
f
.
write
(
str_playbook
)
return
path
def
perm_user_api
(
user
,
asset_new
,
asset_del
,
asset_group_new
,
asset_group_del
):
asset_new_ip
=
[]
asset_del_ip
=
[]
def
playbook_run
(
inventory
,
playbook
,
default_user
=
None
,
default_port
=
None
,
default_pri_key_path
=
None
):
stats
=
callbacks
.
AggregateStats
()
playbook_cb
=
callbacks
.
PlaybookCallbacks
(
verbose
=
utils
.
VERBOSITY
)
runner_cb
=
callbacks
.
PlaybookRunnerCallbacks
(
stats
,
verbose
=
utils
.
VERBOSITY
)
# run the playbook
results
=
PlayBook
(
host_list
=
inventory
,
playbook
=
playbook
,
forks
=
5
,
remote_user
=
default_user
,
remote_port
=
default_port
,
private_key_file
=
default_pri_key_path
,
callbacks
=
playbook_cb
,
runner_callbacks
=
runner_cb
,
stats
=
stats
,
become
=
True
,
become_user
=
'root'
)
.
run
()
for
hostname
,
result
in
results
.
items
():
if
result
.
get
(
'failures'
,
2
):
print
"
%
s >>> Failed"
%
hostname
else
:
print
"
%
s >>> Success"
%
hostname
return
results
def
perm_user_api
(
asset_new
,
asset_del
,
asset_group_new
,
asset_group_del
,
user
=
None
,
user_group
=
None
):
"""用户授权api,通过调用ansible API完成用户新建等"""
asset_new_ip
=
[]
# 新授权的ip列表
asset_del_ip
=
[]
# 回收授权的ip列表
if
''
in
asset_group_new
:
asset_group_new
.
remove
(
''
)
...
...
@@ -71,48 +90,38 @@ def perm_user_api(user, asset_new, asset_del, asset_group_new, asset_group_del):
if
''
in
asset_group_del
:
asset_group_del
.
remove
(
''
)
asset_new_ip
.
extend
([
asset
.
ip
for
asset
in
get_object_list
(
Asset
,
asset_new
)])
asset_new_ip
.
extend
([
asset
.
ip
for
asset
in
get_object_list
(
Asset
,
asset_new
)])
# 查库,获取新授权ip
for
asset_group_id
in
asset_group_new
:
asset_new_ip
.
extend
([
asset
.
ip
for
asset
in
get_object
(
AssetGroup
,
id
=
asset_group_id
)
.
asset_set
.
all
()])
asset_del_ip
.
extend
([
asset
.
ip
for
asset
in
get_object_list
(
Asset
,
asset_del
)])
asset_new_ip
.
extend
([
asset
.
ip
for
asset
in
get_object
(
AssetGroup
,
id
=
asset_group_id
)
.
asset_set
.
all
()])
# 同理
asset_del_ip
.
extend
([
asset
.
ip
for
asset
in
get_object_list
(
Asset
,
asset_del
)])
# 查库,获取回收授权的ip
for
asset_group_id
in
asset_group_del
:
asset_del_ip
.
extend
([
asset
.
ip
for
asset
in
get_object
(
AssetGroup
,
id
=
asset_group_id
)
.
asset_set
.
all
()])
asset_del_ip
.
extend
([
asset
.
ip
for
asset
in
get_object
(
AssetGroup
,
id
=
asset_group_id
)
.
asset_set
.
all
()])
# 同理
print
asset_new_ip
print
asset_del_ip
stats
=
callbacks
.
AggregateStats
()
playbook_cb
=
callbacks
.
PlaybookCallbacks
(
verbose
=
utils
.
VERBOSITY
)
runner_cb
=
callbacks
.
PlaybookRunnerCallbacks
(
stats
,
verbose
=
utils
.
VERBOSITY
)
if
asset_new_ip
or
asset_del_ip
:
host_group
=
{
'new'
:
asset_new_ip
,
'del'
:
asset_del_ip
}
host_list
=
get_inventory
(
host_group
)
inventory
=
get_inventory
(
host_group
)
if
user
:
the_items
=
user
.
username
,
elif
user_group
:
users
=
user_group
.
user_set
.
all
()
the_items
=
','
.
join
([
user
.
username
for
user
in
users
])
else
:
return
HttpResponse
(
'Argument error.'
)
playbook
=
get_playbook
(
os
.
path
.
join
(
BASE_DIR
,
'playbook'
,
'user_perm.yaml'
),
{
'the_new_group'
:
'new'
,
'the_del_group'
:
'del'
,
'the_user'
:
user
.
username
,
'the_pub_key'
:
'/tmp/id_rsa.pub'
})
'the_items'
:
the_items
,
'the_pub_key'
:
'/tmp/id_rsa.pub'
})
settings
=
get_object
(
Setting
,
id
=
1
)
if
settings
:
default_user
=
settings
.
default_user
default_port
=
settings
.
default_port
default_pri_key_path
=
settings
.
default_pri_key_path
else
:
default_user
=
default_pri_key_path
=
''
results
=
PlayBook
(
host_list
=
host_list
,
playbook
=
playbook
,
forks
=
5
,
remote_user
=
default_user
,
private_key_file
=
default_pri_key_path
,
callbacks
=
playbook_cb
,
runner_callbacks
=
runner_cb
,
stats
=
stats
,
become
=
True
,
become_user
=
'root'
)
.
run
()
for
hostname
,
result
in
results
.
items
():
if
result
.
get
(
'failures'
,
2
):
print
"
%
s >>> Failed"
%
hostname
else
:
print
"
%
s >>> Success"
%
hostname
default_user
=
default_port
=
default_pri_key_path
=
''
results
=
playbook_run
(
inventory
,
playbook
,
default_user
,
default_port
,
default_pri_key_path
)
return
results
This diff is collapsed.
Click to expand it.
jperm/urls.py
View file @
43fe9851
...
...
@@ -5,6 +5,8 @@ urlpatterns = patterns('jperm.views',
# Examples:
(
r'^user/$'
,
perm_user_list
),
(
r'^perm_user_edit/$'
,
perm_user_edit
),
(
r'^group/$'
,
perm_group_list
),
(
r'^perm_group_edit/$'
,
perm_group_edit
),
# (r'^dept_perm_edit/$', 'dept_perm_edit'),
# (r'^perm_list/$', view_splitter, {'su': perm_list, 'adm': perm_list_adm}),
# (r'^dept_perm_list/$', 'dept_perm_list'),
...
...
This diff is collapsed.
Click to expand it.
jperm/views.py
View file @
43fe9851
This diff is collapsed.
Click to expand it.
jumpserver/templatetags/mytags.py
View file @
43fe9851
...
...
@@ -54,8 +54,8 @@ def get_role(user_id):
# return "%s ..." % ' '.join(groups[0:2])
#
@register.filter
(
name
=
'group
_str2
'
)
def
groups
_str2
(
group_list
):
@register.filter
(
name
=
'group
s2str
'
)
def
groups
2str
(
group_list
):
"""
将用户组列表转换为str
"""
...
...
@@ -64,6 +64,55 @@ def groups_str2(group_list):
else
:
return
'
%
s ...'
%
' '
.
join
([
group
.
name
for
group
in
group_list
[
0
:
2
]])
@register.filter
(
name
=
'user_asset_count'
)
def
user_asset_count
(
user
):
"""
返回用户权限主机的数量
"""
assets_id
=
user
.
assets
.
split
(
','
)
asset_groups
=
user
.
asset_groups
.
split
(
','
)
for
asset_group_id
in
asset_groups
:
asset_group
=
get_object
(
AssetGroup
,
id
=
asset_group_id
)
if
asset_group
:
assets_id
.
extend
(
asset
.
id
for
asset
in
asset_group
.
asset_set
.
all
())
assets_id
=
set
(
map
(
str
,
assets_id
))
return
len
(
assets_id
)
@register.filter
(
name
=
'user_asset_group_count'
)
def
user_asset_group_count
(
user
):
"""
返回用户权限主机组的数量
"""
return
len
(
filter
(
lambda
x
:
x
,
user
.
asset_groups
.
split
(
','
)))
#
# @register.filter(name='user_group_asset_count')
# def user_group_asset_count(user_group):
# """
# 返回用户组权限主机的数量
# """
# assets_id = user_group.assets.split(',')
# asset_groups = user_group.asset_groups.split(',')
#
# for asset_group_id in asset_groups:
# asset_group = get_object(AssetGroup, id=asset_group_id)
# if asset_group:
# assets_id.extend(asset.id for asset in asset_group.asset_set.all())
#
# assets_id = set(map(str, assets_id))
# return len(assets_id)
#
#
# @register.filter(name='user_group_asset_count')
# def user_group_asset_group_count(user_group):
# """
# 返回用户组权限主机组的数量
# """
# return len(user_group.asset_groups.split(','))
#
# @register.filter(name='group_str2_all')
# def group_str2_all(group_list):
...
...
This diff is collapsed.
Click to expand it.
juser/models.py
View file @
43fe9851
...
...
@@ -5,6 +5,8 @@ from django.db import models
class
UserGroup
(
models
.
Model
):
name
=
models
.
CharField
(
max_length
=
80
,
unique
=
True
)
assets
=
models
.
TextField
(
max_length
=
1000
,
verbose_name
=
"Assets"
,
default
=
''
)
asset_groups
=
models
.
CharField
(
max_length
=
1000
,
verbose_name
=
"Asset Groups"
,
default
=
''
)
comment
=
models
.
CharField
(
max_length
=
160
,
blank
=
True
,
null
=
True
)
def
__unicode__
(
self
):
...
...
This diff is collapsed.
Click to expand it.
playbook/user_perm.yaml
View file @
43fe9851
-
hosts
:
the_del_group
tasks
:
-
name
:
del user
user
:
name={{ item }} state=absent remove=yes
with_items
:
[
the_items
]
-
hosts
:
the_new_group
vars
:
user
:
the_user
tasks
:
-
name
:
add user
user
:
name={{ user }} state=present
user
:
name={{ item }} state=present
with_items
:
[
the_items
]
-
name
:
.ssh direcotory
file
:
name=/home/{{ user }}/.ssh mode=700 owner={{ user }} group={{ user }} state=directory
file
:
name=/home/{{ item }}/.ssh mode=700 owner={{ item }} group={{ item }} state=directory
with_items
:
[
the_items
]
-
name
:
set authorizied_file
copy
:
src=the_pub_key dest=/home/{{ user }}/.ssh/authorizied_keys owner={{ user }} group={{ user }} mode=600
copy
:
src=the_pub_key dest=/home/{{ item }}/.ssh/authorizied_keys owner={{ item }} group={{ item }} mode=600
with_items
:
[
the_items
]
-
hosts
:
the_del_group
vars
:
user
:
the_user
tasks
:
-
name
:
del user
user
:
name={{ user }} state=absent remove=yes
This diff is collapsed.
Click to expand it.
templates/jperm/perm_group_edit.html
0 → 100644
View file @
43fe9851
{% extends 'base.html' %}
{% load mytags %}
{% block content %}
{% include 'nav_cat_bar.html' %}
<div
class=
"wrapper wrapper-content animated fadeInRight"
>
<div
class=
"row"
>
<div
class=
"col-lg-10"
>
<div
class=
"ibox float-e-margins"
>
<div
class=
"ibox-title"
>
<h5>
{{ user_group.name }}授权修改
</h5>
<div
class=
"ibox-tools"
>
<a
class=
"collapse-link"
>
<i
class=
"fa fa-chevron-up"
></i>
</a>
<a
class=
"dropdown-toggle"
data-toggle=
"dropdown"
href=
"#"
>
<i
class=
"fa fa-wrench"
></i>
</a>
<a
class=
"close-link"
>
<i
class=
"fa fa-times"
></i>
</a>
</div>
</div>
<div
class=
"ibox-content"
>
<form
id=
"userPerm"
method=
"post"
class=
"form-horizontal"
action=
"../perm_group_edit/?id={{ user_group.id }}"
>
{% if error %}
<div
class=
"alert alert-warning text-center"
>
{{ error }}
</div>
{% endif %}
{% if msg %}
<div
class=
"alert alert-success text-center"
>
{{ msg }}
</div>
{% endif %}
<div
class=
"row"
>
<div
class=
"form-group"
>
<label
for=
""
class=
"col-sm-2 control-label"
>
用户组
<span
class=
"red-fonts"
>
*
</span></label>
<div
class=
"col-sm-4"
>
<input
id=
"user_group_name"
name=
"user_group_name"
type=
"text"
class=
"form-control"
value=
"{{ user_group.name }}"
readonly
>
</div>
</div>
<div
class=
"hr-line-dashed"
></div>
<div
class=
"form-group"
>
<label
for=
""
class=
"col-sm-2 control-label"
>
资产
<span
class=
"red-fonts"
>
*
</span></label>
<div
class=
"col-sm-4"
>
<div>
<select
id=
"assets"
name=
"assets"
class=
"form-control m-b"
size=
"12"
multiple
>
{% for asset in assets %}
<option
value=
"{{ asset.id }}"
>
{{ asset.ip }}
</option>
{% endfor %}
</select>
</div>
</div>
<div
class=
"col-sm-1"
>
<div
class=
"btn-group"
style=
"margin-top: 42px;"
>
<button
type=
"button"
class=
"btn btn-white"
onclick=
"move('assets', 'asset_select')"
><i
class=
"fa fa-chevron-right"
></i></button>
<button
type=
"button"
class=
"btn btn-white"
onclick=
"move('asset_select', 'assets')"
><i
class=
"fa fa-chevron-left"
></i>
</button>
</div>
</div>
<div
class=
"col-sm-3"
>
<div>
<select
id=
"asset_select"
name=
"asset_select"
class=
"form-control m-b"
size=
"12"
multiple
>
{% for asset in asset_permed %}
<option
value=
"{{ asset.id }}"
>
{{ asset.ip }}
</option>
{% endfor %}
</select>
</div>
</div>
</div>
<div
class=
"hr-line-dashed"
></div>
<div
class=
"form-group"
>
<label
for=
""
class=
"col-sm-2 control-label"
>
资产组
<span
class=
"red-fonts"
>
*
</span></label>
<div
class=
"col-sm-4"
>
<div>
<select
id=
"asset_groups"
name=
"asset_groups"
class=
"form-control m-b"
size=
"12"
multiple
>
{% for asset_group in asset_groups %}
<option
value=
"{{ asset_group.id }}"
>
{{ asset_group.name }}
</option>
{% endfor %}
</select>
</div>
</div>
<div
class=
"col-sm-1"
>
<div
class=
"btn-group"
style=
"margin-top: 42px;"
>
<button
type=
"button"
class=
"btn btn-white"
onclick=
"move('asset_groups', 'asset_groups_select')"
><i
class=
"fa fa-chevron-right"
></i></button>
<button
type=
"button"
class=
"btn btn-white"
onclick=
"move('asset_groups_select', 'asset_groups')"
><i
class=
"fa fa-chevron-left"
></i>
</button>
</div>
</div>
<div
class=
"col-sm-3"
>
<div>
<select
id=
"asset_groups_select"
name=
"asset_groups_select"
class=
"form-control m-b"
size=
"12"
multiple
>
{% for asset_group in asset_group_permed %}
<option
value=
"{{ asset_group.id }}"
>
{{ asset_group.name }}
</option>
{% endfor %}
</select>
</div>
</div>
</div>
</div>
<div
class=
"row"
>
<div
class=
"form-group"
>
<div
class=
"col-sm-4 col-sm-offset-2"
>
<button
class=
"btn btn-white"
type=
"reset"
>
取消
</button>
<button
id=
"submit_button"
class=
"btn btn-primary"
type=
"submit"
onclick=
"selectAllOption('userForm')"
>
确认保存
</button>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
<script>
$
(
'#sudoPerm'
).
validator
({
timely
:
2
,
theme
:
"yellow_right_effect"
,
fields
:
{
"name"
:
{
rule
:
"required"
,
tip
:
"输入授权名"
,
ok
:
""
,
msg
:
{
required
:
"必须填写!"
}
}
},
valid
:
function
(
form
)
{
form
.
submit
();
}
});
$
(
document
).
ready
(
function
(){
$
(
"#submit_button"
).
click
(
function
(){
$
(
'#user_groups_select option'
).
each
(
function
(){
$
(
this
).
prop
(
'selected'
,
true
)
})
$
(
'#asset_groups_select option'
).
each
(
function
(){
$
(
this
).
prop
(
'selected'
,
true
)
})
})
})
</script>
{% endblock %}
\ No newline at end of file
This diff is collapsed.
Click to expand it.
templates/jperm/perm_group_list.html
0 → 100644
View file @
43fe9851
{% extends 'base.html' %}
{% load mytags %}
{% block content %}
{% include 'nav_cat_bar.html' %}
<div
class=
"wrapper wrapper-content animated fadeInRight"
>
<div
class=
"row"
>
<div
class=
"col-lg-10"
>
<div
class=
"ibox float-e-margins"
>
<div
class=
"ibox-title"
>
<h5>
查看小组
</h5>
<div
class=
"ibox-tools"
>
<a
class=
"collapse-link"
>
<i
class=
"fa fa-chevron-up"
></i>
</a>
<a
class=
"dropdown-toggle"
data-toggle=
"dropdown"
href=
"#"
>
<i
class=
"fa fa-wrench"
></i>
</a>
<a
class=
"close-link"
>
<i
class=
"fa fa-times"
></i>
</a>
</div>
</div>
<div
class=
"ibox-content"
>
<div
class=
""
>
<a
target=
"_blank"
href=
"/juser/group_add/"
class=
"btn btn-sm btn-primary "
>
添加用户组
</a>
<form
id=
"search_form"
method=
"get"
action=
""
class=
"pull-right mail-search"
>
<div
class=
"input-group"
>
<input
type=
"text"
class=
"form-control input-sm"
id=
"search_input"
name=
"search"
placeholder=
"Search"
>
<div
class=
"input-group-btn"
>
<button
id=
'search_btn'
type=
"submit"
class=
"btn btn-sm btn-primary"
>
- 搜索 -
</button>
</div>
</div>
</form>
</div>
<table
class=
"table table-striped table-bordered table-hover "
id=
"editable"
>
<thead>
<tr>
<th
class=
"text-center"
>
用户组
</th>
<th
class=
"text-center"
>
成员
</th>
<th
class=
"text-center"
>
授权资产
</th>
<th
class=
"text-center"
>
授权资产组
</th>
<th
class=
"text-center"
>
操作
</th>
</tr>
</thead>
<tbody>
{% for user_group in user_groups.object_list %}
<tr
class=
"gradeX"
>
<td
class=
"text-center"
>
{{ user_group.name }}
</td>
<td
class=
"text-center"
>
<a
href=
"/juser/user_list/?gid={{ user_group.id }}"
>
{{ user_group.user_set.all | length }}
</a>
</td>
<td
class=
"text-center"
>
<a
href=
"/jasset/asset_list/?gid={{ user_group.id }}"
>
{{ user_group | user_asset_count }}
</a>
</td>
<td
class=
"text-center"
>
<a
href=
"/jasset/group_list/?gid={{ user_group.id }}"
>
{{ user_group | user_asset_group_count }}
</a></td>
<td
class=
"text-center"
>
<a
href=
"../perm_user_detail/?id={{ user_group.id }}"
class=
"btn btn-xs btn-primary"
>
详情
</a>
<a
href=
"../perm_group_edit/?id={{ user_group.id }}"
class=
"btn btn-xs btn-danger"
>
编辑
</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<div
class=
"row"
>
<div
class=
"col-sm-6"
>
<div
class=
"dataTables_info"
id=
"editable_info"
role=
"status"
aria-live=
"polite"
>
Showing {{ users.start_index }} to {{ users.end_index }} of {{ p.count }} entries
</div>
</div>
{% include 'paginator.html' %}
</div>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
\ No newline at end of file
This diff is collapsed.
Click to expand it.
templates/jperm/perm_user_list.html
View file @
43fe9851
...
...
@@ -51,9 +51,11 @@
{% for user in users.object_list %}
<tr
class=
"gradeX"
>
<td
class=
"text-center"
>
{{ user.name }}
</td>
<td
class=
"text-center"
>
<a
href=
"/juser/user_list/?gid={{ user.id }}"
>
{{ user.id }}
</a>
</td>
<td
class=
"text-center"
>
<a
href=
"/jasset/host_list/?gid={{ user.id }}"
>
{{ user.id }}
</a>
</td>
<td
class=
"text-center"
>
{{ user.comment }}
</td>
<td
class=
"text-center"
>
<a
href=
"/juser/user_list/?gid={{ user.id }}"
>
{{ user.group.all | groups2str }}
</a>
</td>
<td
class=
"text-center"
>
<a
href=
"/jasset/asset_list/?gid={{ user.id }}"
>
{{ user | user_asset_count }}
</a>
</td>
<td
class=
"text-center"
>
<a
href=
"/jasset/group_list/?gid={{ user.id }}"
>
{{ user | user_asset_group_count }}
</a></td>
<td
class=
"text-center"
>
<a
href=
"../perm_user_detail/?id={{ user.id }}"
class=
"btn btn-xs btn-primary"
>
详情
</a>
<a
href=
"../perm_user_edit/?id={{ user.id }}"
class=
"btn btn-xs btn-danger"
>
编辑
</a>
...
...
This diff is collapsed.
Click to expand it.
templates/nav.html
View file @
43fe9851
...
...
@@ -32,7 +32,7 @@
</li>
<li
class=
"perm_list perm_edit perm_detail"
>
<a
href=
"/jperm/
perm_list
/"
>
用户组授权
</a>
<a
href=
"/jperm/
group
/"
>
用户组授权
</a>
</li>
<li
class=
"sudo_list sudo_edit sudo_add cmd_list cmd_edit cmd_add sudo_detail"
>
...
...
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