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
2a645747
Commit
2a645747
authored
Jan 31, 2015
by
root
Browse files
Options
Browse Files
Download
Plain Diff
Merge in 20150131
parents
a8991bfb
deb55d3b
Hide whitespace changes
Inline
Side-by-side
Showing
40 changed files
with
1081 additions
and
563 deletions
+1081
-563
connect.py
connect.py
+8
-28
models.py
jasset/models.py
+2
-4
views.py
jasset/views.py
+2
-2
__init__.py
jperm/__init__.py
+0
-0
admin.py
jperm/admin.py
+0
-0
models.py
jperm/models.py
+12
-0
tests.py
jperm/tests.py
+0
-0
urls.py
jperm/urls.py
+5
-4
views.py
jperm/views.py
+104
-0
models.py
jpermission/models.py
+0
-20
views.py
jpermission/views.py
+0
-62
jumpserver.conf
jumpserver.conf
+1
-5
settings.py
jumpserver/settings.py
+1
-1
mytags.py
jumpserver/templatetags/mytags.py
+37
-6
urls.py
jumpserver/urls.py
+4
-2
views.py
jumpserver/views.py
+49
-3
models.py
juser/models.py
+8
-2
views.py
juser/views.py
+197
-150
style.css
static/css/style.css
+4
-1
logo.png
static/img/logo.png
+0
-0
base.html
templates/base.html
+3
-3
css_js.html
templates/css_js.html
+0
-34
perm_asset_detail.html
templates/jperm/perm_asset_detail.html
+42
-0
perm_detail.html
templates/jperm/perm_detail.html
+42
-0
perm_edit.html
templates/jperm/perm_edit.html
+139
-0
perm_list.html
templates/jperm/perm_list.html
+187
-48
perm_user_list.html
templates/jperm/perm_user_list.html
+0
-62
perm_user_show.html
templates/jperm/perm_user_show.html
+0
-62
group_add.html
templates/juser/group_add.html
+68
-2
group_detail.html
templates/juser/group_detail.html
+11
-12
group_list.html
templates/juser/group_list.html
+5
-3
user_add.html
templates/juser/user_add.html
+74
-9
user_detail.html
templates/juser/user_detail.html
+6
-5
user_list.html
templates/juser/user_list.html
+7
-6
link_css.html
templates/link_css.html
+1
-2
login.html
templates/login.html
+10
-7
nav.html
templates/nav.html
+2
-4
nav_bar_header.html
templates/nav_bar_header.html
+1
-1
nav_li_profile.html
templates/nav_li_profile.html
+2
-1
script.html
templates/script.html
+47
-12
No files found.
connect.py
View file @
2a645747
...
...
@@ -26,6 +26,7 @@ django.setup()
from
juser.models
import
User
from
jasset.models
import
Asset
from
jlog.models
import
Log
from
jperm.views
import
perm_user_asset
try
:
import
termios
...
...
@@ -208,15 +209,10 @@ def posix_shell(chan, username, host):
def
get_user_host
(
username
):
"""Get the hosts of under the user control."""
hosts_attr
=
{}
try
:
user
=
User
.
objects
.
get
(
username
=
username
)
except
ObjectDoesNotExist
:
raise
ServerError
(
"Username
\033
[1;31m
%
s
\033
[0m doesn't exist on Jumpserver."
%
username
)
else
:
perm_all
=
user
.
permission_set
.
all
()
for
perm
in
perm_all
:
hosts_attr
[
perm
.
asset
.
ip
]
=
[
perm
.
asset
.
id
,
perm
.
asset
.
comment
]
return
hosts_attr
asset_all
=
perm_user_asset
(
username
=
username
)
for
asset
in
asset_all
:
hosts_attr
[
asset
.
ip
]
=
[
asset
.
id
,
asset
.
comment
]
return
hosts_attr
def
get_connect_item
(
username
,
ip
):
...
...
@@ -235,34 +231,18 @@ def get_connect_item(username, ip):
login_type_dict
=
{
'L'
:
user
.
ldap_pwd
,
'S'
:
user
.
ssh_key_pwd2
,
'P'
:
user
.
ssh_pwd
,
}
if
asset
.
login_type
in
login_type_dict
:
password
=
cryptor
.
decrypt
(
login_type_dict
[
asset
.
login_type
])
return
username
,
password
,
ip
,
port
elif
asset
.
login_type
==
'M'
:
perms
=
asset
.
permission_set
.
filter
(
user
=
user
)
if
perms
:
perm
=
perms
[
0
]
else
:
raise
ServerError
(
'Permission
%
s to
%
s does not exist.'
%
(
username
,
ip
))
if
perm
.
role
==
'SU'
:
username_super
=
asset
.
username_super
password_super
=
cryptor
.
decrypt
(
asset
.
password_super
)
return
username_super
,
password_super
,
ip
,
port
elif
perm
.
role
==
'CU'
:
username_common
=
asset
.
username_common
password_common
=
asset
.
password_common
return
username_common
,
password_common
,
ip
,
port
username
=
asset
.
username
password
=
cryptor
.
decrypt
(
asset
.
password
)
return
username
,
password
,
ip
,
port
else
:
raise
ServerError
(
'Perm in
%
s for
%
s map role is not in ["SU", "CU"].'
%
(
ip
,
username
))
else
:
raise
ServerError
(
'Login type is not in ["L", "S", "P", "M"]'
)
...
...
jasset/models.py
View file @
2a645747
...
...
@@ -37,10 +37,8 @@ class Asset(models.Model):
user_group
=
models
.
ManyToManyField
(
UserGroup
)
bis_group
=
models
.
ManyToManyField
(
BisGroup
)
login_type
=
models
.
CharField
(
max_length
=
1
,
choices
=
LOGIN_TYPE_CHOICES
,
default
=
'L'
)
username_common
=
models
.
CharField
(
max_length
=
20
,
blank
=
True
,
null
=
True
)
password_common
=
models
.
CharField
(
max_length
=
80
,
blank
=
True
,
null
=
True
)
username_super
=
models
.
CharField
(
max_length
=
20
,
blank
=
True
,
null
=
True
)
password_super
=
models
.
CharField
(
max_length
=
80
,
blank
=
True
,
null
=
True
)
username
=
models
.
CharField
(
max_length
=
20
,
blank
=
True
,
null
=
True
)
password
=
models
.
CharField
(
max_length
=
80
,
blank
=
True
,
null
=
True
)
date_added
=
models
.
DateTimeField
(
auto_now
=
True
,
default
=
datetime
.
datetime
.
now
(),
null
=
True
)
is_active
=
models
.
BooleanField
(
default
=
True
)
comment
=
models
.
CharField
(
max_length
=
100
,
blank
=
True
,
null
=
True
)
...
...
jasset/views.py
View file @
2a645747
...
...
@@ -8,6 +8,7 @@ from models import IDC, Asset, BisGroup
from
juser.models
import
UserGroup
from
connect
import
PyCrypt
,
KEY
from
jumpserver.views
import
jasset_group_add
,
jasset_host_edit
from
jperm.models
import
Perm
cryptor
=
PyCrypt
(
KEY
)
...
...
@@ -237,4 +238,4 @@ def group_del(request, offset):
return
HttpResponseRedirect
(
'/jasset/group_list/'
)
def
test
(
request
):
return
render_to_response
(
'jasset/test.html'
,
locals
())
\ No newline at end of file
return
render_to_response
(
'jasset/test.html'
,
locals
())
jperm
ission
/__init__.py
→
jperm/__init__.py
View file @
2a645747
File moved
jperm
ission
/admin.py
→
jperm/admin.py
View file @
2a645747
File moved
jperm/models.py
0 → 100644
View file @
2a645747
from
django.db
import
models
from
juser.models
import
User
,
UserGroup
from
jasset.models
import
Asset
,
BisGroup
class
Perm
(
models
.
Model
):
user_group
=
models
.
ForeignKey
(
UserGroup
)
asset_group
=
models
.
ForeignKey
(
BisGroup
)
def
__unicode__
(
self
):
return
'
%
s_
%
s'
%
(
self
.
user_group
.
name
,
self
.
asset_group
.
name
)
\ No newline at end of file
jperm
ission
/tests.py
→
jperm/tests.py
View file @
2a645747
File moved
jperm
ission
/urls.py
→
jperm/urls.py
View file @
2a645747
from
django.conf.urls
import
patterns
,
include
,
url
urlpatterns
=
patterns
(
'jperm
ission
.views'
,
urlpatterns
=
patterns
(
'jperm.views'
,
# Examples:
# url(r'^$', 'jumpserver.views.home', name='home'),
# url(r'^blog/', include('blog.urls')),
(
r'^perm_user_list/$'
,
'perm_user_list'
),
(
r'^perm_add/$'
,
'perm_add'
),
(
r'^perm_user_show/$'
,
'perm_user_show'
),
(
r'^perm_edit/$'
,
'perm_edit'
),
(
r'^perm_list/$'
,
'perm_list'
),
(
r'^perm_detail/$'
,
'perm_detail'
),
(
r'^perm_del/$'
,
'perm_del'
),
(
r'^perm_asset_detail/$'
,
'perm_asset_detail'
),
)
jperm/views.py
0 → 100644
View file @
2a645747
# coding: utf-8
from
django.shortcuts
import
render_to_response
from
django.http
import
HttpResponseRedirect
,
HttpResponse
from
juser.models
import
User
,
UserGroup
from
jasset.models
import
Asset
,
BisGroup
from
jperm.models
import
Perm
from
django.core.paginator
import
Paginator
,
EmptyPage
,
InvalidPage
def
perm_group_update
(
user_group_name
=
''
,
user_group_id
=
''
,
asset_groups_name
=
''
,
asset_groups_id
=
''
):
if
user_group_name
:
user_group
=
UserGroup
.
objects
.
get
(
name
=
user_group_name
)
else
:
user_group
=
UserGroup
.
objects
.
get
(
id
=
user_group_id
)
Perm
.
objects
.
filter
(
user_group
=
user_group
)
.
delete
()
if
asset_groups_name
:
for
asset_group_name
in
asset_groups_name
:
asset_group
=
BisGroup
.
objects
.
get
(
name
=
asset_group_name
)
Perm
(
user_group
=
user_group
,
asset_group
=
asset_group
)
.
save
()
else
:
for
asset_group_id
in
asset_groups_id
:
asset_group
=
BisGroup
.
objects
.
get
(
id
=
asset_group_id
)
Perm
(
user_group
=
user_group
,
asset_group
=
asset_group
)
.
save
()
def
perm_user_asset
(
user_id
=
None
,
username
=
None
):
if
user_id
:
user
=
User
.
objects
.
get
(
id
=
user_id
)
else
:
user
=
User
.
objects
.
get
(
username
=
username
)
user_groups
=
user
.
user_group
.
all
()
perms
=
[]
assets
=
[]
for
user_group
in
user_groups
:
perm
=
user_group
.
perm_set
.
all
()
perms
.
extend
(
perm
)
asset_groups
=
[
perm
.
asset_group
for
perm
in
perms
]
for
asset_group
in
asset_groups
:
assets
.
extend
(
list
(
asset_group
.
asset_set
.
all
()))
return
list
(
set
(
assets
))
def
perm_list
(
request
):
header_title
,
path1
,
path2
=
u'主机授权 | Perm Host Detail.'
,
u'jperm'
,
u'perm_list'
groups
=
contact_list
=
UserGroup
.
objects
.
all
()
.
order_by
(
'type'
)
users
=
contact_list2
=
User
.
objects
.
all
()
.
order_by
(
'id'
)
p
=
paginator
=
Paginator
(
contact_list
,
10
)
p2
=
paginator2
=
Paginator
(
contact_list2
,
10
)
try
:
page
=
int
(
request
.
GET
.
get
(
'page'
,
'1'
))
except
ValueError
:
page
=
1
try
:
contacts
=
paginator
.
page
(
page
)
contacts2
=
paginator2
.
page
(
page
)
except
(
EmptyPage
,
InvalidPage
):
contacts
=
paginator
.
page
(
paginator
.
num_pages
)
contacts2
=
paginator2
.
page
(
paginator2
.
num_pages
)
return
render_to_response
(
'jperm/perm_list.html'
,
locals
())
def
perm_edit
(
request
):
if
request
.
method
==
'GET'
:
header_title
,
path1
,
path2
=
u'编辑授权 | Perm Host Edit.'
,
u'jperm'
,
u'perm_edit'
user_group_id
=
request
.
GET
.
get
(
'id'
)
user_group
=
UserGroup
.
objects
.
get
(
id
=
user_group_id
)
asset_groups
=
BisGroup
.
objects
.
all
()
asset_groups_permed
=
[
perm
.
asset_group
for
perm
in
user_group
.
perm_set
.
all
()]
asset_groups_unperm
=
[
asset_group
for
asset_group
in
asset_groups
if
asset_group
not
in
asset_groups_permed
]
return
render_to_response
(
'jperm/perm_edit.html'
,
locals
())
else
:
user_group_name
=
request
.
POST
.
get
(
'user_group_name'
)
asset_groups_selected
=
request
.
POST
.
getlist
(
'asset_group_permed'
)
perm_group_update
(
user_group_name
=
user_group_name
,
asset_groups_id
=
asset_groups_selected
)
return
HttpResponseRedirect
(
'/jperm/perm_list/'
)
def
perm_detail
(
request
):
user_group_id
=
request
.
GET
.
get
(
'id'
)
user_group
=
UserGroup
.
objects
.
get
(
id
=
user_group_id
)
asset_groups
=
[
perm
.
asset_group
for
perm
in
user_group
.
perm_set
.
all
()]
return
render_to_response
(
'jperm/perm_detail.html'
,
locals
())
def
perm_del
(
request
):
user_group_id
=
request
.
GET
.
get
(
'id'
)
user_group
=
UserGroup
.
objects
.
get
(
id
=
user_group_id
)
Perm
.
objects
.
filter
(
user_group
=
user_group
)
.
delete
()
return
HttpResponseRedirect
(
'/jperm/perm_list/'
)
def
perm_asset_detail
(
request
):
user_id
=
request
.
GET
.
get
(
'id'
)
user
=
User
.
objects
.
get
(
id
=
user_id
)
assets
=
perm_user_asset
(
user_id
)
return
render_to_response
(
'jperm/perm_asset_detail.html'
,
locals
())
jpermission/models.py
deleted
100644 → 0
View file @
a8991bfb
from
django.db
import
models
from
juser.models
import
User
from
jasset.models
import
Asset
class
Permission
(
models
.
Model
):
USER_ROLE_CHOICES
=
(
(
'SU'
,
'SuperUser'
),
(
'CU'
,
'CommonUser'
),
)
user
=
models
.
ForeignKey
(
User
)
asset
=
models
.
ForeignKey
(
Asset
)
role
=
models
.
CharField
(
choices
=
USER_ROLE_CHOICES
,
max_length
=
2
,
blank
=
True
,
null
=
True
)
def
__unicode__
(
self
):
return
'
%
s_
%
s'
%
(
self
.
user
.
username
,
self
.
asset
.
ip
)
\ No newline at end of file
jpermission/views.py
deleted
100644 → 0
View file @
a8991bfb
# coding: utf-8
from
django.shortcuts
import
render_to_response
from
django.http
import
HttpResponseRedirect
from
juser.models
import
User
from
jasset.models
import
Asset
from
jpermission.models
import
Permission
def
perm_user_list
(
request
):
header_title
,
path1
,
path2
=
u'查看授权用户 | Perm User Detail.'
,
u'授权管理'
,
u'用户详情'
users
=
User
.
objects
.
all
()
return
render_to_response
(
'jperm/perm_user_list.html'
,
locals
(),)
def
perm_add
(
request
):
header_title
,
path1
,
path2
=
u'添加授权 | Add User perm.'
,
u'授权管理'
,
u'添加授权'
if
request
.
method
==
'GET'
:
username
=
request
.
GET
.
get
(
'username'
,
None
)
if
not
username
:
return
HttpResponseRedirect
(
'/'
)
user
=
User
.
objects
.
get
(
username
=
username
)
permed_hosts
=
[]
for
perm
in
user
.
permission_set
.
all
():
permed_hosts
.
append
(
perm
.
asset
)
hosts_all
=
Asset
.
objects
.
all
()
hosts
=
list
(
set
(
hosts_all
)
-
set
(
permed_hosts
))
else
:
username
=
request
.
POST
.
get
(
'username'
,
None
)
host_ids
=
request
.
POST
.
getlist
(
'host_ids'
,
None
)
user
=
User
.
objects
.
get
(
username
=
username
)
for
id
in
host_ids
:
asset
=
Asset
.
objects
.
get
(
id
=
id
)
perm
=
Permission
(
user
=
user
,
asset
=
asset
)
perm
.
save
()
msg
=
u'添加成功'
return
render_to_response
(
'jperm/perm_add.html'
,
locals
())
def
perm_user_show
(
request
):
header_title
,
path1
,
path2
=
u'查看授权用户 | Perm User Detail.'
,
u'授权管理'
,
u'用户详情'
users
=
User
.
objects
.
all
()
return
render_to_response
(
'jperm/perm_user_show.html'
,
locals
(),)
def
perm_list
(
request
):
header_title
,
path1
,
path2
=
u'查看用户授权 | Perm User Detail.'
,
u'授权管理'
,
u'用户详情'
username
=
request
.
GET
.
get
(
'username'
,
None
)
if
not
username
:
return
HttpResponseRedirect
(
'/'
)
user
=
User
.
objects
.
get
(
username
=
username
)
hosts
=
[]
for
perm
in
user
.
permission_set
.
all
():
hosts
.
append
(
perm
.
asset
)
return
render_to_response
(
'jperm/perm_list.html'
,
locals
())
jumpserver.conf
View file @
2a645747
...
...
@@ -8,11 +8,7 @@ password = mysql234
database
=
jumpserver
[
ldap
]
host_url
=
ldap
://
192
.
168
.
8
.
60
:
389
base_dn
=
dc
=
fengxing
,
dc
=
org
root_dn
=
cn
=
admin
,
dc
=
fengxing
,
dc
=
org
root_pw
=
123456
ldap_enable
=
0
ldap_enable
=
1
host_url
=
ldap
://
127
.
0
.
0
.
1
:
389
base_dn
=
dc
=
jumpserver
,
dc
=
org
root_dn
=
cn
=
admin
,
dc
=
jumpserver
,
dc
=
org
...
...
jumpserver/settings.py
View file @
2a645747
...
...
@@ -49,7 +49,7 @@ INSTALLED_APPS = (
'jumpserver'
,
'juser'
,
'jasset'
,
'jperm
ission
'
,
'jperm'
,
'jlog'
,
)
...
...
jumpserver/templatetags/mytags.py
View file @
2a645747
...
...
@@ -2,7 +2,9 @@
import
time
from
django
import
template
from
juser.models
import
User
from
django.db.models
import
Q
from
juser.models
import
User
,
UserGroup
from
jperm.views
import
perm_user_asset
register
=
template
.
Library
()
...
...
@@ -24,16 +26,20 @@ def int2str(value):
def
get_role
(
user_id
):
user_role
=
{
'SU'
:
u'超级管理员'
,
'GA'
:
u'组管理员'
,
'CU'
:
u'普通用户'
}
user
=
User
.
objects
.
get
(
id
=
user_id
)
return
user_role
.
get
(
user
.
role
)
return
user_role
.
get
(
str
(
user
.
role
)
)
@register.filter
(
name
=
'groups_str'
)
def
groups_str
(
username
):
groups
=
[]
user
=
User
.
objects
.
get
(
username
=
username
)
for
group
in
user
.
user_group
.
all
(
):
for
group
in
user
.
user_group
.
filter
(
Q
(
type
=
'A'
)
|
Q
(
type
=
'M'
)
):
groups
.
append
(
group
.
name
)
return
','
.
join
(
groups
)
if
len
(
groups
)
<
4
:
return
' '
.
join
(
groups
)
else
:
return
"
%
s ..."
%
' '
.
join
(
groups
[
0
:
3
])
@register.filter
(
name
=
'get_item'
)
def
get_item
(
dictionary
,
key
):
...
...
@@ -45,4 +51,30 @@ def bool2str(value):
if
value
:
return
u'是'
else
:
return
u'否'
\ No newline at end of file
return
u'否'
@register.filter
(
name
=
'member_count'
)
def
member_count
(
group_id
):
group
=
UserGroup
.
objects
.
get
(
id
=
group_id
)
return
group
.
user_set
.
count
()
@register.filter
(
name
=
'perm_count'
)
def
perm_count
(
group_id
):
group
=
UserGroup
.
objects
.
get
(
id
=
group_id
)
return
group
.
perm_set
.
count
()
@register.filter
(
name
=
'group_type_to_str'
)
def
group_type_to_str
(
type_name
):
group_types
=
{
'P'
:
'私有组'
,
'M'
:
'管理组'
,
'A'
:
'授权组'
,
}
return
group_types
.
get
(
type_name
)
@register.filter
(
name
=
'perm_asset_count'
)
def
perm_asset_count
(
user_id
):
return
len
(
perm_user_asset
(
user_id
))
jumpserver/urls.py
View file @
2a645747
...
...
@@ -5,11 +5,13 @@ urlpatterns = patterns('',
# Examples:
# url(r'^$', 'jumpserver.views.home', name='home'),
# url(r'^blog/', include('blog.urls')),
(
r'^$'
,
'jumpserver.views.base'
),
(
r'^skin_config/$'
,
'jumpserver.views.skin_config'
),
(
r'^base/$'
,
'jumpserver.views.base'
),
(
r'^login/$'
,
'jumpserver.views.login'
),
(
r'^logout/$'
,
'jumpserver.views.logout'
),
(
r'^juser/'
,
include
(
'juser.urls'
)),
(
r'^jperm/'
,
include
(
'jpermission.urls'
)),
(
r'^jasset/'
,
include
(
'jasset.urls'
)),
(
r'^jlog/'
,
include
(
'jlog.urls'
)),
(
r'^jperm/'
,
include
(
'jperm.urls'
)),
)
jumpserver/views.py
View file @
2a645747
#coding: utf-8
import
hashlib
from
django.http
import
HttpResponse
from
django.shortcuts
import
render_to_response
from
django.http
import
HttpResponseRedirect
from
juser.models
import
User
from
connect
import
PyCrypt
,
KEY
from
jasset.models
import
Asset
,
BisGroup
,
IDC
from
django.shortcuts
import
render_to_response
def
md5_crypt
(
string
):
return
hashlib
.
new
(
"md5"
,
string
)
.
hexdigest
()
def
base
(
request
):
...
...
@@ -12,6 +23,7 @@ def skin_config(request):
return
render_to_response
(
'skin_config.html'
)
<<<<<<<
HEAD
def
jasset_group_add
(
name
,
comment
,
type
):
if
BisGroup
.
objects
.
filter
(
name
=
name
):
emg
=
u'该业务组已存在!'
...
...
@@ -51,4 +63,39 @@ def jasset_host_edit(j_ip, j_idc, j_port, j_type, j_group, j_active, j_comment):
a
.
save
()
a
.
bis_group
=
groups
a
.
save
()
\ No newline at end of file
a
.
save
()
=======
def
login
(
request
):
"""登录界面"""
if
request
.
session
.
get
(
'username'
):
return
HttpResponseRedirect
(
'/'
)
if
request
.
method
==
'GET'
:
return
render_to_response
(
'login.html'
)
else
:
username
=
request
.
POST
.
get
(
'username'
)
password
=
request
.
POST
.
get
(
'password'
)
user
=
User
.
objects
.
filter
(
username
=
username
)
if
user
:
user
=
user
[
0
]
if
md5_crypt
(
password
)
==
user
.
password
:
request
.
session
[
'username'
]
=
username
if
user
.
role
==
'SU'
:
request
.
session
[
'role'
]
=
2
elif
user
.
role
==
'GA'
:
request
.
session
[
'role'
]
=
1
else
:
request
.
session
[
'role'
]
=
0
return
HttpResponseRedirect
(
'/'
)
else
:
error
=
'密码错误,请重新输入。'
else
:
error
=
'用户不存在。'
return
render_to_response
(
'login.html'
,
{
'error'
:
error
})
def
logout
(
request
):
request
.
session
.
delete
()
return
HttpResponseRedirect
(
'/login/'
)
>>>>>>>
guanghongwei
juser/models.py
View file @
2a645747
...
...
@@ -2,7 +2,14 @@ from django.db import models
class
UserGroup
(
models
.
Model
):
GROUP_TYPE_CHOICES
=
(
(
'P'
,
'PrivateGroup'
),
(
'M'
,
'ManageGroup'
),
(
'A'
,
'AuthorizeGroup'
),
)
name
=
models
.
CharField
(
max_length
=
80
,
unique
=
True
)
type
=
models
.
CharField
(
max_length
=
1
,
choices
=
GROUP_TYPE_CHOICES
,
default
=
'P'
)
comment
=
models
.
CharField
(
max_length
=
160
,
blank
=
True
,
null
=
True
)
def
__unicode__
(
self
):
...
...
@@ -22,8 +29,7 @@ class User(models.Model):
role
=
models
.
CharField
(
max_length
=
2
,
choices
=
USER_ROLE_CHOICES
,
default
=
'CU'
)
user_group
=
models
.
ManyToManyField
(
UserGroup
)
ldap_pwd
=
models
.
CharField
(
max_length
=
100
)
ssh_key_pwd1
=
models
.
CharField
(
max_length
=
100
)
ssh_key_pwd2
=
models
.
CharField
(
max_length
=
100
)
ssh_key_pwd
=
models
.
CharField
(
max_length
=
100
)
ssh_pwd
=
models
.
CharField
(
max_length
=
100
)
is_active
=
models
.
BooleanField
(
default
=
True
)
last_login
=
models
.
IntegerField
(
default
=
0
)
...
...
juser/views.py
View file @
2a645747
...
...
@@ -15,6 +15,8 @@ from django.http import HttpResponseRedirect
from
django.shortcuts
import
render_to_response
from
django.core.exceptions
import
ObjectDoesNotExist
from
django.db.models
import
Q
from
django.http
import
HttpResponse
from
juser.models
import
UserGroup
,
User
from
connect
import
PyCrypt
,
KEY
...
...
@@ -31,10 +33,6 @@ if LDAP_ENABLE:
LDAP_ROOT_PW
=
CONF
.
get
(
'ldap'
,
'root_pw'
)
def
md5_crypt
(
string
):
return
hashlib
.
new
(
"md5"
,
string
)
.
hexdigest
()
def
gen_rand_pwd
(
num
):
"""生成随机密码"""
seed
=
"1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
...
...
@@ -113,33 +111,176 @@ def gen_sha512(salt, password):
return
crypt
.
crypt
(
password
,
'$6$
%
s$'
%
salt
)
def
group_db_add
(
**
kwargs
):
group_name
=
kwargs
.
get
(
'name'
)
group
=
UserGroup
.
objects
.
filter
(
name
=
group_name
)
if
group
:
raise
AddError
(
'Group
%
s have been exist .'
%
group_name
)
UserGroup
.
objects
.
create
(
**
kwargs
)
def
group_add_user
(
group_name
,
user_id
=
None
,
username
=
None
):
try
:
if
user_id
:
user
=
User
.
objects
.
get
(
id
=
user_id
)
else
:
user
=
User
.
objects
.
get
(
username
=
username
)
except
ObjectDoesNotExist
:
raise
AddError
(
'用户获取失败'
)
else
:
group
=
UserGroup
.
objects
.
get
(
name
=
group_name
)
group
.
user_set
.
add
(
user
)
def
group_update_user
(
group_id
,
users_id
):
group
=
UserGroup
.
objects
.
get
(
id
=
group_id
)
group
.
user_set
.
clear
()
for
user_id
in
users_id
:
user
=
User
.
objects
.
get
(
id
=
user_id
)
group
.
user_set
.
add
(
user
)
def
db_add_user
(
**
kwargs
):
groups_post
=
kwargs
.
pop
(
'groups'
)
user
=
User
(
**
kwargs
)
group_select
=
[]
for
group_id
in
groups_post
:
group
=
UserGroup
.
objects
.
filter
(
id
=
group_id
)
group_select
.
extend
(
group
)
user
.
save
()
user
.
user_group
=
group_select
def
db_update_user
(
**
kwargs
):
groups_post
=
kwargs
.
pop
(
'groups'
)
username
=
kwargs
.
get
(
'username'
)
user
=
User
.
objects
.
filter
(
username
=
username
)
user
.
update
(
**
kwargs
)
user
=
User
.
objects
.
get
(
username
=
username
)
group_select
=
[]
for
group_id
in
groups_post
:
group
=
UserGroup
.
objects
.
filter
(
id
=
group_id
)
group_select
.
extend
(
group
)
user
.
save
()
user
.
user_group
=
group_select
def
db_del_user
(
username
):
try
:
user
=
User
.
objects
.
get
(
username
=
username
)
user
.
delete
()
except
ObjectDoesNotExist
:
pass
def
gen_ssh_key
(
username
,
password
=
None
,
length
=
2048
):
private_key_dir
=
os
.
path
.
join
(
BASE_DIR
,
'keys/jumpserver/'
)
private_key_file
=
os
.
path
.
join
(
private_key_dir
,
username
)
public_key_dir
=
'/home/
%
s/.ssh/'
%
username
public_key_file
=
os
.
path
.
join
(
public_key_dir
,
'authorized_keys'
)
is_dir
(
private_key_dir
)
is_dir
(
public_key_dir
,
mode
=
0700
)
key
=
RSA
.
generate
(
length
)
with
open
(
private_key_file
,
'w'
)
as
pri_f
:
pri_f
.
write
(
key
.
exportKey
(
'PEM'
,
password
))
os
.
chmod
(
private_key_file
,
0600
)
pub_key
=
key
.
publickey
()
with
open
(
public_key_file
,
'w'
)
as
pub_f
:
pub_f
.
write
(
pub_key
.
exportKey
(
'OpenSSH'
))
os
.
chmod
(
public_key_file
,
0600
)
bash
(
'chown
%
s:
%
s
%
s'
%
(
username
,
username
,
public_key_file
))
def
server_add_user
(
username
,
password
,
ssh_key_pwd
):
bash
(
'useradd
%
s; echo
%
s | passwd --stdin
%
s'
%
(
username
,
password
,
username
))
gen_ssh_key
(
username
,
ssh_key_pwd
)
def
server_del_user
(
username
):
bash
(
'userdel -r
%
s'
%
username
)
def
ldap_add_user
(
username
,
ldap_pwd
):
user_dn
=
"uid=
%
s,ou=People,
%
s"
%
(
username
,
LDAP_BASE_DN
)
password_sha512
=
gen_sha512
(
gen_rand_pwd
(
6
),
ldap_pwd
)
user
=
User
.
objects
.
get
(
username
=
username
)
user_attr
=
{
'uid'
:
[
str
(
username
)],
'cn'
:
[
str
(
username
)],
'objectClass'
:
[
'account'
,
'posixAccount'
,
'top'
,
'shadowAccount'
],
'userPassword'
:
[
'{crypt}
%
s'
%
password_sha512
],
'shadowLastChange'
:
[
'16328'
],
'shadowMin'
:
[
'0'
],
'shadowMax'
:
[
'99999'
],
'shadowWarning'
:
[
'7'
],
'loginShell'
:
[
'/bin/bash'
],
'uidNumber'
:
[
str
(
user
.
id
)],
'gidNumber'
:
[
str
(
user
.
id
)],
'homeDirectory'
:
[
str
(
'/home/
%
s'
%
username
)]}
group_dn
=
"cn=
%
s,ou=Group,
%
s"
%
(
username
,
LDAP_BASE_DN
)
group_attr
=
{
'objectClass'
:
[
'posixGroup'
,
'top'
],
'cn'
:
[
str
(
username
)],
'userPassword'
:
[
'{crypt}x'
],
'gidNumber'
:
[
str
(
user
.
id
)]}
sudo_dn
=
'cn=
%
s,ou=Sudoers,
%
s'
%
(
username
,
LDAP_BASE_DN
)
sudo_attr
=
{
'objectClass'
:
[
'top'
,
'sudoRole'
],
'cn'
:
[
'
%
s'
%
str
(
username
)],
'sudoCommand'
:
[
'/bin/pwd'
],
'sudoHost'
:
[
'192.168.1.1'
],
'sudoOption'
:
[
'!authenticate'
],
'sudoRunAsUser'
:
[
'root'
],
'sudoUser'
:
[
'
%
s'
%
str
(
username
)]}
ldap_conn
=
LDAPMgmt
(
LDAP_HOST_URL
,
LDAP_BASE_DN
,
LDAP_ROOT_DN
,
LDAP_ROOT_PW
)
ldap_conn
.
add
(
user_dn
,
user_attr
)
ldap_conn
.
add
(
group_dn
,
group_attr
)
ldap_conn
.
add
(
sudo_dn
,
sudo_attr
)
def
ldap_del_user
(
username
):
user_dn
=
"uid=
%
s,ou=People,
%
s"
%
(
username
,
LDAP_BASE_DN
)
group_dn
=
"cn=
%
s,ou=Group,
%
s"
%
(
username
,
LDAP_BASE_DN
)
sudo_dn
=
'cn=
%
s,ou=Sudoers,
%
s'
%
(
username
,
LDAP_BASE_DN
)
ldap_conn
=
LDAPMgmt
(
LDAP_HOST_URL
,
LDAP_BASE_DN
,
LDAP_ROOT_DN
,
LDAP_ROOT_PW
)
ldap_conn
.
delete
(
user_dn
)
ldap_conn
.
delete
(
group_dn
)
ldap_conn
.
delete
(
sudo_dn
)
def
group_add
(
request
):
error
=
''
msg
=
''
header_title
,
path1
,
path2
=
'添加属组 | Add Group'
,
'juser'
,
'group_add'
group_types
=
{
# 'P': '私有组',
'M'
:
'管理组'
,
'A'
:
'授权组'
,
}
users
=
User
.
objects
.
all
()
if
request
.
method
==
'POST'
:
group_name
=
request
.
POST
.
get
(
'group_name'
,
None
)
comment
=
request
.
POST
.
get
(
'comment'
,
None
)
group_name
=
request
.
POST
.
get
(
'group_name'
,
''
)
group_type
=
request
.
POST
.
get
(
'group_type'
,
'A'
)
users_selected
=
request
.
POST
.
getlist
(
'users_selected'
,
''
)
comment
=
request
.
POST
.
get
(
'comment'
,
''
)
try
:
if
not
group_name
:
error
=
u'组名不能为空'
raise
AddError
group_db_add
(
name
=
group_name
,
comment
=
comment
,
type
=
group_type
)
for
user_id
in
users_selected
:
group_add_user
(
group_name
,
user_id
=
user_id
)
group
=
UserGroup
.
objects
.
filter
(
name
=
group_name
)
if
group
:
error
=
u'组
%
s 已存在'
%
group_name
raise
AddError
group
=
UserGroup
(
name
=
group_name
,
comment
=
comment
)
group
.
save
()
except
AddError
:
pass
except
TypeError
:
error
=
u'保存用户失败'
error
=
u'保存用户组失败'
else
:
msg
=
u'添加组
%
s 成功'
%
group_name
...
...
@@ -148,7 +289,7 @@ def group_add(request):
def
group_list
(
request
):
header_title
,
path1
,
path2
=
'查看属组 | Show Group'
,
'juser'
,
'group_list'
groups
=
contact_list
=
UserGroup
.
objects
.
all
(
)
.
order_by
(
'id'
)
groups
=
contact_list
=
UserGroup
.
objects
.
filter
(
Q
(
type
=
'M'
)
|
Q
(
type
=
'A'
)
)
.
order_by
(
'id'
)
p
=
paginator
=
Paginator
(
contact_list
,
10
)
try
:
...
...
@@ -168,6 +309,7 @@ def group_detail(request):
if
not
group_id
:
return
HttpResponseRedirect
(
'/'
)
group
=
UserGroup
.
objects
.
get
(
id
=
group_id
)
users
=
group
.
user_set
.
all
()
return
render_to_response
(
'juser/group_detail.html'
,
locals
())
...
...
@@ -184,19 +326,32 @@ def group_edit(request):
error
=
''
msg
=
''
header_title
,
path1
,
path2
=
'修改属组 | Edit Group'
,
'juser'
,
'group_edit'
group_types
=
{
# 'P': '私有组',
'M'
:
'管理组'
,
'A'
:
'授权组'
,
}
if
request
.
method
==
'GET'
:
group_id
=
request
.
GET
.
get
(
'id'
,
None
)
group
=
UserGroup
.
objects
.
get
(
id
=
group_id
)
group_name
=
group
.
name
comment
=
group
.
comment
group_type
=
group
.
type
users_all
=
User
.
objects
.
all
()
users_selected
=
group
.
user_set
.
all
()
users
=
[
user
for
user
in
users_all
if
user
not
in
users_selected
]
return
render_to_response
(
'juser/group_add.html'
,
locals
())
else
:
group_id
=
request
.
POST
.
get
(
'group_id'
,
None
)
group_name
=
request
.
POST
.
get
(
'group_name'
,
None
)
comment
=
request
.
POST
.
get
(
'comment'
,
''
)
users_selected
=
request
.
POST
.
getlist
(
'users_selected'
)
group_type
=
request
.
POST
.
get
(
'group_type'
)
group
=
UserGroup
.
objects
.
filter
(
id
=
group_id
)
group
.
update
(
name
=
group_name
,
comment
=
comment
)
# return HttpResponse(group_type)
group
.
update
(
name
=
group_name
,
comment
=
comment
,
type
=
group_type
)
group_update_user
(
group_id
,
users_selected
)
return
HttpResponseRedirect
(
'/juser/group_list/'
)
...
...
@@ -233,6 +388,10 @@ def user_del(request):
return
HttpResponseRedirect
(
'/'
)
user
=
User
.
objects
.
get
(
id
=
user_id
)
user
.
delete
()
group
=
UserGroup
.
objects
.
get
(
name
=
user
.
username
)
group
.
delete
()
server_del_user
(
user
.
username
)
ldap_del_user
(
user
.
username
)
return
HttpResponseRedirect
(
'/juser/user_list/'
,
locals
())
...
...
@@ -246,10 +405,10 @@ def user_edit(request):
user
=
User
.
objects
.
get
(
id
=
user_id
)
username
=
user
.
username
password
=
user
.
password
ssh_key_pwd
1
=
user
.
ssh_key_pwd1
ssh_key_pwd
=
user
.
ssh_key_pwd
name
=
user
.
name
all_group
=
UserGroup
.
objects
.
all
(
)
groups
=
user
.
user_group
.
all
(
)
all_group
=
UserGroup
.
objects
.
filter
(
Q
(
type
=
'M'
)
|
Q
(
type
=
'A'
)
)
groups
=
user
.
user_group
.
filter
(
Q
(
type
=
'M'
)
|
Q
(
type
=
'A'
)
)
groups_str
=
' '
.
join
([
str
(
group
.
id
)
for
group
in
groups
])
user_role
=
{
'SU'
:
u'超级管理员'
,
'GA'
:
u'组管理员'
,
'CU'
:
u'普通用户'
}
role_post
=
user
.
role
...
...
@@ -265,10 +424,10 @@ def user_edit(request):
groups_str
=
' '
.
join
(
groups
)
role_post
=
request
.
POST
.
get
(
'role'
,
None
)
ssh_pwd
=
request
.
POST
.
get
(
'ssh_pwd'
,
None
)
ssh_key_pwd
1
=
request
.
POST
.
get
(
'ssh_key_pwd1
'
,
None
)
ssh_key_pwd
=
request
.
POST
.
get
(
'ssh_key_pwd
'
,
None
)
is_active
=
request
.
POST
.
get
(
'is_active'
,
'1'
)
ldap_pwd
=
gen_rand_pwd
(
16
)
all_group
=
UserGroup
.
objects
.
all
(
)
all_group
=
UserGroup
.
objects
.
filter
(
Q
(
type
=
'M'
)
|
Q
(
type
=
'A'
)
)
user_role
=
{
'SU'
:
u'超级管理员'
,
'GA'
:
u'组管理员'
,
'CU'
:
u'普通用户'
}
if
username
:
...
...
@@ -282,8 +441,8 @@ def user_edit(request):
if
ssh_pwd
!=
user
.
ssh_pwd
:
ssh_pwd
=
CRYPTOR
.
encrypt
(
ssh_pwd
)
if
ssh_key_pwd
1
!=
user
.
ssh_key_pwd1
:
ssh_key_pwd
1
=
CRYPTOR
.
encrypt
(
ssh_key_pwd1
)
if
ssh_key_pwd
!=
user
.
ssh_key_pwd
:
ssh_key_pwd
=
CRYPTOR
.
encrypt
(
ssh_key_pwd
)
db_update_user
(
username
=
username
,
password
=
password
,
...
...
@@ -292,7 +451,7 @@ def user_edit(request):
groups
=
groups
,
role
=
role_post
,
ssh_pwd
=
ssh_pwd
,
ssh_key_pwd
1
=
ssh_key_pwd1
)
ssh_key_pwd
=
ssh_key_pwd
)
msg
=
u'修改用户成功'
return
HttpResponseRedirect
(
'/juser/user_list/'
)
...
...
@@ -300,140 +459,27 @@ def user_edit(request):
return
render_to_response
(
'juser/user_add.html'
,
locals
())
def
db_add_user
(
**
kwargs
):
groups_post
=
kwargs
.
pop
(
'groups'
)
user
=
User
(
**
kwargs
)
group_select
=
[]
for
group_id
in
groups_post
:
group
=
UserGroup
.
objects
.
filter
(
id
=
group_id
)
group_select
.
extend
(
group
)
user
.
save
()
user
.
user_group
=
group_select
def
db_update_user
(
**
kwargs
):
groups_post
=
kwargs
.
pop
(
'groups'
)
username
=
kwargs
.
get
(
'username'
)
user
=
User
.
objects
.
filter
(
username
=
username
)
user
.
update
(
**
kwargs
)
user
=
User
.
objects
.
get
(
username
=
username
)
group_select
=
[]
for
group_id
in
groups_post
:
group
=
UserGroup
.
objects
.
filter
(
id
=
group_id
)
group_select
.
extend
(
group
)
user
.
save
()
user
.
user_group
=
group_select
def
db_del_user
(
username
):
try
:
user
=
User
.
objects
.
get
(
username
=
username
)
user
.
delete
()
except
ObjectDoesNotExist
:
pass
def
gen_ssh_key
(
username
,
password
=
None
,
length
=
2048
):
private_key_dir
=
os
.
path
.
join
(
BASE_DIR
,
'keys/jumpserver/'
)
private_key_file
=
os
.
path
.
join
(
private_key_dir
,
username
)
public_key_dir
=
'/home/
%
s/.ssh/'
%
username
public_key_file
=
os
.
path
.
join
(
public_key_dir
,
'authorized_keys'
)
is_dir
(
private_key_dir
)
is_dir
(
public_key_dir
,
mode
=
0700
)
key
=
RSA
.
generate
(
length
)
with
open
(
private_key_file
,
'w'
)
as
pri_f
:
pri_f
.
write
(
key
.
exportKey
(
'PEM'
,
password
))
os
.
chmod
(
private_key_file
,
0600
)
pub_key
=
key
.
publickey
()
with
open
(
public_key_file
,
'w'
)
as
pub_f
:
pub_f
.
write
(
pub_key
.
exportKey
(
'OpenSSH'
))
os
.
chmod
(
public_key_file
,
0600
)
bash
(
'chown
%
s:
%
s
%
s'
%
(
username
,
username
,
public_key_file
))
def
server_add_user
(
username
,
password
,
ssh_key_pwd1
):
bash
(
'useradd
%
s; echo
%
s | passwd --stdin
%
s'
%
(
username
,
password
,
username
))
gen_ssh_key
(
username
,
ssh_key_pwd1
)
def
server_del_user
(
username
):
bash
(
'userdel -r
%
s'
%
username
)
def
ldap_add_user
(
username
,
ldap_pwd
):
user_dn
=
"uid=
%
s,ou=People,
%
s"
%
(
username
,
LDAP_BASE_DN
)
password_sha512
=
gen_sha512
(
gen_rand_pwd
(
6
),
ldap_pwd
)
user
=
User
.
objects
.
get
(
username
=
username
)
user_attr
=
{
'uid'
:
[
str
(
username
)],
'cn'
:
[
str
(
username
)],
'objectClass'
:
[
'account'
,
'posixAccount'
,
'top'
,
'shadowAccount'
],
'userPassword'
:
[
'{crypt}
%
s'
%
password_sha512
],
'shadowLastChange'
:
[
'16328'
],
'shadowMin'
:
[
'0'
],
'shadowMax'
:
[
'99999'
],
'shadowWarning'
:
[
'7'
],
'loginShell'
:
[
'/bin/bash'
],
'uidNumber'
:
[
str
(
user
.
id
)],
'gidNumber'
:
[
str
(
user
.
id
)],
'homeDirectory'
:
[
str
(
'/home/
%
s'
%
username
)]}
group_dn
=
"cn=
%
s,ou=Group,
%
s"
%
(
username
,
LDAP_BASE_DN
)
group_attr
=
{
'objectClass'
:
[
'posixGroup'
,
'top'
],
'cn'
:
[
str
(
username
)],
'userPassword'
:
[
'{crypt}x'
],
'gidNumber'
:
[
str
(
user
.
id
)]}
sudo_dn
=
'cn=
%
s,ou=Sudoers,
%
s'
%
(
username
,
LDAP_BASE_DN
)
sudo_attr
=
{
'objectClass'
:
[
'top'
,
'sudoRole'
],
'cn'
:
[
'
%
s'
%
str
(
username
)],
'sudoCommand'
:
[
'/bin/pwd'
],
'sudoHost'
:
[
'192.168.1.1'
],
'sudoOption'
:
[
'!authenticate'
],
'sudoRunAsUser'
:
[
'root'
],
'sudoUser'
:
[
'
%
s'
%
str
(
username
)]}
ldap_conn
=
LDAPMgmt
(
LDAP_HOST_URL
,
LDAP_BASE_DN
,
LDAP_ROOT_DN
,
LDAP_ROOT_PW
)
ldap_conn
.
add
(
user_dn
,
user_attr
)
ldap_conn
.
add
(
group_dn
,
group_attr
)
ldap_conn
.
add
(
sudo_dn
,
sudo_attr
)
def
ldap_del_user
(
username
):
user_dn
=
"uid=
%
s,ou=People,
%
s"
%
(
username
,
LDAP_BASE_DN
)
group_dn
=
"cn=
%
s,ou=Group,
%
s"
%
(
username
,
LDAP_BASE_DN
)
sudo_dn
=
'cn=
%
s,ou=Sudoers,
%
s'
%
(
username
,
LDAP_BASE_DN
)
ldap_conn
=
LDAPMgmt
(
LDAP_HOST_URL
,
LDAP_BASE_DN
,
LDAP_ROOT_DN
,
LDAP_ROOT_PW
)
ldap_conn
.
delete
(
user_dn
)
ldap_conn
.
delete
(
group_dn
)
ldap_conn
.
delete
(
sudo_dn
)
def
user_add
(
request
):
error
=
''
msg
=
''
header_title
,
path1
,
path2
=
'添加用户 | Add User'
,
'juser'
,
'user_add'
user_role
=
{
'SU'
:
u'超级管理员'
,
'GA'
:
u'组管理员'
,
'CU'
:
u'普通用户'
}
all_group
=
UserGroup
.
objects
.
all
(
)
all_group
=
UserGroup
.
objects
.
filter
(
Q
(
type
=
'M'
)
|
Q
(
type
=
'A'
))
.
order_by
(
'-type'
)
if
request
.
method
==
'POST'
:
username
=
request
.
POST
.
get
(
'username'
,
None
)
password
=
request
.
POST
.
get
(
'password'
,
None
)
password
=
request
.
POST
.
get
(
'password'
,
''
)
name
=
request
.
POST
.
get
(
'name'
,
None
)
email
=
request
.
POST
.
get
(
'email'
,
''
)
groups
=
request
.
POST
.
getlist
(
'groups'
,
None
)
groups_str
=
' '
.
join
(
groups
)
role_post
=
request
.
POST
.
get
(
'role'
,
None
)
ssh_pwd
=
request
.
POST
.
get
(
'ssh_pwd'
,
None
)
ssh_key_pwd
1
=
request
.
POST
.
get
(
'ssh_key_pwd1'
,
None
)
role_post
=
request
.
POST
.
get
(
'role'
,
'CU'
)
ssh_pwd
=
request
.
POST
.
get
(
'ssh_pwd'
,
''
)
ssh_key_pwd
=
request
.
POST
.
get
(
'ssh_key_pwd'
,
''
)
is_active
=
request
.
POST
.
get
(
'is_active'
,
'1'
)
ldap_pwd
=
gen_rand_pwd
(
16
)
try
:
if
None
in
[
username
,
password
,
ssh_key_pwd
1
,
name
,
groups
,
role_post
,
is_active
]:
if
None
in
[
username
,
password
,
ssh_key_pwd
,
name
,
groups
,
role_post
,
is_active
]:
error
=
u'带*内容不能为空'
raise
AddError
user
=
User
.
objects
.
filter
(
username
=
username
)
...
...
@@ -450,17 +496,18 @@ def user_add(request):
password
=
md5_crypt
(
password
),
name
=
name
,
email
=
email
,
groups
=
groups
,
role
=
role_post
,
ssh_pwd
=
CRYPTOR
.
encrypt
(
ssh_pwd
),
ssh_key_pwd
1
=
CRYPTOR
.
encrypt
(
ssh_key_pwd1
),
ssh_pwd
=
CRYPTOR
.
encrypt
(
ssh_pwd
)
if
ssh_pwd
else
''
,
ssh_key_pwd
=
CRYPTOR
.
encrypt
(
ssh_key_pwd
),
ldap_pwd
=
CRYPTOR
.
encrypt
(
ldap_pwd
),
is_active
=
is_active
,
date_joined
=
time_now
)
server_add_user
(
username
,
password
,
ssh_key_pwd1
)
server_add_user
(
username
,
password
,
ssh_key_pwd
)
group_db_add
(
name
=
username
,
comment
=
username
,
type
=
'P'
)
group_add_user
(
group_name
=
username
,
username
=
username
)
if
LDAP_ENABLE
:
ldap_add_user
(
username
,
ldap_pwd
)
msg
=
u'添加用户
%
s 成功!'
%
username
# locals = lambda: {}
except
Exception
,
e
:
error
=
u'添加用户
%
s 失败
%
s '
%
(
username
,
e
)
...
...
static/css/style.css
View file @
2a645747
...
...
@@ -2577,7 +2577,7 @@ a.forum-item-title:hover {
padding-right
:
20px
!important
;
}
body
{
font-family
:
"open sans"
,
"Helvetica Neue"
,
Helvetica
,
Arial
,
sans-serif
;
font-family
:
"open sans"
,
"Helvetica Neue"
,
Helvetica
,
Arial
,
"微软雅黑"
,
sans-serif
;
background-color
:
#2f4050
;
font-size
:
13px
;
color
:
#676a6c
;
...
...
@@ -2623,6 +2623,9 @@ a:focus {
.b-r
{
border-right
:
1px
solid
#e7eaec
;
}
.b-l
{
border-left
:
1px
solid
#e7eaec
;
}
.hr-line-dashed
{
border-top
:
1px
dashed
#e7eaec
;
color
:
#ffffff
;
...
...
static/img/logo.png
0 → 100644
View file @
2a645747
5.97 KB
templates/base.html
View file @
2a645747
...
...
@@ -10,7 +10,7 @@
<link
rel=
"shortcut icon"
href=
"/static/img/facio.ico"
type=
"image/x-icon"
>
{% include 'link_css.html' %}
{% include 'script.html' %}
</head>
...
...
@@ -27,7 +27,7 @@
</div>
</div>
<!--{% include 'script.html' %}-->
{#
<!--{% include 'script.html' %}-->
#}
</body>
{% include 'script.html' %}
</html>
templates/css_js.html
deleted
100644 → 0
View file @
a8991bfb
<link
href=
"/static/css/bootstrap.min.css"
rel=
"stylesheet"
>
<link
href=
"/static/font-awesome/css/font-awesome.css"
rel=
"stylesheet"
>
<link
href=
"/static/css/plugins/iCheck/custom.css"
rel=
"stylesheet"
>
<link
href=
"/static/css/animate.css"
rel=
"stylesheet"
>
<link
href=
"/static/css/style.css"
rel=
"stylesheet"
>
<link
href=
"/static/css/colorbox.css"
rel=
"stylesheet"
>
<!-- Mainly scripts -->
<script
src=
"/static/js/jquery-2.1.1.js"
></script>
<script
src=
"/static/js/bootstrap.min.js"
></script>
<script
src=
"/static/js/plugins/metisMenu/jquery.metisMenu.js"
></script>
<script
src=
"/static/js/plugins/slimscroll/jquery.slimscroll.min.js"
></script>
<!-- Peity -->
<script
src=
"/static/js/plugins/peity/jquery.peity.min.js"
></script>
<!-- Custom and plugin javascript -->
<script
src=
"/static/js/inspinia.js"
></script>
<script
src=
"/static/js/plugins/pace/pace.min.js"
></script>
<!-- iCheck -->
<script
src=
"/static/js/plugins/iCheck/icheck.min.js"
></script>
<!-- Peity -->
<script
src=
"/static/js/demo/peity-demo.js"
></script>
<!-- pop windows -->
<script
src=
"/static/js/jquery.colorbox.js"
></script>
<script>
$
(
document
).
ready
(
function
(){
$
(
".iframe"
).
colorbox
({
iframe
:
true
,
width
:
"90%"
,
height
:
"90%"
});
});
</script>
\ No newline at end of file
templates/jperm/perm_asset_detail.html
0 → 100644
View file @
2a645747
{% load mytags %}
<html>
<head>
{% include 'link_css.html' %}
<style
type=
"text/css"
>
body
{
background
:
#FFFFFF
;
}
</style>
</head>
<body>
<div
class=
"row"
>
<div
class=
"contact-box"
>
<h2
class=
"text-center"
>
{{ user.name }} 授权详情
</h2>
<div
class=
"ibox-content"
>
<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>
</tr>
</thead>
<tbody>
{% for asset in assets %}
<tr
class=
"gradeX"
>
<td
class=
"text-center"
>
{{ asset.ip }}
</td>
<td
class=
"text-center"
>
{{ asset.port }}
</td>
<td
class=
"text-center"
>
{{ asset.login_type }}
</td>
</tr>
{% endfor %}
</table>
</div>
</div>
</body>
</html>
\ No newline at end of file
templates/jperm/perm_detail.html
0 → 100644
View file @
2a645747
{% load mytags %}
<html>
<head>
{% include 'link_css.html' %}
<style
type=
"text/css"
>
body
{
background
:
#FFFFFF
;
}
</style>
</head>
<body>
<div
class=
"row"
>
<div
class=
"contact-box"
>
<h2
class=
"text-center"
>
{{ group.name }} 授权详情
</h2>
<div
class=
"ibox-content"
>
<table
class=
"table table-striped table-bordered table-hover "
id=
"editable"
>
<thead>
<tr>
<th
class=
"text-center"
>
ID
</th>
<th
class=
"text-center"
>
主机组
</th>
<th
class=
"text-center"
>
主机数量
</th>
</tr>
</thead>
<tbody>
{% for asset_group in asset_groups %}
<tr
class=
"gradeX"
>
<td
class=
"text-center"
>
{{ asset_group.id }}
</td>
<td
class=
"text-center"
>
{{ asset_group.name }}
</td>
<td
class=
"text-center"
>
{{ asset_group.asset_set.count }}
</td>
</tr>
{% endfor %}
</table>
</div>
</div>
</body>
</html>
\ No newline at end of file
templates/jperm/perm_edit.html
0 → 100644
View file @
2a645747
{% extends 'base.html' %}
{% load mytags %}
{% block content %}
<script
type=
"text/javascript"
>
function
search_host
(
text
){
$
(
"#asset_group_unperm"
).
children
().
each
(
function
(){
$
(
this
).
remove
();});
var
permArray
=
[];
$
(
"#asset_group_permed"
).
children
().
each
(
function
(){
permArray
.
push
(
$
(
this
).
text
());
});
$
(
"#asset_groups"
).
children
().
each
(
function
(){
if
(
$
(
this
).
text
().
search
(
text
)
!=
-
1
&&
permArray
.
indexOf
(
$
(
this
).
text
())
==
-
1
)
{
$
(
"#asset_group_unperm"
).
append
(
$
(
this
).
clone
())
}
});
}
</script>
{% 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"
>
<!-- title -->
<div
class=
"ibox-title"
>
<h5>
授权编辑表单
<small>
Edit perm of Group
</small></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>
<ul
class=
"dropdown-menu dropdown-user"
>
<li><a
href=
"#"
>
Config option 1
</a>
</li>
<li><a
href=
"#"
>
Config option 2
</a>
</li>
</ul>
<a
class=
"close-link"
>
<i
class=
"fa fa-times"
></i>
</a>
</div>
</div>
<!-- end title -->
<div
class=
"ibox-content"
>
<div
class=
"row"
>
<div
class=
"col-sm-5 "
>
<div
class=
"form-group"
>
<label></label>
<input
type=
"text"
id=
"group_filter"
placeholder=
"Search"
class=
"form-control"
value=
""
oninput=
"search_host(this.value)"
>
</div>
</div>
<div
class=
"col-sm-1 "
>
<div
class=
"form-group"
>
<label></label>
</div>
</div>
<div
class=
"col-sm-5 "
>
<div
class=
"form-group"
>
<label></label>
<input
type=
"text"
class=
"form-control"
value=
"{{ user_group.name }}"
readonly
>
</div>
</div>
</div>
<form
method=
"post"
action=
""
>
<input
type=
"text"
name=
"user_group_name"
class=
"form-control"
value=
"{{ user_group.name }}"
style=
"display: none"
>
<div
class=
"row"
>
<div
class=
"col-sm-5"
><h4>
未授权主机组
</h4>
<div>
<select
id=
"asset_groups"
name=
"asset_groups"
class=
"form-control"
size=
"10"
multiple
style=
"display: none"
>
{% for asset_group in asset_groups %}
<option
value=
"{{ asset_group.id }}"
>
{{ asset_group.name }}
</option>
{% endfor %}
</select>
<select
id=
"asset_group_unperm"
name=
"asset_group_unperm"
class=
"form-control m-b"
size=
"12"
multiple
>
{% for asset_group in asset_groups_unperm %}
<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: 50px;"
>
<button
type=
"button"
class=
"btn btn-white"
onclick=
"move('asset_group_unperm', 'asset_group_permed')"
><i
class=
"fa fa-chevron-right"
></i></button>
<button
type=
"button"
class=
"btn btn-white"
onclick=
"move('asset_group_permed', 'asset_group_unperm')"
><i
class=
"fa fa-chevron-left"
></i>
</button>
</div>
</div>
<div
class=
"col-sm-5"
><h4>
授权主机
</h4>
<div>
<select
id=
"asset_group_permed"
name=
"asset_group_permed"
class=
"form-control m-b"
size=
"12"
multiple
>
{% for asset_group in asset_groups_permed %}
<option
value=
"{{ asset_group.id }}"
>
{{ asset_group.name }}
</option>
{% endfor %}
</select>
</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=
"submit"
>
取消
</button>
<button
class=
"btn btn-primary"
type=
"submit"
onclick=
"javascript: (function(){$('#asset_group_permed option').each(function(){$(this).prop('selected', true)})})()"
>
确认保存
</button>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
<script>
var
str
=
document
.
location
.
pathname
.
split
(
"/"
)[
1
];
var
str1
=
document
.
location
.
pathname
.
split
(
"/"
)[
2
];
$
(
"#"
+
str
).
addClass
(
'active'
);
$
(
"#"
+
str1
).
addClass
(
'active'
);
</script>
{#
<script
type=
"text/javascript"
>
#
}
{
#
$
(
"#asset_group_permed"
).
children
().
each
(
function
(){
#
}
{
#
$
(
"#asset_groups"
).
append
(
$
(
this
).
clone
());
#
}
{
##
}
{
#
if
(
$
(
this
).
prop
(
"selected"
)
==
false
)
{
#
}
{
#
$
(
"#asset_group_unperm"
).
append
(
this
);
#
}
{
#
}
#
}
{
##
}
{
#
$
(
"#asset_groups"
).
children
().
each
(
function
(){
$
(
this
).
prop
(
"selected"
,
false
)});
#
}
{
#
});
#
}
{
#
</script>
#}
{% endblock %}
\ No newline at end of file
templates/jperm/perm_list.html
View file @
2a645747
{% 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.username }}
<small>
show perm host info.
</small></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
>
<ul
class=
"dropdown-menu dropdown-user"
>
<li><a
href=
"#"
>
未启用 1
</a
>
</li
>
<li><a
href=
"#"
>
未启用 2
</a
>
</li
>
</
ul
>
<a
class=
"close-link"
>
<i
class=
"fa fa-times"
></i
>
<
/a
>
</
div
>
{% 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>
用户组授权
<small>
show host perm info.
</small>
</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
>
<ul
class=
"dropdown-menu dropdown-user"
>
<li><a
href=
"#"
>
未启用 1
</a
>
</li
>
<li><a
href=
"#"
>
未启用 2
</a
>
</
li
>
</ul
>
<a
class=
"close-link"
>
<
i
class=
"fa fa-times"
></i
>
</
a
>
</div>
<div
class=
"ibox-content"
style=
"display: block;"
>
<form
method=
"post"
action=
""
>
<table
class=
"table table-hover"
>
<thead>
<tr>
<th>
ID
</th>
<th>
IP
</th>
</tr>
</thead>
<tbody>
{% for host in hosts %}
<tr>
<td>
{{ host.id }}
</td>
<td>
{{ host.ip }}
</td>
</tr>
{% endfor %}
</tbody>
</table>
<div
class=
"form-group"
>
<div
class=
"col-sm-4 col-sm-offset-2"
>
<button
class=
"btn btn-white"
type=
"submit"
>
取消
</button>
<button
id=
"submit_button"
class=
"btn btn-primary"
type=
"submit"
>
确认删除
</button>
</div>
<div
class=
"ibox-content"
>
<div
class=
"panel blank-panel"
>
<div
class=
"panel-heading"
>
<div
class=
"panel-options"
>
<ul
class=
"nav nav-tabs"
>
<li
class=
"active"
><a
data-toggle=
"tab"
href=
"#tab-1"
>
授权编辑
</a></li>
<li
class=
""
><a
data-toggle=
"tab"
href=
"#tab-2"
>
查看授权
</a></li>
</ul>
</div>
</div>
<div
class=
"panel-body"
>
<div
class=
"tab-content"
>
<div
id=
"tab-1"
class=
"tab-pane active"
>
<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 group in contacts.object_list %}
<tr
class=
"gradeX"
>
<td
class=
"text-center"
>
{{ group.name }}
</td>
<td
class=
"text-center"
>
{{ group.type|group_type_to_str }}
</td>
<td
class=
"text-center"
>
{{ group.id|member_count }}
</td>
<td
class=
"text-center"
>
{{ group.id|perm_count }}
</td>
<td
class=
"text-center"
>
<a
href=
"../perm_detail/?id={{ group.id }}"
class=
"iframe btn btn-xs btn-primary"
>
详情
</a>
<a
href=
"../perm_edit/?id={{ group.id }}"
class=
"btn btn-xs btn-info"
>
编辑
</a>
<a
href=
"../perm_del/?id={{ 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 {{ contacts.start_index }} to {{ contacts.end_index }} of {{ p.count }} entries
</div>
</div>
<div
class=
"col-sm-6"
>
<div
class=
"dataTables_paginate paging_simple_numbers"
id=
"editable_paginate"
>
<ul
class=
"pagination"
style=
"margin-top: 0; float: right"
>
{% if contacts.has_previous %}
<li
class=
"paginate_button previous"
aria-controls=
"editable"
tabindex=
"0"
id=
"editable_previous"
>
<a
href=
"?page={{ contacts.previous_page_number }}"
>
Previous
</a>
</li>
{% else %}
<li
class=
"paginate_button previous disabled"
aria-controls=
"editable"
tabindex=
"0"
id=
"editable_previous"
>
<a
href=
"#"
>
Previous
</a>
</li>
{% endif %}
{% for page in p.page_range %}
{% ifequal offset1 page %}
<li
class=
"paginate_button active"
aria-controls=
"editable"
tabindex=
"0"
><a
href=
"?page={{ page }}"
title=
"第{{ page }}页"
>
{{ page }}
</a></li>
{% else %}
<li
class=
"paginate_button"
aria-controls=
"editable"
tabindex=
"0"
><a
href=
"?page={{ page }}"
title=
"第{{ page }}页"
>
{{ page }}
</a></li>
{% endifequal %}
{% endfor %}
{% if contacts.has_next %}
<li
class=
"paginate_button next"
aria-controls=
"editable"
tabindex=
"0"
id=
"editable_next"
>
<a
href=
"?page={{ contacts.next_page_number }}"
>
Next
</a>
</li>
{% else %}
<li
class=
"paginate_button next disabled"
aria-controls=
"editable"
tabindex=
"0"
id=
"editable_next"
>
<a
href=
"#"
>
Next
</a>
</li>
{% endif %}
</ul>
</div>
</div>
</div>
</div>
<div
id=
"tab-2"
class=
"tab-pane"
>
<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 in contacts2.object_list %}
<tr
class=
"gradeX"
>
<td
class=
"text-center"
>
{{ user.name }}
</td>
<td
class=
"text-center"
>
{{ user.id | get_role }}
</td>
<td
class=
"text-center"
>
{{ user.username | groups_str }}
</td>
<td
class=
"text-center"
>
{{ user.id | perm_asset_count }}
</td>
<td
class=
"text-center"
>
<a
href=
"../perm_asset_detail/?id={{ user.id }}"
class=
"iframe btn btn-xs btn-primary"
>
详情
</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 {{ contacts2.start_index }} to {{ contacts2.end_index }} of {{ p2.count }} entries
</div>
</div>
<div
class=
"col-sm-6"
>
<div
class=
"dataTables_paginate paging_simple_numbers"
id=
"editable_paginate"
>
<ul
class=
"pagination"
style=
"margin-top: 0; float: right"
>
{% if contacts2.has_previous %}
<li
class=
"paginate_button previous"
aria-controls=
"editable"
tabindex=
"0"
id=
"editable_previous"
>
<a
href=
"?page={{ contacts2.previous_page_number }}"
>
Previous
</a>
</li>
{% else %}
<li
class=
"paginate_button previous disabled"
aria-controls=
"editable"
tabindex=
"0"
id=
"editable_previous"
>
<a
href=
"#"
>
Previous
</a>
</li>
{% endif %}
{% for page in p2.page_range %}
{% ifequal offset1 page %}
<li
class=
"paginate_button active"
aria-controls=
"editable"
tabindex=
"0"
><a
href=
"?page={{ page }}"
title=
"第{{ page }}页"
>
{{ page }}
</a></li>
{% else %}
<li
class=
"paginate_button"
aria-controls=
"editable"
tabindex=
"0"
><a
href=
"?page={{ page }}"
title=
"第{{ page }}页"
>
{{ page }}
</a></li>
{% endifequal %}
{% endfor %}
{% if contacts2.has_next %}
<li
class=
"paginate_button next"
aria-controls=
"editable"
tabindex=
"0"
id=
"editable_next"
>
<a
href=
"?page={{ contacts2.next_page_number }}"
>
Next
</a>
</li>
{% else %}
<li
class=
"paginate_button next disabled"
aria-controls=
"editable"
tabindex=
"0"
id=
"editable_next"
>
<a
href=
"#"
>
Next
</a>
</li>
{% endif %}
</ul>
</div>
</div>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
$
(
document
).
ready
(
function
(){
$
(
".iframe"
).
colorbox
({
iframe
:
true
,
width
:
"70%"
,
height
:
"70%"
});
});
</script>
{% endblock %}
\ No newline at end of file
templates/jperm/perm_user_list.html
deleted
100644 → 0
View file @
a8991bfb
{% 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>
用户信息
<small>
show user info.
</small></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>
<ul
class=
"dropdown-menu dropdown-user"
>
<li><a
href=
"#"
>
未启用 1
</a>
</li>
<li><a
href=
"#"
>
未启用 2
</a>
</li>
</ul>
<a
class=
"close-link"
>
<i
class=
"fa fa-times"
></i>
</a>
</div>
</div>
<div
class=
"ibox-content"
style=
"display: block;"
>
<form
method=
"post"
action=
""
>
<table
class=
"table table-hover"
>
<thead>
<tr>
<th>
ID
</th>
<th>
添加授权
</th>
</tr>
</thead>
<tbody>
{% for user in users %}
<tr>
<td>
{{ user.id }}
</td>
<td>
{{ user.username }}
</td>
<td><a
href=
"../perm_add/?username={{ user.username }}"
>
添加权限
</a></td>
</tr>
{% endfor %}
</tbody>
</table>
<div
class=
"form-group"
>
<div
class=
"col-sm-4 col-sm-offset-2"
>
<button
class=
"btn btn-white"
type=
"submit"
>
取消
</button>
<button
id=
"submit_button"
class=
"btn btn-primary"
type=
"submit"
>
确认删除
</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
\ No newline at end of file
templates/jperm/perm_user_show.html
deleted
100644 → 0
View file @
a8991bfb
{% 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>
用户信息
<small>
show user info.
</small></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>
<ul
class=
"dropdown-menu dropdown-user"
>
<li><a
href=
"#"
>
未启用 1
</a>
</li>
<li><a
href=
"#"
>
未启用 2
</a>
</li>
</ul>
<a
class=
"close-link"
>
<i
class=
"fa fa-times"
></i>
</a>
</div>
</div>
<div
class=
"ibox-content"
style=
"display: block;"
>
<form
method=
"post"
action=
""
>
<table
class=
"table table-hover"
>
<thead>
<tr>
<th>
ID
</th>
<th>
添加授权
</th>
</tr>
</thead>
<tbody>
{% for user in users %}
<tr>
<td>
{{ user.id }}
</td>
<td>
{{ user.username }}
</td>
<td><a
href=
"../perm_list/?username={{ user.username }}"
>
查看权限
</a></td>
</tr>
{% endfor %}
</tbody>
</table>
<div
class=
"form-group"
>
<div
class=
"col-sm-4 col-sm-offset-2"
>
<button
class=
"btn btn-white"
type=
"submit"
>
取消
</button>
<button
id=
"submit_button"
class=
"btn btn-primary"
type=
"submit"
>
确认删除
</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
\ No newline at end of file
templates/juser/group_add.html
View file @
2a645747
...
...
@@ -27,7 +27,7 @@
</div>
</div>
<div
class=
"ibox-content"
>
<form
method=
"post"
class=
"form-horizontal"
action=
""
>
<form
id=
"groupForm"
method=
"post"
class=
"form-horizontal"
action=
""
>
{% if error %}
<div
class=
"alert alert-warning text-center"
>
{{ error }}
</div>
{% endif %}
...
...
@@ -47,6 +47,47 @@
</div>
</div>
<div
class=
"hr-line-dashed"
></div>
<div
class=
"form-group"
>
<label
for=
"group_type"
class=
"col-sm-2 control-label"
>
类型
<span
class=
"red-fonts"
>
*
</span></label>
<div
class=
"col-sm-8"
>
<select
id=
"group_type"
name=
"group_type"
class=
"form-control m-b"
>
{% for t, type_name in group_types.items %}
{% ifequal t group_type %}
<option
value=
"{{ t }}"
selected
>
{{ type_name }}
</option>
{% else %}
<option
value=
"{{ t }}"
>
{{ type_name }}
</option>
{% endifequal %}
{% endfor %}
</select>
</div>
</div>
<div
class=
"hr-line-dashed"
></div>
<div
class=
"form-group"
>
<label
for=
"groups"
class=
"col-lg-2 control-label"
>
用户
</label>
<div
class=
"col-sm-3"
>
<select
id=
"users"
name=
"users"
size=
"12"
class=
"form-control m-b"
multiple
>
{% for user in users %}
<option
value=
"{{ user.id }}"
>
{{ user.name }}
</option>
{% endfor %}
</select>
</div>
<div
class=
"col-sm-1"
>
<div
class=
"btn-group"
style=
"margin-top: 50px;"
>
<button
type=
"button"
class=
"btn btn-white"
onclick=
"move('users', 'users_selected')"
><i
class=
"fa fa-chevron-right"
></i></button>
<button
type=
"button"
class=
"btn btn-white"
onclick=
"move('users_selected', 'users')"
><i
class=
"fa fa-chevron-left"
></i>
</button>
</div>
</div>
<div
class=
"col-sm-3"
>
<div>
<select
id=
"users_selected"
name=
"users_selected"
class=
"form-control m-b"
size=
"12"
multiple
>
{% for user in users_selected %}
<option
value=
"{{ user.id }}"
>
{{ user.name }}
</option>
{% endfor %}
</select>
</div>
</div>
</div>
<div
class=
"hr-line-dashed"
></div>
<div
class=
"form-group"
>
<label
for=
"comment"
class=
"col-sm-2 control-label"
>
备注
</label>
<div
class=
"col-sm-8"
>
...
...
@@ -58,7 +99,7 @@
<div
class=
"form-group"
>
<div
class=
"col-sm-4 col-sm-offset-2"
>
<button
class=
"btn btn-white"
type=
"submit"
>
取消
</button>
<button
class=
"btn btn-primary"
type=
"submit"
>
确认保存
</button>
<button
class=
"btn btn-primary"
type=
"submit"
onclick=
"javascript: (function(){$('#users_selected option').each(function(){$(this).prop('selected', true)})})()"
>
确认保存
</button>
</div>
</div>
</form>
...
...
@@ -67,4 +108,28 @@
</div>
</div>
</div>
<script>
$
(
'#groupForm'
).
validator
({
timely
:
2
,
theme
:
"yellow_right_effect"
,
fields
:
{
"group_name"
:
{
rule
:
"required"
,
tip
:
"输入组名"
,
ok
:
""
,
msg
:
{
required
:
"必须填写!"
}
},
"group_type"
:
{
rule
:
"checked"
,
tip
:
"选择组类型"
,
ok
:
""
,
msg
:
{
required
:
"至少选择一个组!"
}
}
},
valid
:
function
(
form
)
{
form
.
submit
();
}
});
</script>
{% endblock %}
\ No newline at end of file
templates/juser/group_detail.html
View file @
2a645747
...
...
@@ -20,23 +20,22 @@
<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 in users %}
<tr
class=
"gradeX"
>
<td
class=
"text-center"
>
ID
</td>
<td
class=
"text-center"
>
{{ group.id }}
</td>
</tr>
<tr
class=
"gradeX"
>
<td
class=
"text-center"
>
组名
</td>
<td
class=
"text-center"
>
{{ group.name }}
</td>
</tr>
<tr
class=
"gradeX"
>
<td
class=
"text-center"
>
备注
</td>
<td
class=
"text-center"
>
{{ group_comment }}
</td>
<td
class=
"text-center"
>
{{ user.username }}
</td>
<td
class=
"text-center"
>
{{ user.name }}
</td>
<td
class=
"text-center"
>
{{ user.id|get_role }}
</td>
</tr>
{% endfor %}
</tbody>
</tbody>
</table>
</div>
</div>
...
...
templates/juser/group_list.html
View file @
2a645747
...
...
@@ -36,9 +36,10 @@
<table
class=
"table table-striped table-bordered table-hover "
id=
"editable"
>
<thead>
<tr>
<th
class=
"text-center"
><input
type=
"checkbox"
class=
"i-checks"
name=
""
></th>
<th
class=
"text-center"
>
ID
</th>
<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>
...
...
@@ -46,12 +47,13 @@
<tbody>
{% for group in contacts.object_list %}
<tr
class=
"gradeX"
>
<td
class=
"text-center"
><input
type=
"checkbox"
class=
"i-checks"
name=
""
></td>
<td
class=
"text-center"
>
{{ group.id }}
</td>
<td
class=
"text-center"
>
{{ group.name }}
</td>
<td
class=
"text-center"
>
{{ group.type|group_type_to_str }}
</td>
<td
class=
"text-center"
>
{{ group.id|member_count }}
</td>
<td
class=
"text-center"
>
{{ group.comment }}
</td>
<td
class=
"text-center"
>
<a
href=
"../group_detail/?id={{ group.id }}"
class=
"iframe btn btn-xs btn-primary"
>
详情
</a>
<a
href=
"../group_detail/?id={{ group.id }}"
class=
"iframe btn btn-xs btn-primary"
>
成员
</a>
<a
href=
"../group_edit/?id={{ group.id }}"
class=
"btn btn-xs btn-info"
>
编辑
</a>
<a
href=
"../group_del/?id={{ group.id }}"
class=
"btn btn-xs btn-danger"
>
删除
</a>
</td>
...
...
templates/juser/user_add.html
View file @
2a645747
{% extends 'base.html' %}
{% load mytags %}
{% block content %}
{% include 'nav_cat_bar.html' %}
<div
class=
"wrapper wrapper-content animated fadeInRight"
>
...
...
@@ -28,7 +29,7 @@
</div>
</div>
<div
class=
"ibox-content"
>
<form
method=
"post"
class=
"form-horizontal"
action=
""
>
<form
method=
"post"
id=
"userForm"
class=
"form-horizontal"
action=
""
>
{% if error %}
<div
class=
"alert alert-warning text-center"
>
{{ error }}
</div>
{% endif %}
...
...
@@ -53,9 +54,9 @@
</div>
<div
class=
"hr-line-dashed"
></div>
<div
class=
"form-group"
>
<label
for=
"ssh_key_pwd
1
"
class=
"col-sm-2 control-label"
>
密钥密码
<span
class=
"red-fonts"
>
*
</span></label>
<label
for=
"ssh_key_pwd"
class=
"col-sm-2 control-label"
>
密钥密码
<span
class=
"red-fonts"
>
*
</span></label>
<div
class=
"col-sm-8"
>
<input
id=
"ssh_key_pwd
1"
name=
"ssh_key_pwd1"
placeholder=
"SSH Key Password"
type=
"password"
class=
"form-control"
value=
"{{ ssh_key_pwd1
}}"
>
<input
id=
"ssh_key_pwd
"
name=
"ssh_key_pwd"
placeholder=
"SSH Key Password"
type=
"password"
class=
"form-control"
value=
"{{ ssh_key_pwd
}}"
>
<span
class=
"help-block m-b-none"
>
登陆 Jumpserver 使用的SSH密钥的密码
</span>
...
...
@@ -72,19 +73,19 @@
<div
class=
"form-group"
>
<label
for=
"groups"
class=
"col-lg-2 control-label"
>
属组
<span
class=
"red-fonts"
>
*
</span></label>
<div
class=
"col-sm-8"
>
<select
id=
"groups"
name=
"groups"
class=
"form-control m-b"
multiple
>
<select
id=
"groups"
name=
"groups"
class=
"form-control m-b"
multiple
size=
"10"
>
{% for group in all_group %}
{% if groups_str %}
{% if group.id|int2str in groups_str %}
<option
value=
"{{ group.id }}"
selected
>
{{ group.name }}
</option>
<option
value=
"{{ group.id }}"
selected
>
{{ group.name }}
--- {{ group.type|group_type_to_str }}
</option>
{% else %}
<option
value=
"{{ group.id }}"
>
{{ group.name }}
</option>
<option
value=
"{{ group.id }}"
>
{{ group.name }}
--- {{ group.type|group_type_to_str }}
</option>
{% endif %}
{% else %}
{% if forloop.first %}
<option
value=
"{{ group.id }}"
selected
>
{{ group.name }}
</option>
<option
value=
"{{ group.id }}"
selected
>
{{ group.name }}
--- {{ group.type|group_type_to_str }}
</option>
{% else %}
<option
value=
"{{ group.id }}"
>
{{ group.name }}
</option>
<option
value=
"{{ group.id }}"
>
{{ group.name }}
--- {{ group.type|group_type_to_str }}
</option>
{% endif %}
{% endif %}
{% endfor %}
...
...
@@ -118,7 +119,7 @@
</div>
<div
class=
"hr-line-dashed"
></div>
<div
class=
"form-group"
>
<label
for=
"email"
class=
"col-sm-2 control-label"
>
Email
</label>
<label
for=
"email"
class=
"col-sm-2 control-label"
>
Email
<
span
class=
"red-fonts"
>
*
</span><
/label>
<div
class=
"col-sm-8"
>
<input
id=
"email"
name=
"email"
type=
"email"
placeholder=
"Email"
class=
"form-control"
value=
"{{ email }}"
>
</div>
...
...
@@ -148,4 +149,67 @@
</div>
</div>
<script>
$
(
'#userForm'
).
validator
({
timely
:
2
,
theme
:
"yellow_right_effect"
,
rules
:
{
check_ip
:
[
/^
(\d{1,2}
|1
\d\d
|2
[
0-4
]\d
|25
[
0-5
])(\.(\d{1,2}
|1
\d\d
|2
[
0-4
]\d
|25
[
0-5
])){3}
$/
,
'ip地址不正确'
],
check_port
:
[
/^
\d{1,5}
$/
,
'端口号不正确'
],
type_m
:
function
(
element
){
return
$
(
"#M"
).
is
(
":checked"
);
}
},
fields
:
{
"username"
:
{
rule
:
"required"
,
tip
:
"输入用户名"
,
ok
:
""
,
msg
:
{
required
:
"必须填写!"
}
},
"password"
:
{
rule
:
"required;length[6~50]"
,
tip
:
"输入密码"
,
ok
:
""
,
msg
:
{
required
:
"必须填写!"
}
},
"ssh_key_pwd"
:
{
rule
:
"required;length[6~50]"
,
tip
:
"ssh私钥密码"
,
ok
:
""
,
msg
:
{
required
:
"必须填写"
}
},
"groups"
:
{
rule
:
"checked"
,
tip
:
"选择用户组"
,
ok
:
""
,
msg
:
{
checked
:
"至少选择一个组"
}
},
"name"
:
{
rule
:
"required"
,
tip
:
"姓名"
,
ok
:
""
,
msg
:
{
required
:
"必须填写"
}
},
"email"
:
{
rule
:
"required"
,
tip
:
"Email"
,
ok
:
""
,
msg
:
{
required
:
"必须填写"
}
},
"role"
:
{
rule
:
"checked"
,
tip
:
"角色"
,
ok
:
""
,
msg
:
{
required
:
"选择一个"
}
}
},
valid
:
function
(
form
)
{
form
.
submit
();
}
});
</script>
{% endblock %}
\ No newline at end of file
templates/juser/user_detail.html
View file @
2a645747
...
...
@@ -16,9 +16,6 @@
<div
class=
"contact-box"
>
<h2
class=
"text-center"
>
{{ user.name }} 用户详情
</h2>
<div
class=
"ibox-content"
>
<div
class=
""
>
<a
target=
"_blank"
href=
"/juser/user_add/"
class=
"btn btn-sm btn-primary "
>
添加
</a>
</div>
<table
class=
"table table-striped table-bordered table-hover "
id=
"editable"
>
<thead>
...
...
@@ -46,7 +43,11 @@
</tr>
<tr
class=
"gradeX"
>
<td
class=
"text-center"
>
属组
</td>
<td
class=
"text-center"
>
{{ user.username|groups_str }}
</td>
<td
class=
"text-center"
>
{% for group in user.user_group.all %}
{{ group.name }}
{% endfor %}
</td>
</tr>
<tr
class=
"gradeX"
>
<td
class=
"text-center"
>
Email
</td>
...
...
@@ -58,7 +59,7 @@
</tr>
<tr
class=
"gradeX"
>
<td
class=
"text-center"
>
添加时间
</td>
<td
class=
"text-center"
>
{{ user.
joined
}}
</td>
<td
class=
"text-center"
>
{{ user.
date_joined|stamp2str
}}
</td>
</tr>
<tr
class=
"gradeX"
>
<td
class=
"text-center"
>
最后登录
</td>
...
...
templates/juser/user_list.html
View file @
2a645747
...
...
@@ -36,13 +36,14 @@
<table
class=
"table table-striped table-bordered table-hover "
id=
"editable"
>
<thead>
<tr>
<th
class=
"text-center"
><input
type=
"checkbox"
class=
"i-checks"
name=
""
></th>
<th
class=
"text-center"
>
<input
type=
"checkbox"
id=
"select_all"
onclick=
"selectAll()"
name=
"select_all"
>
</th>
<th
class=
"text-center"
>
ID
</th>
<th
class=
"text-center"
>
用户名
</th>
<th
class=
"text-center"
>
姓名
</th>
<th
class=
"text-center"
>
属组
</th>
<th
class=
"text-center"
>
角色
</th>
<th
class=
"text-center"
>
Email
</th>
<th
class=
"text-center"
>
激活
</th>
<th
class=
"text-center"
>
操作
</th>
</tr>
...
...
@@ -50,13 +51,14 @@
<tbody>
{% for user in contacts.object_list %}
<tr
class=
"gradeX"
>
<td
class=
"text-center"
><input
type=
"checkbox"
class=
"i-checks"
name=
""
></td>
<td
class=
"text-center"
>
<input
type=
"checkbox"
name=
"selected"
value=
"{{ user.id }}"
>
</td>
<td
class=
"text-center"
>
{{ user.id }}
</td>
<td
class=
"text-center"
>
{{ user.username }}
</td>
<td
class=
"text-center"
>
{{ user.name }}
</td>
<td
class=
"text-center"
>
{{ user.username|groups_str }}
</td>
<td
class=
"text-center"
>
{{ user.id|get_role }}
</td>
<td
class=
"text-center"
>
{{ user.email }}
</td>
<td
class=
"text-center"
>
{{ user.is_active|bool2str }}
</td>
<td
class=
"text-center"
>
<a
href=
"../user_detail/?id={{ user.id }}"
class=
"iframe btn btn-xs btn-primary"
>
详情
</a>
...
...
@@ -117,4 +119,4 @@
});
</script>
{% endblock %}
\ No newline at end of file
{% endblock %}
templates/link_css.html
View file @
2a645747
...
...
@@ -4,4 +4,4 @@
<link
href=
"/static/css/animate.css"
rel=
"stylesheet"
>
<link
href=
"/static/css/style.css"
rel=
"stylesheet"
>
<link
href=
"/static/css/colorbox.css"
rel=
"stylesheet"
>
<link
href=
"/static/css/vaildator/jquery.validator.css"
rel=
"stylesheet"
>
\ No newline at end of file
<link
href=
"/static/css/vaildator/jquery.validator.css"
rel=
"stylesheet"
>
templates/login.html
View file @
2a645747
...
...
@@ -7,7 +7,7 @@
<meta
name=
"viewport"
content=
"width=device-width, initial-scale=1.0"
>
<title>
JumpServer | Login
</title>
<link
rel=
"shortcut icon"
href=
"/static/img/facio.ico"
type=
"image/x-icon"
>
<link
href=
"/static/css/bootstrap.min.css"
rel=
"stylesheet"
>
<link
href=
"/static/font-awesome/css/font-awesome.css"
rel=
"stylesheet"
>
...
...
@@ -22,22 +22,25 @@
<div>
<div>
<h1
class=
"logo-name"
>
JumpServer
</h1>
<h1
class=
"logo-name"
>
<img
src=
"/static/img/logo.png"
>
</h1>
</div>
<h3>
Welcome to JumpServer
</h3>
<form
class=
"m-t"
role=
"form"
method=
"post"
action=
"/login/"
>
{% if error %}
<div
class=
"alert alert-danger text-center"
>
{{ error }}
</div>
{% endif %}
<h2>
Welcome to JumpServer
</h2>
<form
class=
"m-t"
role=
"form"
method=
"post"
action=
""
>
<div
class=
"form-group"
>
<input
type=
"
email"
class=
"form-control"
placeholder=
"Username"
required=
"
"
>
<input
type=
"
text"
name=
"username"
class=
"form-control"
placeholder=
"Username"
required=
"length[6~50]
"
>
</div>
<div
class=
"form-group"
>
<input
type=
"password"
class=
"form-control"
placeholder=
"Password"
required=
""
>
<input
type=
"password"
name=
"password"
class=
"form-control"
placeholder=
"Password"
required=
""
>
</div>
<button
type=
"submit"
class=
"btn btn-primary block full-width m-b"
>
Login
</button>
<a
href=
"#"
><small>
Forgot password?
</small></a>
</form>
<p
class=
"m-t"
>
<small>
Inspinia we app framework base on Bootstrap 3
©
2014
</small>
</p>
<p
class=
"m-t"
>
<small>
<b>
Copyright
</b>
Jumpserver.org Organization © 2014-2015
</small>
</p>
</div>
</div>
...
...
templates/nav.html
View file @
2a645747
...
...
@@ -32,10 +32,8 @@
<li
id=
"jperm"
>
<a
href=
"#"
><i
class=
"fa fa-edit"
></i>
<span
class=
"nav-label"
>
授权管理
</span><span
class=
"fa arrow"
></span></a>
<ul
class=
"nav nav-second-level"
>
<li><a
href=
"/jperm/perm_user_show/"
>
查看授权
</a></li>
<li><a
href=
"/jperm/perm_user_list/"
>
添加授权
</a></li>
<li><a
href=
"/jperm/showlist/"
>
查看sudo
</a></li>
<li><a
href=
"/jperm/add/"
>
添加sudo
</a></li>
<li
id=
"perm_list"
><a
href=
"/jperm/perm_list/"
>
主机授权
</a></li>
<li
id=
"perm_sudo"
><a
href=
"/jperm/perm_sudo/"
>
Sudo授权
</a></li>
</ul>
</li>
<li
id=
"jlog"
>
...
...
templates/nav_bar_header.html
View file @
2a645747
...
...
@@ -108,7 +108,7 @@
</li>
<li>
<a
href=
"
login.html
"
>
<a
href=
"
/logout/
"
>
<i
class=
"fa fa-sign-out"
></i>
Log out
</a>
</li>
...
...
templates/nav_li_profile.html
View file @
2a645747
...
...
@@ -10,10 +10,11 @@
<li><a
href=
"contacts.html"
>
Contacts
</a></li>
<li><a
href=
"mailbox.html"
>
Mailbox
</a></li>
<li
class=
"divider"
></li>
<li><a
href=
"
login.html
"
>
Logout
</a></li>
<li><a
href=
"
/logout/
"
>
Logout
</a></li>
</ul>
</div>
<div
class=
"logo-element"
>
JS+
</div>
</li>
templates/script.html
View file @
2a645747
...
...
@@ -7,28 +7,63 @@
<script
src=
"/static/js/mindmup-editabletable.js"
></script>
<script
src=
"/static/js/base.js"
></script>
<!-- Peity -->
<script
src=
"/static/js/plugins/peity/jquery.peity.min.js"
></script>
<!-- Custom and plugin javascript -->
<script
src=
"/static/js/inspinia.js"
></script>
<script
src=
"/static/js/plugins/pace/pace.min.js"
></script>
<!-- iCheck -->
<!-- iCheck
box
-->
<script
src=
"/static/js/plugins/iCheck/icheck.min.js"
></script>
<!-- Peity -->
<script
src=
"/static/js/plugins/peity/jquery.peity.min.js"
></script>
<!-- Peity -->
<script
src=
"/static/js/demo/peity-demo.js"
></script>
<!--<script>-->
<!--$(document).ready(function(){-->
<!--$('.i-checks').iCheck({-->
<!--checkboxClass: 'icheckbox_square-green',-->
<!--radioClass: 'iradio_square-green',-->
<!--});-->
<!--});-->
<script>
$
(
document
).
ready
(
function
(){
$
(
'.i-checks'
).
iCheck
({
checkboxClass
:
'icheckbox_square-green'
,
radioClass
:
'iradio_square-green'
});
});
function
selectAll
(){
var
checklist
=
document
.
getElementsByName
(
"selected"
);
if
(
document
.
getElementById
(
"select_all"
).
checked
)
{
for
(
var
i
=
0
;
i
<
checklist
.
length
;
i
++
)
{
checklist
[
i
].
checked
=
1
;
}
}
else
{
for
(
var
j
=
0
;
j
<
checklist
.
length
;
j
++
)
{
checklist
[
j
].
checked
=
0
;
}
}
}
function
move
(
from
,
to
)
{
$
(
"#"
+
from
+
" option"
).
each
(
function
(){
if
(
$
(
this
).
prop
(
"selected"
)
==
true
)
{
$
(
"#"
+
to
).
append
(
this
);
}
});
}
function
move_all
(
from
,
to
){
$
(
"#"
+
from
).
children
().
each
(
function
(){
$
(
"#"
+
to
).
append
(
this
);
});
}
</script>
<!--</script>-->
<!-- pop windows -->
<script
src=
"/static/js/jquery.colorbox.js"
></script>
...
...
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