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
a79c3dd1
Commit
a79c3dd1
authored
Feb 06, 2017
by
ibuler
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[Fixture] 添加command log backends, 未来支持es
parent
0869931e
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
39 changed files
with
566 additions
and
243 deletions
+566
-243
api.py
apps/applications/api.py
+2
-1
user.py
apps/assets/models/user.py
+10
-0
views.py
apps/assets/views.py
+7
-9
__init__.py
apps/audits/__init__.py
+1
-0
api.py
apps/audits/api.py
+19
-5
__init__.py
apps/audits/backends/__init__.py
+6
-0
__init__.py
apps/audits/backends/command/__init__.py
+0
-0
base.py
apps/audits/backends/command/base.py
+19
-0
db.py
apps/audits/backends/command/db.py
+45
-0
serializers.py
apps/audits/backends/command/serializers.py
+21
-0
models.py
apps/audits/models.py
+35
-38
serializers.py
apps/audits/serializers.py
+2
-10
command_log_list.html
apps/audits/templates/audits/command_log_list.html
+15
-16
proxy_log_detail.html
apps/audits/templates/audits/proxy_log_detail.html
+3
-3
proxy_log_list.html
apps/audits/templates/audits/proxy_log_list.html
+39
-30
api_urls.py
apps/audits/urls/api_urls.py
+2
-1
views.py
apps/audits/views.py
+0
-0
common_tags.py
apps/common/templatetags/common_tags.py
+25
-4
utils.py
apps/common/utils.py
+6
-4
middleware.py
apps/jumpserver/middleware.py
+14
-0
settings.py
apps/jumpserver/settings.py
+3
-0
api.py
apps/perms/api.py
+43
-0
forms.py
apps/perms/forms.py
+0
-11
hands.py
apps/perms/hands.py
+4
-4
models.py
apps/perms/models.py
+33
-12
asset_permission_detail.html
apps/perms/templates/perms/asset_permission_detail.html
+66
-4
asset_permission_user.html
apps/perms/templates/perms/asset_permission_user.html
+28
-23
tests.py
apps/perms/tests.py
+3
-1
api_urls.py
apps/perms/urls/api_urls.py
+6
-1
utils.py
apps/perms/utils.py
+36
-5
views.py
apps/perms/views.py
+22
-3
jumpserver.js
apps/static/js/jumpserver.js
+22
-22
authentication.py
apps/users/authentication.py
+0
-1
forms.py
apps/users/forms.py
+28
-35
group.py
apps/users/views/group.py
+1
-0
deb_requirements.txt
requirements/deb_requirements.txt
+0
-0
mac_requirements.py
requirements/mac_requirements.py
+0
-0
requirements.txt
requirements/requirements.txt
+0
-0
rpm_requirements.txt
requirements/rpm_requirements.txt
+0
-0
No files found.
apps/applications/api.py
View file @
a79c3dd1
# -*- coding: utf-8 -*-
# -*- coding: utf-8 -*-
#
#
from
collections
import
OrderedDict
from
django.core.cache
import
cache
from
django.core.cache
import
cache
from
django.conf
import
settings
from
django.conf
import
settings
import
copy
import
copy
...
@@ -35,7 +36,7 @@ class TerminalRegisterView(ListCreateAPIView):
...
@@ -35,7 +36,7 @@ class TerminalRegisterView(ListCreateAPIView):
if
serializer
.
is_valid
():
if
serializer
.
is_valid
():
terminal
=
serializer
.
save
()
terminal
=
serializer
.
save
()
app_user
,
access_key
=
terminal
.
create_related_app_user
()
app_user
,
access_key
=
terminal
.
create_related_app_user
()
data
=
{}
data
=
OrderedDict
()
data
[
'terminal'
]
=
copy
.
deepcopy
(
serializer
.
data
)
data
[
'terminal'
]
=
copy
.
deepcopy
(
serializer
.
data
)
data
[
'user'
]
=
app_user
.
to_json
()
data
[
'user'
]
=
app_user
.
to_json
()
data
[
'access_key_id'
]
=
access_key
.
id
data
[
'access_key_id'
]
=
access_key
.
id
...
...
apps/assets/models/user.py
View file @
a79c3dd1
...
@@ -167,6 +167,16 @@ class SystemUser(models.Model):
...
@@ -167,6 +167,16 @@ class SystemUser(models.Model):
def
asset_group_amount
(
self
):
def
asset_group_amount
(
self
):
return
self
.
asset_groups
.
count
()
return
self
.
asset_groups
.
count
()
def
to_json
(
self
):
return
{
'id'
:
self
.
id
,
'name'
:
self
.
name
,
'username'
:
self
.
username
,
'protocol'
:
self
.
protocol
,
'auth_method'
:
self
.
auth_method
,
'auto_push'
:
self
.
auto_push
,
}
class
Meta
:
class
Meta
:
ordering
=
[
'name'
]
ordering
=
[
'name'
]
...
...
apps/assets/views.py
View file @
a79c3dd1
...
@@ -233,9 +233,6 @@ class AssetGroupCreateView(AdminUserRequiredMixin, CreateView):
...
@@ -233,9 +233,6 @@ class AssetGroupCreateView(AdminUserRequiredMixin, CreateView):
form_class
=
forms
.
AssetGroupForm
form_class
=
forms
.
AssetGroupForm
template_name
=
'assets/asset_group_create.html'
template_name
=
'assets/asset_group_create.html'
success_url
=
reverse_lazy
(
'assets:asset-group-list'
)
success_url
=
reverse_lazy
(
'assets:asset-group-list'
)
#ordering = '-id'
# Todo: Asset group create template select assets so hard, need be resolve next
def
get_context_data
(
self
,
**
kwargs
):
def
get_context_data
(
self
,
**
kwargs
):
context
=
{
context
=
{
...
@@ -249,7 +246,8 @@ class AssetGroupCreateView(AdminUserRequiredMixin, CreateView):
...
@@ -249,7 +246,8 @@ class AssetGroupCreateView(AdminUserRequiredMixin, CreateView):
def
form_valid
(
self
,
form
):
def
form_valid
(
self
,
form
):
asset_group
=
form
.
save
()
asset_group
=
form
.
save
()
assets_id_list
=
self
.
request
.
POST
.
getlist
(
'assets'
,
[])
assets_id_list
=
self
.
request
.
POST
.
getlist
(
'assets'
,
[])
assets
=
[
get_object_or_404
(
Asset
,
id
=
int
(
asset_id
))
for
asset_id
in
assets_id_list
]
assets
=
[
get_object_or_404
(
Asset
,
id
=
int
(
asset_id
))
for
asset_id
in
assets_id_list
]
asset_group
.
created_by
=
self
.
request
.
user
.
username
or
'Admin'
asset_group
.
created_by
=
self
.
request
.
user
.
username
or
'Admin'
asset_group
.
assets
.
add
(
*
tuple
(
assets
))
asset_group
.
assets
.
add
(
*
tuple
(
assets
))
asset_group
.
save
()
asset_group
.
save
()
...
@@ -284,7 +282,8 @@ class AssetGroupDetailView(AdminUserRequiredMixin, DetailView):
...
@@ -284,7 +282,8 @@ class AssetGroupDetailView(AdminUserRequiredMixin, DetailView):
'app'
:
_
(
'Assets'
),
'app'
:
_
(
'Assets'
),
'action'
:
_
(
'Asset group detail'
),
'action'
:
_
(
'Asset group detail'
),
'assets_remain'
:
assets_remain
,
'assets_remain'
:
assets_remain
,
'assets'
:
[
asset
for
asset
in
Asset
.
objects
.
all
()
if
asset
not
in
assets_remain
],
'assets'
:
[
asset
for
asset
in
Asset
.
objects
.
all
()
if
asset
not
in
assets_remain
],
'system_users'
:
system_users
,
'system_users'
:
system_users
,
'system_users_remain'
:
system_users_remain
,
'system_users_remain'
:
system_users_remain
,
}
}
...
@@ -349,10 +348,9 @@ class IDCCreateView(AdminUserRequiredMixin, CreateView):
...
@@ -349,10 +348,9 @@ class IDCCreateView(AdminUserRequiredMixin, CreateView):
return
super
(
IDCCreateView
,
self
)
.
get_context_data
(
**
kwargs
)
return
super
(
IDCCreateView
,
self
)
.
get_context_data
(
**
kwargs
)
def
form_valid
(
self
,
form
):
def
form_valid
(
self
,
form
):
IDC
=
form
.
save
(
commit
=
False
)
idc
=
form
.
save
(
commit
=
False
)
IDC
.
created_by
=
self
.
request
.
user
.
username
or
'System'
idc
.
created_by
=
self
.
request
.
user
.
username
or
'System'
IDC
.
save
()
idc
.
save
()
# IDC_add_success_next(user)
return
super
(
IDCCreateView
,
self
)
.
form_valid
(
form
)
return
super
(
IDCCreateView
,
self
)
.
form_valid
(
form
)
...
...
apps/audits/__init__.py
View file @
a79c3dd1
apps/audits/api.py
View file @
a79c3dd1
...
@@ -5,11 +5,12 @@
...
@@ -5,11 +5,12 @@
from
__future__
import
absolute_import
,
unicode_literals
from
__future__
import
absolute_import
,
unicode_literals
from
rest_framework
import
generics
,
viewsets
from
rest_framework
import
generics
,
viewsets
from
rest_framework.views
import
APIView
,
Response
from
rest_framework_bulk
import
BulkModelViewSet
from
rest_framework_bulk
import
BulkModelViewSet
from
audits.backends
import
command_store
from
audits.backends.command.serializers
import
CommandLogSerializer
from
.
import
models
,
serializers
from
.
import
models
,
serializers
from
.hands
import
IsSuperUserOrAppUser
,
Terminal
,
IsAppUser
from
.hands
import
IsSuperUserOrAppUser
,
IsAppUser
class
ProxyLogReceiveView
(
generics
.
CreateAPIView
):
class
ProxyLogReceiveView
(
generics
.
CreateAPIView
):
...
@@ -47,8 +48,21 @@ class ProxyLogViewSet(viewsets.ModelViewSet):
...
@@ -47,8 +48,21 @@ class ProxyLogViewSet(viewsets.ModelViewSet):
permission_classes
=
(
IsSuperUserOrAppUser
,)
permission_classes
=
(
IsSuperUserOrAppUser
,)
class
CommandLogViewSet
(
viewsets
.
ModelViewSet
):
class
CommandLogViewSet
(
BulkModelViewSet
):
queryset
=
models
.
CommandLog
.
objects
.
all
()
"""接受app发送来的command log, 格式如下
serializer_class
=
serializers
.
CommandLogSerializer
{
"proxy_log_id": 23,
"user": "admin",
"asset": "localhost",
"system_user": "web",
"command_no": 1,
"command": "whoami",
"output": "d2hvbWFp", # base64.b64encode(s)
"timestamp": 1485238673.0
}
"""
queryset
=
command_store
.
all
()
serializer_class
=
CommandLogSerializer
permission_classes
=
(
IsSuperUserOrAppUser
,)
permission_classes
=
(
IsSuperUserOrAppUser
,)
apps/audits/backends/__init__.py
0 → 100644
View file @
a79c3dd1
from
importlib
import
import_module
from
django.conf
import
settings
command_engine
=
import_module
(
settings
.
COMMAND_STORE_BACKEND
)
command_store
=
command_engine
.
CommandStore
()
from
.command.serializers
import
CommandLogSerializer
mac_requirements
.py
→
apps/audits/backends/command/__init__
.py
View file @
a79c3dd1
File moved
apps/audits/backends/command/base.py
0 → 100644
View file @
a79c3dd1
# coding: utf-8
import
abc
class
CommandBase
(
object
):
__metaclass__
=
abc
.
ABCMeta
@abc.abstractmethod
def
save
(
self
,
proxy_log_id
,
user
,
asset
,
system_user
,
command_no
,
command
,
output
,
timestamp
):
pass
@abc.abstractmethod
def
filter
(
self
,
date_from
=
None
,
date_to
=
None
,
user
=
''
,
asset
=
''
,
system_user
=
''
,
command
=
''
):
pass
apps/audits/backends/command/db.py
0 → 100644
View file @
a79c3dd1
# ~*~ coding: utf-8 ~*~
from
.base
import
CommandBase
from
audits.models
import
CommandLog
class
CommandStore
(
CommandBase
):
model
=
CommandLog
queryset
=
[]
def
save
(
self
,
proxy_log_id
,
user
,
asset
,
system_user
,
command_no
,
command
,
output
,
timestamp
):
self
.
model
.
objects
.
create
(
proxy_log_id
=
proxy_log_id
,
user
=
user
,
asset
=
asset
,
system_user
=
system_user
,
command_no
=
command_no
,
command
=
command
,
output
=
output
,
timestamp
=
timestamp
)
def
filter
(
self
,
date_from_ts
=
None
,
date_to_ts
=
None
,
user
=
''
,
asset
=
''
,
system_user
=
''
,
command
=
''
,
proxy_log_id
=
''
):
filter_kwargs
=
{}
if
date_from_ts
:
filter_kwargs
[
'timestamp__gte'
]
=
date_from_ts
if
date_to_ts
:
filter_kwargs
[
'timestamp__lte'
]
=
date_to_ts
if
user
:
filter_kwargs
[
'user'
]
=
user
if
asset
:
filter_kwargs
[
'asset'
]
=
asset
if
system_user
:
filter_kwargs
[
'system_user'
]
=
system_user
if
command
:
filter_kwargs
[
'command__icontains'
]
=
command
if
proxy_log_id
:
filter_kwargs
[
'proxy_log_id'
]
=
proxy_log_id
if
filter_kwargs
:
self
.
queryset
=
self
.
model
.
objects
.
filter
(
**
filter_kwargs
)
return
self
.
queryset
def
all
(
self
):
"""返回所有数据"""
return
self
.
model
.
objects
.
iterator
()
apps/audits/backends/command/serializers.py
0 → 100644
View file @
a79c3dd1
# ~*~ coding: utf-8 ~*~
import
base64
from
rest_framework
import
serializers
from
audits.models
import
CommandLog
from
audits.backends
import
command_store
class
CommandLogSerializer
(
serializers
.
ModelSerializer
):
"""使用这个类作为基础Command Log Serializer类, 用来序列化"""
class
Meta
:
model
=
CommandLog
fields
=
'__all__'
def
save
(
self
):
try
:
output
=
self
.
validated_data
[
'output'
]
self
.
validated_data
[
'output'
]
=
base64
.
b64decode
(
output
)
except
IndexError
:
pass
return
command_store
.
save
(
**
dict
(
self
.
validated_data
))
apps/audits/models.py
View file @
a79c3dd1
...
@@ -24,7 +24,8 @@ class LoginLog(models.Model):
...
@@ -24,7 +24,8 @@ class LoginLog(models.Model):
verbose_name
=
_
(
'Login city'
))
verbose_name
=
_
(
'Login city'
))
user_agent
=
models
.
CharField
(
max_length
=
100
,
blank
=
True
,
null
=
True
,
user_agent
=
models
.
CharField
(
max_length
=
100
,
blank
=
True
,
null
=
True
,
verbose_name
=
_
(
'User agent'
))
verbose_name
=
_
(
'User agent'
))
date_login
=
models
.
DateTimeField
(
auto_now_add
=
True
,
verbose_name
=
_
(
'Date login'
))
date_login
=
models
.
DateTimeField
(
auto_now_add
=
True
,
verbose_name
=
_
(
'Date login'
))
class
Meta
:
class
Meta
:
db_table
=
'login_log'
db_table
=
'login_log'
...
@@ -37,56 +38,52 @@ class ProxyLog(models.Model):
...
@@ -37,56 +38,52 @@ class ProxyLog(models.Model):
(
'WT'
,
'Web Terminal'
),
(
'WT'
,
'Web Terminal'
),
)
)
user
name
=
models
.
CharField
(
max_length
=
20
,
verbose_name
=
_
(
'Username
'
))
user
=
models
.
CharField
(
max_length
=
32
,
verbose_name
=
_
(
'User
'
))
name
=
models
.
CharField
(
max_length
=
20
,
blank
=
True
,
verbose_name
=
_
(
'Name
'
))
asset
=
models
.
CharField
(
max_length
=
32
,
verbose_name
=
_
(
'Asset
'
))
hostname
=
models
.
CharField
(
max_length
=
128
,
blank
=
True
,
verbose_name
=
_
(
'Hostname
'
))
system_user
=
models
.
CharField
(
max_length
=
32
,
verbose_name
=
_
(
'System user
'
))
ip
=
models
.
GenericIPAddressField
(
max_length
=
32
,
verbose_name
=
_
(
'IP'
))
login_type
=
models
.
CharField
(
system_user
=
models
.
CharField
(
max_length
=
20
,
verbose_name
=
_
(
'System user'
))
choices
=
LOGIN_TYPE_CHOICE
,
max_length
=
2
,
blank
=
True
,
login_type
=
models
.
CharField
(
choices
=
LOGIN_TYPE_CHOICE
,
max_length
=
2
,
blank
=
True
,
null
=
True
,
verbose_name
=
_
(
'Login type'
))
null
=
True
,
verbose_name
=
_
(
'Login type'
))
terminal
=
models
.
CharField
(
terminal
=
models
.
CharField
(
max_length
=
32
,
blank
=
True
,
null
=
True
,
verbose_name
=
_
(
'Terminal'
))
max_length
=
32
,
blank
=
True
,
null
=
True
,
verbose_name
=
_
(
'Terminal'
))
log_file
=
models
.
CharField
(
max_length
=
1000
,
blank
=
True
,
null
=
True
)
log_file
=
models
.
CharField
(
max_length
=
1000
,
blank
=
True
,
null
=
True
)
was_failed
=
models
.
BooleanField
(
default
=
False
,
verbose_name
=
_
(
'Did connect failed'
))
is_failed
=
models
.
BooleanField
(
is_finished
=
models
.
BooleanField
(
default
=
False
,
verbose_name
=
_
(
'Is finished'
))
default
=
False
,
verbose_name
=
_
(
'Did connect failed'
))
date_start
=
models
.
DateTimeField
(
auto_created
=
True
,
verbose_name
=
_
(
'Date start'
))
is_finished
=
models
.
BooleanField
(
date_finished
=
models
.
DateTimeField
(
null
=
True
,
verbose_name
=
_
(
'Date finished'
))
default
=
False
,
verbose_name
=
_
(
'Is finished'
))
date_start
=
models
.
DateTimeField
(
auto_created
=
True
,
verbose_name
=
_
(
'Date start'
))
date_finished
=
models
.
DateTimeField
(
null
=
True
,
verbose_name
=
_
(
'Date finished'
))
def
__unicode__
(
self
):
def
__unicode__
(
self
):
return
'
%
s-
%
s-
%
s-
%
s'
%
(
self
.
username
,
self
.
hostname
,
self
.
system_user
,
self
.
id
)
return
'
%
s-
%
s-
%
s'
%
(
self
.
user
,
self
.
asset
,
self
.
system_user
)
@property
def
commands_dict
(
self
):
commands
=
self
.
command_log
.
all
()
return
[{
"command_no"
:
command
.
command_no
,
"command"
:
command
.
command
,
"output"
:
command
.
output_decode
,
"datetime"
:
command
.
datetime
,
}
for
command
in
commands
]
class
Meta
:
class
Meta
:
ordering
=
[
'-date_start'
,
'user
name
'
]
ordering
=
[
'-date_start'
,
'user'
]
class
CommandLog
(
models
.
Model
):
class
CommandLog
(
models
.
Model
):
proxy_log
=
models
.
ForeignKey
(
ProxyLog
,
on_delete
=
models
.
CASCADE
,
proxy_log_id
=
models
.
IntegerField
()
related_name
=
'commands'
)
user
=
models
.
CharField
(
max_length
=
48
,
db_index
=
True
)
asset
=
models
.
CharField
(
max_length
=
128
,
db_index
=
True
)
system_user
=
models
.
CharField
(
max_length
=
48
,
db_index
=
True
)
command_no
=
models
.
IntegerField
()
command_no
=
models
.
IntegerField
()
command
=
models
.
CharField
(
max_length
=
1000
,
blank
=
True
)
command
=
models
.
CharField
(
max_length
=
1000
,
blank
=
True
,
db_index
=
True
)
output
=
models
.
TextField
(
blank
=
True
)
output
=
models
.
TextField
(
blank
=
True
)
datetime
=
models
.
DateTimeField
(
null
=
True
)
timestamp
=
models
.
FloatField
(
null
=
True
,
db_index
=
True
)
def
__unicode__
(
self
):
def
__unicode__
(
self
):
return
'
%
s:
%
s'
%
(
self
.
id
,
self
.
command
)
return
'
%
s:
%
s'
%
(
self
.
id
,
self
.
command
)
@property
def
output_decode
(
self
):
try
:
return
base64
.
b64decode
(
self
.
output
)
.
decode
(
'utf-8'
)
\
.
replace
(
'
\n
'
,
'<br />'
)
except
UnicodeDecodeError
:
return
'UnicodeDecodeError'
class
Meta
:
class
Meta
:
db_table
=
'command_log'
ordering
=
[
'command_no'
,
'command'
]
ordering
=
[
'command_no'
,
'command'
]
class
RecordLog
(
models
.
Model
):
proxy_log_id
=
models
.
IntegerField
()
output
=
models
.
TextField
(
verbose_name
=
_
(
'Output'
))
timestamp
=
models
.
FloatField
(
null
=
True
)
def
__unicode__
(
self
):
return
'Record:
%
s'
%
self
.
proxy_log_id
apps/audits/serializers.py
View file @
a79c3dd1
...
@@ -13,10 +13,7 @@ class ProxyLogSerializer(serializers.ModelSerializer):
...
@@ -13,10 +13,7 @@ class ProxyLogSerializer(serializers.ModelSerializer):
class
Meta
:
class
Meta
:
model
=
models
.
ProxyLog
model
=
models
.
ProxyLog
fields
=
[
'id'
,
'name'
,
'username'
,
'hostname'
,
'ip'
,
'system_user'
,
fields
=
'__all__'
'login_type'
,
'terminal'
,
'log_file'
,
'was_failed'
,
'is_finished'
,
'date_start'
,
'date_finished'
,
'time'
,
'command_length'
,
"commands_dict"
]
@staticmethod
@staticmethod
def
get_time
(
obj
):
def
get_time
(
obj
):
...
@@ -27,10 +24,5 @@ class ProxyLogSerializer(serializers.ModelSerializer):
...
@@ -27,10 +24,5 @@ class ProxyLogSerializer(serializers.ModelSerializer):
@staticmethod
@staticmethod
def
get_command_length
(
obj
):
def
get_command_length
(
obj
):
return
len
(
obj
.
commands
.
all
())
return
2
class
CommandLogSerializer
(
serializers
.
ModelSerializer
):
class
Meta
:
model
=
models
.
CommandLog
fields
=
'__all__'
apps/audits/templates/audits/command_log_list.html
View file @
a79c3dd1
...
@@ -23,32 +23,31 @@
...
@@ -23,32 +23,31 @@
</div>
</div>
</div>
</div>
<div
class=
"input-group"
>
<div
class=
"input-group"
>
<select
class=
"select2 form-control"
name=
"user
name
"
>
<select
class=
"select2 form-control"
name=
"user"
>
<option
value=
""
>
{% trans 'User' %}
</option>
<option
value=
""
>
{% trans 'User' %}
</option>
{% for u
ser
in user_list %}
{% for u in user_list %}
<option
value=
"{{ u
ser.username }}"
{%
if
user
.
username =
=
username
%}
selected
{%
endif
%}
>
{{ user
.username }}
</option>
<option
value=
"{{ u
.username }}"
{%
if
user =
=
u
.
username
%}
selected
{%
endif
%}
>
{{ u
.username }}
</option>
{% endfor %}
{% endfor %}
</select>
</select>
</div>
</div>
<div
class=
"input-group"
>
<div
class=
"input-group"
>
<select
class=
"select2 form-control"
name=
"
ip
"
>
<select
class=
"select2 form-control"
name=
"
asset
"
>
<option
value=
""
>
{% trans 'Asset' %}
</option>
<option
value=
""
>
{% trans 'Asset' %}
</option>
{% for a
sset
in asset_list %}
{% for a in asset_list %}
<option
value=
"{{ a
sset.ip }}"
{%
if
asset
.
ip =
=
ip
%}
selected
{%
endif
%}
>
{{ asset
.ip }}
</option>
<option
value=
"{{ a
.ip }}"
{%
if
asset =
=
a
.
ip
%}
selected
{%
endif
%}
>
{{ a
.ip }}
</option>
{% endfor %}
{% endfor %}
</select>
</select>
</div>
</div>
<div
class=
"input-group"
>
<div
class=
"input-group"
>
<select
class=
"select2 form-control"
name=
"system_user"
>
<select
class=
"select2 form-control"
name=
"system_user"
>
{#
<option
value=
""
>
{{ system_user }}
</option>
#}
<option
value=
""
>
{% trans 'System user' %}
</option>
<option
value=
""
>
{% trans 'System user' %}
</option>
{% for s
ystem_user
in system_user_list %}
{% for s in system_user_list %}
<option
value=
"{{ s
ystem_user.username }}"
{%
if
system_user
.
username =
=
system_user
%}
selected
{%
endif
%}
>
{{ system_user
.username }}
</option>
<option
value=
"{{ s
.username }}"
{%
if
s
.
username =
=
system_user
%}
selected
{%
endif
%}
>
{{ s
.username }}
</option>
{% endfor %}
{% endfor %}
</select>
</select>
</div>
</div>
<div
class=
"input-group"
>
<div
class=
"input-group"
>
<input
type=
"text"
class=
"form-control input-sm"
name=
"
keyword"
placeholder=
"Search"
value=
"{{ keywor
d }}"
>
<input
type=
"text"
class=
"form-control input-sm"
name=
"
command"
placeholder=
"Command"
value=
"{{ comman
d }}"
>
</div>
</div>
<div
class=
"input-group"
>
<div
class=
"input-group"
>
<div
class=
"input-group-btn"
>
<div
class=
"input-group-btn"
>
...
@@ -78,12 +77,12 @@
...
@@ -78,12 +77,12 @@
<tr>
<tr>
<td>
{{ command.id }}
</td>
<td>
{{ command.id }}
</td>
<td>
{{ command.command }}
</td>
<td>
{{ command.command }}
</td>
<td>
{{ command.
proxy_log.username
}}
</td>
<td>
{{ command.
user
}}
</td>
<td>
{{ command.
proxy_log.ip
}}
</td>
<td>
{{ command.
asset
}}
</td>
<td>
{{ command.
proxy_log.
system_user }}
</td>
<td>
{{ command.system_user }}
</td>
<td><a
href=
"{% url 'audits:proxy-log-detail' pk=command.proxy_log
.id %}"
>
{{ command.proxy_log.
id}}
</a></td>
<td><a
href=
"{% url 'audits:proxy-log-detail' pk=command.proxy_log
_id %}"
>
{{ command.proxy_log_
id}}
</a></td>
<td>
{{ command.
datetim
e }}
</td>
<td>
{{ command.
timestamp|ts_to_dat
e }}
</td>
<td>
{{ command.output_decode|safe }}
</td>
<td>
<pre
style=
"border: none; background: none"
>
{{ command.output|to_html|safe }}
</pre>
</td>
</tr>
</tr>
{% endfor %}
{% endfor %}
</tbody>
</tbody>
...
...
apps/audits/templates/audits/proxy_log_detail.html
View file @
a79c3dd1
...
@@ -19,7 +19,7 @@
...
@@ -19,7 +19,7 @@
</ul>
</ul>
</div>
</div>
<div
class=
"tab-content"
>
<div
class=
"tab-content"
>
<div
class=
"col-sm-
7
"
style=
"padding-left: 0;"
>
<div
class=
"col-sm-
11
"
style=
"padding-left: 0;"
>
<div
class=
"ibox float-e-margins"
>
<div
class=
"ibox float-e-margins"
>
<div
class=
"ibox-title"
>
<div
class=
"ibox-title"
>
<span
style=
"float: left"
>
{% trans 'Command log list' %}
<b>
{{ user_object.name }}
</b></span>
<span
style=
"float: left"
>
{% trans 'Command log list' %}
<b>
{{ user_object.name }}
</b></span>
...
@@ -52,8 +52,8 @@
...
@@ -52,8 +52,8 @@
<tr>
<tr>
<td>
{{ command.command_no }}
</td>
<td>
{{ command.command_no }}
</td>
<td>
{{ command.command }}
</td>
<td>
{{ command.command }}
</td>
<td>
{{ command.output_decode|safe }}
</td>
<td>
<pre
style=
"border: none;background: none"
>
{{ command.output|to_html|safe}}
</pre>
</td>
<td>
{{ command.
datetime
}}
</td>
<td>
{{ command.
timestamp|ts_to_date
}}
</td>
</tr>
</tr>
{% endfor %}
{% endfor %}
</tbody>
</tbody>
...
...
apps/audits/templates/audits/proxy_log_list.html
View file @
a79c3dd1
...
@@ -47,7 +47,7 @@
...
@@ -47,7 +47,7 @@
</select>
</select>
</div>
</div>
<div
class=
"input-group"
>
<div
class=
"input-group"
>
<input
type=
"text"
class=
"form-control input-sm"
name=
"keyword"
placeholder=
"
Comman
d"
value=
"{{ keyword }}"
>
<input
type=
"text"
class=
"form-control input-sm"
name=
"keyword"
placeholder=
"
Keywor
d"
value=
"{{ keyword }}"
>
</div>
</div>
<div
class=
"input-group"
>
<div
class=
"input-group"
>
<div
class=
"input-group-btn"
>
<div
class=
"input-group-btn"
>
...
@@ -61,44 +61,53 @@
...
@@ -61,44 +61,53 @@
{% block table_head %}
{% block table_head %}
<th
class=
"text-center"
>
{% trans 'ID' %}
</th>
<th
class=
"text-center"
>
{% trans 'ID' %}
</th>
<th
class=
"text-center"
>
{% trans 'User
name
' %}
</th>
<th
class=
"text-center"
>
{% trans 'User' %}
</th>
<th
class=
"text-center"
>
{% trans '
IP
' %}
</th>
<th
class=
"text-center"
>
{% trans '
Asset
' %}
</th>
<th
class=
"text-center"
>
{% trans 'System user' %}
</th>
<th
class=
"text-center"
>
{% trans 'System user' %}
</th>
<th
class=
"text-center"
>
{% trans 'Command' %}
</th>
<th
class=
"text-center"
>
{% trans 'Command' %}
</th>
<th
class=
"text-center"
>
{% trans 'Success' %}
</th>
<th
class=
"text-center"
>
{% trans 'Success' %}
</th>
<th
class=
"text-center"
>
{% trans 'Finished' %}
</th>
<th
class=
"text-center"
>
{% trans 'Finished' %}
</th>
<th
class=
"text-center"
>
{% trans 'R/M' %}
</th>
<th
class=
"text-center"
>
{% trans 'Date start' %}
</th>
<th
class=
"text-center"
>
{% trans 'Date start' %}
</th>
<th
class=
"text-center"
>
{% trans 'Time' %}
</th>
<th
class=
"text-center"
>
{% trans 'Time' %}
</th>
{% endblock %}
{% endblock %}
{% block table_body %}
{% block table_body %}
{% for proxy_log in proxy_log_list %}
{% for proxy_log in proxy_log_list %}
<tr
class=
"gradeX"
>
<tr
class=
"gradeX"
>
<td
class=
"text-center"
>
<td
class=
"text-center"
>
<a
href=
"{% url 'audits:proxy-log-detail' pk=proxy_log.id %}"
>
{{ proxy_log.id }}
</a>
<a
href=
"{% url 'audits:proxy-log-detail' pk=proxy_log.id %}"
>
{{ proxy_log.id }}
</a>
</td>
</td>
<td
class=
"text-center"
>
{{ proxy_log.username }}
</td>
<td
class=
"text-center"
>
{{ proxy_log.user }}
</td>
<td
class=
"text-center"
>
{{ proxy_log.ip }}
</td>
<td
class=
"text-center"
>
{{ proxy_log.asset }}
</td>
<td
class=
"text-center"
>
{{ proxy_log.system_user }}
</td>
<td
class=
"text-center"
>
{{ proxy_log.system_user }}
</td>
<td
class=
"text-center"
>
{{ proxy_log.commands.all|length}}
</td>
<td
class=
"text-center"
>
{{ proxy_log.commands.all|length}}
</td>
<td
class=
"text-center"
>
<td
class=
"text-center"
>
{% if proxy_log.was_failed %}
{% if proxy_log.is_failed %}
<i
class=
"fa fa-times text-danger"
></i>
<i
class=
"fa fa-times text-danger"
></i>
{% else %}
{% else %}
<i
class=
"fa fa-check text-navy"
></i>
<i
class=
"fa fa-check text-navy"
></i>
{% endif %}
{% endif %}
</td>
</td>
<td
class=
"text-center"
>
{% if proxy_log.is_finished %}
{% if proxy_log.is_finished %}
<td
class=
"text-center"
>
<i
class=
"fa fa-check text-navy"
></i>
<i
class=
"fa fa-check text-navy"
></i>
{% else %}
</td>
<i
class=
"fa fa-times text-danger"
></i>
<td
class=
"text-center"
>
{% endif %}
<a><span
class=
"text-navy"
><i
class=
"fa fa-play-circle"
></i></span></a>
</td>
</td>
<td
class=
"text-center"
>
{{ proxy_log.date_start }}
</td>
{% else %}
<td
class=
"text-center"
>
{{ proxy_log.date_finished|timeuntil:proxy_log.date_start }}
</td>
<td
class=
"text-center"
>
</tr>
<i
class=
"fa fa-times text-danger"
></i>
{% endfor %}
</td>
<td
class=
"text-center"
>
<a><span
class=
"text-danger"
><i
class=
"fa fa-eye"
></i></span></a>
</td>
{% endif %}
<td
class=
"text-center"
>
{{ proxy_log.date_start }}
</td>
<td
class=
"text-center"
>
{{ proxy_log.date_finished|timeuntil:proxy_log.date_start }}
</td>
</tr>
{% endfor %}
{% endblock %}
{% endblock %}
{% block custom_foot_js %}
{% block custom_foot_js %}
...
...
apps/audits/urls/api_urls.py
View file @
a79c3dd1
...
@@ -10,7 +10,8 @@ router.register(r'v1/proxy-log', api.ProxyLogViewSet, 'proxy-log')
...
@@ -10,7 +10,8 @@ router.register(r'v1/proxy-log', api.ProxyLogViewSet, 'proxy-log')
router
.
register
(
r'v1/command-log'
,
api
.
CommandLogViewSet
,
'command-log'
)
router
.
register
(
r'v1/command-log'
,
api
.
CommandLogViewSet
,
'command-log'
)
urlpatterns
=
[
urlpatterns
=
[
url
(
r'^v1/proxy-log/receive/$'
,
api
.
ProxyLogReceiveView
.
as_view
(),
name
=
'proxy-log-receive'
),
url
(
r'^v1/proxy-log/receive/$'
,
api
.
ProxyLogReceiveView
.
as_view
(),
name
=
'proxy-log-receive'
),
]
]
urlpatterns
+=
router
.
urls
urlpatterns
+=
router
.
urls
apps/audits/views.py
View file @
a79c3dd1
This diff is collapsed.
Click to expand it.
apps/common/templatetags/common_tags.py
View file @
a79c3dd1
...
@@ -3,7 +3,8 @@
...
@@ -3,7 +3,8 @@
from
django
import
template
from
django
import
template
from
django.utils
import
timezone
from
django.utils
import
timezone
from
django.conf
import
settings
from
django.conf
import
settings
from
django.utils.html
import
escape
from
audits.backends
import
command_store
register
=
template
.
Library
()
register
=
template
.
Library
()
...
@@ -41,10 +42,30 @@ def join_attr(seq, attr=None, sep=None):
...
@@ -41,10 +42,30 @@ def join_attr(seq, attr=None, sep=None):
sep
=
', '
sep
=
', '
if
attr
is
not
None
:
if
attr
is
not
None
:
seq
=
[
getattr
(
obj
,
attr
)
for
obj
in
seq
]
seq
=
[
getattr
(
obj
,
attr
)
for
obj
in
seq
]
print
(
seq
)
return
sep
.
join
(
seq
)
return
sep
.
join
(
seq
)
@register.filter
@register.filter
def
int_to_str
(
value
):
def
int_to_str
(
value
):
return
str
(
value
)
return
str
(
value
)
\ No newline at end of file
@register.filter
def
ts_to_date
(
ts
):
try
:
ts
=
float
(
ts
)
except
TypeError
:
ts
=
0
dt
=
timezone
.
datetime
.
fromtimestamp
(
ts
)
.
\
replace
(
tzinfo
=
timezone
.
get_current_timezone
())
return
dt
.
strftime
(
'
%
Y-
%
m-
%
d
%
H:
%
M:
%
S'
)
@register.filter
def
to_html
(
s
):
return
escape
(
s
)
.
replace
(
'
\n
'
,
'<br />'
)
@register.filter
def
proxy_log_commands
(
log_id
):
return
command_store
.
filter
(
proxy_log_id
=
log_id
)
\ No newline at end of file
apps/common/utils.py
View file @
a79c3dd1
...
@@ -33,8 +33,10 @@ from .compat import to_bytes, to_string
...
@@ -33,8 +33,10 @@ from .compat import to_bytes, to_string
SECRET_KEY
=
settings
.
SECRET_KEY
SECRET_KEY
=
settings
.
SECRET_KEY
def
reverse
(
view_name
,
urlconf
=
None
,
args
=
None
,
kwargs
=
None
,
current_app
=
None
,
external
=
False
):
def
reverse
(
view_name
,
urlconf
=
None
,
args
=
None
,
kwargs
=
None
,
url
=
dj_reverse
(
view_name
,
urlconf
=
urlconf
,
args
=
args
,
kwargs
=
kwargs
,
current_app
=
current_app
)
current_app
=
None
,
external
=
False
):
url
=
dj_reverse
(
view_name
,
urlconf
=
urlconf
,
args
=
args
,
kwargs
=
kwargs
,
current_app
=
current_app
)
if
external
:
if
external
:
url
=
settings
.
SITE_URL
.
strip
(
'/'
)
+
url
url
=
settings
.
SITE_URL
.
strip
(
'/'
)
+
url
...
@@ -44,8 +46,8 @@ def reverse(view_name, urlconf=None, args=None, kwargs=None, current_app=None, e
...
@@ -44,8 +46,8 @@ def reverse(view_name, urlconf=None, args=None, kwargs=None, current_app=None, e
def
get_object_or_none
(
model
,
**
kwargs
):
def
get_object_or_none
(
model
,
**
kwargs
):
try
:
try
:
obj
=
model
.
objects
.
get
(
**
kwargs
)
obj
=
model
.
objects
.
get
(
**
kwargs
)
except
model
.
DoesNotExist
:
except
(
model
.
FieldError
,
model
.
DoesNotExist
)
:
obj
=
None
return
None
return
obj
return
obj
...
...
apps/jumpserver/middleware.py
0 → 100644
View file @
a79c3dd1
# ~*~ coding: utf-8 ~*~
import
pytz
from
django.utils
import
timezone
from
django.utils.deprecation
import
MiddlewareMixin
class
TimezoneMiddleware
(
MiddlewareMixin
):
def
process_request
(
self
,
request
):
tzname
=
request
.
META
.
get
(
'TZ'
)
if
tzname
:
timezone
.
activate
(
pytz
.
timezone
(
tzname
))
else
:
timezone
.
deactivate
()
apps/jumpserver/settings.py
View file @
a79c3dd1
...
@@ -79,6 +79,7 @@ MIDDLEWARE = [
...
@@ -79,6 +79,7 @@ MIDDLEWARE = [
'django.contrib.auth.middleware.AuthenticationMiddleware'
,
'django.contrib.auth.middleware.AuthenticationMiddleware'
,
'django.contrib.messages.middleware.MessageMiddleware'
,
'django.contrib.messages.middleware.MessageMiddleware'
,
'django.middleware.clickjacking.XFrameOptionsMiddleware'
,
'django.middleware.clickjacking.XFrameOptionsMiddleware'
,
'jumpserver.middleware.TimezoneMiddleware'
,
]
]
ROOT_URLCONF
=
'jumpserver.urls'
ROOT_URLCONF
=
'jumpserver.urls'
...
@@ -323,3 +324,5 @@ CACHES = {
...
@@ -323,3 +324,5 @@ CACHES = {
CAPTCHA_IMAGE_SIZE
=
(
75
,
33
)
CAPTCHA_IMAGE_SIZE
=
(
75
,
33
)
CAPTCHA_FOREGROUND_COLOR
=
'#001100'
CAPTCHA_FOREGROUND_COLOR
=
'#001100'
COMMAND_STORE_BACKEND
=
'audits.backends.command.db'
apps/perms/api.py
View file @
a79c3dd1
...
@@ -14,6 +14,7 @@ from .models import AssetPermission
...
@@ -14,6 +14,7 @@ from .models import AssetPermission
from
.hands
import
AssetGrantedSerializer
,
User
,
UserGroup
,
AssetGroup
,
Asset
,
\
from
.hands
import
AssetGrantedSerializer
,
User
,
UserGroup
,
AssetGroup
,
Asset
,
\
AssetGroup
,
AssetGroupSerializer
,
SystemUser
AssetGroup
,
AssetGroupSerializer
,
SystemUser
from
.
import
serializers
from
.
import
serializers
from
.utils
import
associate_system_users_and_assets
class
AssetPermissionViewSet
(
viewsets
.
ModelViewSet
):
class
AssetPermissionViewSet
(
viewsets
.
ModelViewSet
):
...
@@ -35,11 +36,32 @@ class AssetPermissionViewSet(viewsets.ModelViewSet):
...
@@ -35,11 +36,32 @@ class AssetPermissionViewSet(viewsets.ModelViewSet):
queryset
=
get_user_group_asset_permissions
(
user_group
)
queryset
=
get_user_group_asset_permissions
(
user_group
)
return
queryset
return
queryset
# Todo: 忘记为何要重写get_serializer_class了
def
get_serializer_class
(
self
):
def
get_serializer_class
(
self
):
if
getattr
(
self
,
'user_id'
,
''
):
if
getattr
(
self
,
'user_id'
,
''
):
return
serializers
.
UserAssetPermissionSerializer
return
serializers
.
UserAssetPermissionSerializer
return
serializers
.
AssetPermissionSerializer
return
serializers
.
AssetPermissionSerializer
def
associate_system_users_and_assets
(
self
,
serializer
):
assets
=
serializer
.
validated_data
.
get
(
'assets'
,
[])
asset_groups
=
serializer
.
validated_data
.
get
(
'asset_groups'
,
[])
system_users
=
serializer
.
validated_data
.
get
(
'system_users'
,
[])
if
serializer
.
partial
:
instance
=
self
.
get_object
()
assets
.
extend
(
list
(
instance
.
assets
.
all
()))
asset_groups
.
extend
(
list
(
instance
.
asset_groups
.
all
()))
system_users
.
extend
(
list
(
instance
.
system_users
.
all
()))
print
(
'Run'
)
associate_system_users_and_assets
(
system_users
,
assets
,
asset_groups
)
def
perform_create
(
self
,
serializer
):
self
.
associate_system_users_and_assets
(
serializer
)
return
super
(
AssetPermissionViewSet
,
self
)
.
perform_create
(
serializer
)
def
perform_update
(
self
,
serializer
):
self
.
associate_system_users_and_assets
(
serializer
)
return
super
(
AssetPermissionViewSet
,
self
)
.
perform_update
(
serializer
)
class
RevokeUserAssetPermission
(
APIView
):
class
RevokeUserAssetPermission
(
APIView
):
permission_classes
=
(
IsSuperUser
,)
permission_classes
=
(
IsSuperUser
,)
...
@@ -58,6 +80,27 @@ class RevokeUserAssetPermission(APIView):
...
@@ -58,6 +80,27 @@ class RevokeUserAssetPermission(APIView):
return
Response
({
'msg'
:
'failed'
},
status
=
404
)
return
Response
({
'msg'
:
'failed'
},
status
=
404
)
class
RemoveSystemUserAssetPermission
(
APIView
):
"""将系统用户从授权中移除, Detail页面会调用"""
permission_classes
=
(
IsSuperUser
,)
def
put
(
self
,
request
,
*
args
,
**
kwargs
):
response
=
[]
asset_permission_id
=
kwargs
.
pop
(
'pk'
)
system_users_id
=
request
.
data
.
get
(
'system_users'
)
print
(
system_users_id
)
asset_permission
=
get_object_or_404
(
AssetPermission
,
id
=
asset_permission_id
)
if
not
isinstance
(
system_users_id
,
list
):
system_users_id
=
[
system_users_id
]
for
system_user_id
in
system_users_id
:
system_user
=
get_object_or_none
(
SystemUser
,
id
=
system_user_id
)
if
system_user
:
asset_permission
.
system_users
.
remove
(
system_user
)
response
.
append
(
system_user
.
to_json
())
return
Response
(
response
,
status
=
200
)
class
RevokeUserGroupAssetPermission
(
APIView
):
class
RevokeUserGroupAssetPermission
(
APIView
):
permission_classes
=
(
IsSuperUser
,)
permission_classes
=
(
IsSuperUser
,)
...
...
apps/perms/forms.py
View file @
a79c3dd1
...
@@ -6,19 +6,9 @@ from django.utils.translation import ugettext_lazy as _
...
@@ -6,19 +6,9 @@ from django.utils.translation import ugettext_lazy as _
# from .hands import User, UserGroup, Asset, AssetGroup, SystemUser
# from .hands import User, UserGroup, Asset, AssetGroup, SystemUser
from
.models
import
AssetPermission
from
.models
import
AssetPermission
from
.hands
import
associate_system_users_with_assets
class
AssetPermissionForm
(
forms
.
ModelForm
):
class
AssetPermissionForm
(
forms
.
ModelForm
):
def
save
(
self
,
commit
=
True
):
instance
=
super
(
AssetPermissionForm
,
self
)
.
save
(
commit
=
commit
)
assets
=
instance
.
assets
.
all
()
asset_groups
=
instance
.
asset_groups
.
all
()
system_users
=
instance
.
system_users
.
all
()
associate_system_users_with_assets
(
system_users
,
assets
,
asset_groups
)
return
instance
class
Meta
:
class
Meta
:
model
=
AssetPermission
model
=
AssetPermission
fields
=
[
fields
=
[
...
@@ -48,4 +38,3 @@ class AssetPermissionForm(forms.ModelForm):
...
@@ -48,4 +38,3 @@ class AssetPermissionForm(forms.ModelForm):
'asset_groups'
:
'* Asset or Asset group at least one required'
,
'asset_groups'
:
'* Asset or Asset group at least one required'
,
'system_users'
:
'* required'
,
'system_users'
:
'* required'
,
}
}
apps/perms/hands.py
View file @
a79c3dd1
...
@@ -7,9 +7,9 @@ from assets.models import Asset, AssetGroup, SystemUser
...
@@ -7,9 +7,9 @@ from assets.models import Asset, AssetGroup, SystemUser
from
assets.serializers
import
AssetGrantedSerializer
,
AssetGroupSerializer
from
assets.serializers
import
AssetGrantedSerializer
,
AssetGroupSerializer
def
associate_system_users_with_assets
(
system_users
,
assets
,
asset_groups
):
def
push_system_user
(
assets
,
system_user
):
print
(
'Push system user
%
s'
%
system_user
.
name
)
for
asset
in
assets
:
for
asset
in
assets
:
asset
.
system_users
.
add
(
*
tuple
(
system_users
))
print
(
'
\t
Asset:
%
s'
%
asset
.
ip
)
for
asset_group
in
asset_groups
:
asset_group
.
system_users
.
add
(
*
tuple
(
system_users
))
apps/perms/models.py
View file @
a79c3dd1
...
@@ -4,6 +4,7 @@ import functools
...
@@ -4,6 +4,7 @@ import functools
from
django.db
import
models
from
django.db
import
models
from
django.utils.translation
import
ugettext_lazy
as
_
from
django.utils.translation
import
ugettext_lazy
as
_
from
django.utils
import
timezone
from
django.utils
import
timezone
from
django.db.models.signals
import
m2m_changed
from
users.models
import
User
,
UserGroup
from
users.models
import
User
,
UserGroup
from
assets.models
import
Asset
,
AssetGroup
,
SystemUser
from
assets.models
import
Asset
,
AssetGroup
,
SystemUser
...
@@ -16,18 +17,26 @@ class AssetPermission(models.Model):
...
@@ -16,18 +17,26 @@ class AssetPermission(models.Model):
# ('U', 'user'),
# ('U', 'user'),
# ('G', 'user group'),
# ('G', 'user group'),
# )
# )
name
=
models
.
CharField
(
max_length
=
128
,
unique
=
True
,
verbose_name
=
_
(
'Name'
))
name
=
models
.
CharField
(
users
=
models
.
ManyToManyField
(
User
,
related_name
=
'asset_permissions'
,
blank
=
True
)
max_length
=
128
,
unique
=
True
,
verbose_name
=
_
(
'Name'
))
user_groups
=
models
.
ManyToManyField
(
UserGroup
,
related_name
=
'asset_permissions'
,
blank
=
True
)
users
=
models
.
ManyToManyField
(
assets
=
models
.
ManyToManyField
(
Asset
,
related_name
=
'granted_by_permissions'
,
blank
=
True
)
User
,
related_name
=
'asset_permissions'
,
blank
=
True
)
asset_groups
=
models
.
ManyToManyField
(
AssetGroup
,
related_name
=
'granted_by_permissions'
,
blank
=
True
)
user_groups
=
models
.
ManyToManyField
(
system_users
=
models
.
ManyToManyField
(
SystemUser
,
related_name
=
'granted_by_permissions'
)
UserGroup
,
related_name
=
'asset_permissions'
,
blank
=
True
)
# private_for = models.CharField(choices=PRIVATE_FOR_CHOICE, max_length=1, default='N', blank=True,
assets
=
models
.
ManyToManyField
(
# verbose_name=_('Private for'))
Asset
,
related_name
=
'granted_by_permissions'
,
blank
=
True
)
is_active
=
models
.
BooleanField
(
default
=
True
,
verbose_name
=
_
(
'Active'
))
asset_groups
=
models
.
ManyToManyField
(
date_expired
=
models
.
DateTimeField
(
default
=
date_expired_default
,
verbose_name
=
_
(
'Date expired'
))
AssetGroup
,
related_name
=
'granted_by_permissions'
,
blank
=
True
)
created_by
=
models
.
CharField
(
max_length
=
128
,
blank
=
True
,
verbose_name
=
_
(
'Created by'
))
system_users
=
models
.
ManyToManyField
(
date_created
=
models
.
DateTimeField
(
auto_now_add
=
True
,
verbose_name
=
_
(
'Date created'
))
SystemUser
,
related_name
=
'granted_by_permissions'
)
is_active
=
models
.
BooleanField
(
default
=
True
,
verbose_name
=
_
(
'Active'
))
date_expired
=
models
.
DateTimeField
(
default
=
date_expired_default
,
verbose_name
=
_
(
'Date expired'
))
created_by
=
models
.
CharField
(
max_length
=
128
,
blank
=
True
,
verbose_name
=
_
(
'Created by'
))
date_created
=
models
.
DateTimeField
(
auto_now_add
=
True
,
verbose_name
=
_
(
'Date created'
))
comment
=
models
.
TextField
(
verbose_name
=
_
(
'Comment'
),
blank
=
True
)
comment
=
models
.
TextField
(
verbose_name
=
_
(
'Comment'
),
blank
=
True
)
def
__unicode__
(
self
):
def
__unicode__
(
self
):
...
@@ -68,3 +77,15 @@ class AssetPermission(models.Model):
...
@@ -68,3 +77,15 @@ class AssetPermission(models.Model):
class
Meta
:
class
Meta
:
db_table
=
'asset_permission'
db_table
=
'asset_permission'
# def change_permission(sender, **kwargs):
# print('Sender: %s' % sender)
# for k, v in kwargs.items():
# print('%s: %s' % (k, v))
# print()
#
# m2m_changed.connect(change_permission, sender=AssetPermission.assets.through)
apps/perms/templates/perms/asset_permission_detail.html
View file @
a79c3dd1
...
@@ -169,16 +169,16 @@
...
@@ -169,16 +169,16 @@
</tr>
</tr>
<tr>
<tr>
<td
colspan=
"2"
class=
"no-borders"
>
<td
colspan=
"2"
class=
"no-borders"
>
<button
type=
"button"
class=
"btn btn-info btn-small"
id=
"btn_add_
user_group
"
>
{% trans 'Join' %}
</button>
<button
type=
"button"
class=
"btn btn-info btn-small"
id=
"btn_add_
system_user
"
>
{% trans 'Join' %}
</button>
</td>
</td>
</tr>
</tr>
</form>
</form>
{% for system_user in system_users %}
{% for system_user in system_users %}
<tr>
<tr>
<td
><b
class=
"bdg
_user_group"
data-g
id=
{{
system_user
.
id
}}
>
{{ system_user.name }}
</b></td>
<td
><b
class=
"bdg
-system-user"
data-u
id=
{{
system_user
.
id
}}
>
{{ system_user.name }}
</b></td>
<td>
<td>
<button
class=
"btn btn-danger btn-xs btn
_delete_user_group
"
type=
"button"
style=
"float: right;"
><i
class=
"fa fa-minus"
></i></button>
<button
class=
"btn btn-danger btn-xs btn
-del"
data-uid=
"{{ system_user.id }}
"
type=
"button"
style=
"float: right;"
><i
class=
"fa fa-minus"
></i></button>
</td>
</td>
</tr>
</tr>
{% endfor %}
{% endfor %}
...
@@ -196,8 +196,47 @@
...
@@ -196,8 +196,47 @@
{% endblock %}
{% endblock %}
{% block custom_foot_js %}
{% block custom_foot_js %}
<script>
<script>
jumpserver
.
system_users_selected
=
{};
function
addSystemUser
(
system_users
)
{
var
the_url
=
"{% url 'api-perms:asset-permission-detail' pk=asset_permission.id %}"
;
var
body
=
{
system_users
:
Object
.
assign
([],
system_users
)
};
var
success
=
function
(
data
)
{
window
.
location
.
reload
();
};
APIUpdateAttr
({
url
:
the_url
,
body
:
JSON
.
stringify
(
body
),
success
:
success
});
}
function
removeSystemUser
(
system_users
,
tr
)
{
var
the_url
=
"{% url 'api-perms:remove-system-user-asset-permission' pk=asset_permission.id %}"
;
var
body
=
{
system_users
:
system_users
};
var
success
=
function
(
data
)
{
tr
.
remove
()
};
APIUpdateAttr
({
url
:
the_url
,
body
:
JSON
.
stringify
(
body
),
method
:
'PUT'
,
success
:
success
})
}
$
(
document
).
ready
(
function
()
{
$
(
document
).
ready
(
function
()
{
$
(
'.select2'
).
select2
();
$
(
'.select2'
).
select2
()
.
on
(
'select2:select'
,
function
(
evt
)
{
var
data
=
evt
.
params
.
data
;
jumpserver
.
system_users_selected
[
data
.
id
]
=
data
.
text
;
})
.
on
(
'select2:unselect'
,
function
(
evt
)
{
var
data
=
evt
.
params
.
data
;
delete
jumpserver
.
system_users_selected
[
data
.
id
]
})
}).
on
(
'click'
,
'.btn-delete-perm'
,
function
()
{
}).
on
(
'click'
,
'.btn-delete-perm'
,
function
()
{
var
$this
=
$
(
this
);
var
$this
=
$
(
this
);
var
name
=
"{{ asset_permission.name }}"
;
var
name
=
"{{ asset_permission.name }}"
;
...
@@ -205,6 +244,28 @@
...
@@ -205,6 +244,28 @@
var
the_url
=
'{% url "api-perms:asset-permission-detail" pk=99991937 %}'
.
replace
(
'99991937'
,
uid
);
var
the_url
=
'{% url "api-perms:asset-permission-detail" pk=99991937 %}'
.
replace
(
'99991937'
,
uid
);
var
redirect_url
=
"{% url 'perms:asset-permission-list' %}"
;
var
redirect_url
=
"{% url 'perms:asset-permission-list' %}"
;
objectDelete
(
$this
,
name
,
the_url
,
redirect_url
);
objectDelete
(
$this
,
name
,
the_url
,
redirect_url
);
}).
on
(
'click'
,
'#btn_add_system_user'
,
function
()
{
if
(
Object
.
keys
(
jumpserver
.
system_users_selected
).
length
===
0
)
{
return
false
;
}
var
system_users
=
$
(
'.bdg-system-user'
).
map
(
function
()
{
return
$
(
this
).
data
(
'uid'
);
}).
get
();
$
.
map
(
jumpserver
.
system_users_selected
,
function
(
value
,
index
)
{
system_users
.
push
(
parseInt
(
index
));
$
(
'#opt_'
+
index
).
remove
();
});
addSystemUser
(
system_users
)
}).
on
(
'click'
,
'.btn-del'
,
function
()
{
var
$this
=
$
(
this
);
var
$uid
=
$this
.
data
(
'uid'
);
var
$tr
=
$this
.
closest
(
'tr'
);
var
$badge
=
$tr
.
find
(
'.bdg-system-user'
);
var
$system_user
=
$badge
.
html
()
||
$badge
.
text
();
$
(
'#groups_selected'
).
append
(
'<option value="'
+
$uid
+
'" id="opt_'
+
$uid
+
'">'
+
$system_user
+
'</option>'
);
removeSystemUser
(
$uid
,
$tr
)
})
})
</script>
</script>
{% endblock %}
{% endblock %}
\ No newline at end of file
apps/perms/templates/perms/asset_permission_user.html
View file @
a79c3dd1
...
@@ -108,7 +108,7 @@
...
@@ -108,7 +108,7 @@
<form>
<form>
<tr
class=
"no-borders-tr"
>
<tr
class=
"no-borders-tr"
>
<td
colspan=
"2"
>
<td
colspan=
"2"
>
<select
data-placeholder=
"{% trans 'Select user' %}"
class=
"select2"
style=
"width: 100%"
multiple=
""
tabindex=
"4"
>
<select
data-placeholder=
"{% trans 'Select user' %}"
class=
"select2
user
"
style=
"width: 100%"
multiple=
""
tabindex=
"4"
>
{% for user in users_remain %}
{% for user in users_remain %}
<option
value=
"{{ user.id }}"
>
{{ user.name }}: {{ user.username }}
</option>
<option
value=
"{{ user.id }}"
>
{{ user.name }}: {{ user.username }}
</option>
{% endfor %}
{% endfor %}
...
@@ -117,7 +117,7 @@
...
@@ -117,7 +117,7 @@
</tr>
</tr>
<tr
class=
"no-borders-tr"
>
<tr
class=
"no-borders-tr"
>
<td
colspan=
"2"
>
<td
colspan=
"2"
>
<button
type=
"button"
class=
"btn btn-primary btn-sm"
>
{% trans 'Add' %}
</button>
<button
type=
"button"
class=
"btn btn-primary btn-sm
btn-add-user
"
>
{% trans 'Add' %}
</button>
</td>
</td>
</tr>
</tr>
</form>
</form>
...
@@ -136,7 +136,7 @@
...
@@ -136,7 +136,7 @@
<form>
<form>
<tr>
<tr>
<td
colspan=
"2"
class=
"no-borders"
>
<td
colspan=
"2"
class=
"no-borders"
>
<select
data-placeholder=
"{% trans 'Select user groups' %}"
class=
"select2"
style=
"width: 100%"
multiple=
""
tabindex=
"4"
>
<select
data-placeholder=
"{% trans 'Select user groups' %}"
class=
"select2
user-group
"
style=
"width: 100%"
multiple=
""
tabindex=
"4"
>
{% for user_group in user_groups_remain %}
{% for user_group in user_groups_remain %}
<option
value=
"{{ user_group.id }}"
id=
"opt_{{ user_group.id }}"
>
{{ user_group.name }}
</option>
<option
value=
"{{ user_group.id }}"
id=
"opt_{{ user_group.id }}"
>
{{ user_group.name }}
</option>
{% endfor %}
{% endfor %}
...
@@ -145,7 +145,7 @@
...
@@ -145,7 +145,7 @@
</tr>
</tr>
<tr>
<tr>
<td
colspan=
"2"
class=
"no-borders"
>
<td
colspan=
"2"
class=
"no-borders"
>
<button
type=
"button"
class=
"btn btn-info btn-small"
id=
"btn_add_user_group"
>
{% trans '
Join
' %}
</button>
<button
type=
"button"
class=
"btn btn-info btn-small"
id=
"btn_add_user_group"
>
{% trans '
Add
' %}
</button>
</td>
</td>
</tr>
</tr>
</form>
</form>
...
@@ -172,25 +172,29 @@
...
@@ -172,25 +172,29 @@
{% endblock %}
{% endblock %}
{% block custom_foot_js %}
{% block custom_foot_js %}
<script>
<script>
{
#
function
switch_user_status
(
obj
)
{
#
}
jumpserver
.
users_selected
=
{};
{
#
var
status
=
$
(
obj
).
prop
(
'checked'
);
#
}
jumpserver
.
user_groups_selected
=
{};
{
##
}
{
#
$
.
ajax
({
#
}
{
#
url
:
"{% url 'users:user-active-api' pk=user.id %}"
,
#
}
{
#
type
:
"PUT"
,
#
}
{
#
data
:
{
#
}
{
#
'is_active'
:
status
#
}
{
#
},
#
}
{
#
success
:
function
(
data
,
status
)
{
#
}
{
#
console
.
log
(
data
)
#
}
{
#
},
#
}
{
#
error
:
function
()
{
#
}
{
#
console
.
log
(
'error'
)
#
}
{
#
}
#
}
{
#
})
#
}
{
#
}
#
}
$
(
document
).
ready
(
function
()
{
$
(
document
).
ready
(
function
()
{
$
(
'.select2'
).
select2
();
$
(
'.select2.user'
).
select2
()
});
.
on
(
'select2:select'
,
function
(
evt
)
{
var
data
=
evt
.
params
.
data
;
jumpserver
.
users_selected
[
data
.
id
]
=
data
.
text
;
})
.
on
(
'select2:unselect'
,
function
(
evt
)
{
var
data
=
evt
.
params
.
data
;
delete
jumpserver
.
users_selected
[
data
.
id
]
});
$
(
'.select2.user-group'
).
select2
()
.
on
(
'select2:select'
,
function
(
evt
)
{
var
data
=
evt
.
params
.
data
;
jumpserver
.
user_groups_selected
[
data
.
id
]
=
data
.
text
;
})
.
on
(
'select2:unselect'
,
function
(
evt
)
{
var
data
=
evt
.
params
.
data
;
delete
jumpserver
.
user_groups_selected
[
data
.
id
]
})
}).
on
(
'click'
,
'.btn-add-user'
,
function
()
{
console
.
log
(
jumpserver
.
users_selected
)
})
</script>
</script>
{% endblock %}
{% endblock %}
\ No newline at end of file
apps/perms/tests.py
View file @
a79c3dd1
from
django.test
import
TestCase
from
django.test
import
TestCase
# Create your tests here.
from
django.contrib.sessions.backends
import
file
,
db
,
cache
from
django.contrib.auth.views
import
login
\ No newline at end of file
apps/perms/urls/api_urls.py
View file @
a79c3dd1
...
@@ -50,7 +50,12 @@ urlpatterns = [
...
@@ -50,7 +50,12 @@ urlpatterns = [
# 验证用户是否有某个资产和系统用户的权限
# 验证用户是否有某个资产和系统用户的权限
url
(
r'v1/asset-permission/user/validate/$'
,
url
(
r'v1/asset-permission/user/validate/$'
,
api
.
ValidateUserAssetPermissionView
.
as_view
(),
api
.
ValidateUserAssetPermissionView
.
as_view
(),
name
=
'validate-user-asset-permission'
)
name
=
'validate-user-asset-permission'
),
# 删除asset permission中的某个系统用户
url
(
r'^v1/asset-permissions/(?P<pk>[0-9]+)/system-user/remove/$'
,
api
.
RemoveSystemUserAssetPermission
.
as_view
(),
name
=
'remove-system-user-asset-permission'
),
]
]
urlpatterns
+=
router
.
urls
urlpatterns
+=
router
.
urls
...
...
apps/perms/utils.py
View file @
a79c3dd1
# coding: utf-8
from
__future__
import
absolute_import
,
unicode_literals
from
__future__
import
absolute_import
,
unicode_literals
from
common.utils
import
setattr_bulk
from
common.utils
import
setattr_bulk
from
.hands
import
User
,
UserGroup
,
Asset
,
AssetGroup
,
SystemUser
from
.hands
import
User
,
UserGroup
,
Asset
,
AssetGroup
,
SystemUser
,
\
push_system_user
def
get_user_group_granted_asset_groups
(
user_group
):
def
get_user_group_granted_asset_groups
(
user_group
):
"""Return asset groups granted of the user group
"""Return asset groups granted of the user group
:param user_group: Instance of :class: ``UserGroup``
:param user_group: Instance of :class: ``UserGroup``
:return: {asset_group1: {system_user1, }, asset_group2: {system_user1, system_user2}}
:return: {asset_group1: {system_user1, },
asset_group2: {system_user1, system_user2}}
"""
"""
asset_groups
=
{}
asset_groups
=
{}
asset_permissions
=
user_group
.
asset_permissions
.
all
()
asset_permissions
=
user_group
.
asset_permissions
.
all
()
...
@@ -50,7 +54,8 @@ def get_user_granted_asset_groups_direct(user):
...
@@ -50,7 +54,8 @@ def get_user_granted_asset_groups_direct(user):
"""Return asset groups granted of the user direct nor inherit from user group
"""Return asset groups granted of the user direct nor inherit from user group
:param user: Instance of :class: ``User``
:param user: Instance of :class: ``User``
:return: {asset_group: {system_user1, }, asset_group2: {system_user1, system_user2]}
:return: {asset_group: {system_user1, },
asset_group2: {system_user1, system_user2]}
"""
"""
asset_groups
=
{}
asset_groups
=
{}
asset_permissions_direct
=
user
.
asset_permissions
.
all
()
asset_permissions_direct
=
user
.
asset_permissions
.
all
()
...
@@ -72,7 +77,8 @@ def get_user_granted_asset_groups_inherit_from_user_groups(user):
...
@@ -72,7 +77,8 @@ def get_user_granted_asset_groups_inherit_from_user_groups(user):
"""Return asset groups granted of the user and inherit from user group
"""Return asset groups granted of the user and inherit from user group
:param user: Instance of :class: ``User``
:param user: Instance of :class: ``User``
:return: {asset_group: {system_user1, }, asset_group2: {system_user1, system_user2]}
:return: {asset_group: {system_user1, },
asset_group2: {system_user1, system_user2]}
"""
"""
asset_groups
=
{}
asset_groups
=
{}
user_groups
=
user
.
groups
.
all
()
user_groups
=
user
.
groups
.
all
()
...
@@ -103,7 +109,8 @@ def get_user_granted_asset_groups(user):
...
@@ -103,7 +109,8 @@ def get_user_granted_asset_groups(user):
:return: {asset1: {system_user1, system_user2}, asset2: {...}}
:return: {asset1: {system_user1, system_user2}, asset2: {...}}
"""
"""
asset_groups_inherit_from_user_groups
=
get_user_granted_asset_groups_inherit_from_user_groups
(
user
)
asset_groups_inherit_from_user_groups
=
\
get_user_granted_asset_groups_inherit_from_user_groups
(
user
)
asset_groups_direct
=
get_user_granted_asset_groups_direct
(
user
)
asset_groups_direct
=
get_user_granted_asset_groups_direct
(
user
)
asset_groups
=
asset_groups_inherit_from_user_groups
asset_groups
=
asset_groups_inherit_from_user_groups
...
@@ -211,3 +218,27 @@ def get_user_groups_granted_in_asset_group(asset):
...
@@ -211,3 +218,27 @@ def get_user_groups_granted_in_asset_group(asset):
def
get_users_granted_in_asset_group
(
asset
):
def
get_users_granted_in_asset_group
(
asset
):
pass
pass
def
associate_system_users_and_assets
(
system_users
,
assets
,
asset_groups
):
"""关联系统用户和资产, 目的是保存它们的关系, 然后新加入的资产或系统
用户时,推送系统用户到资产
Todo: 这里需要最终Api定下来更改一下, 现在策略是以系统用户为核心推送, 一个系统用户
推送一次
"""
assets_all
=
set
(
assets
)
for
asset_group
in
asset_groups
:
assets_all
|=
set
(
asset_group
.
assets
.
all
())
for
system_user
in
system_users
:
assets_need_push
=
[]
if
system_user
.
auto_push
:
assets_need_push
.
extend
(
[
asset
for
asset
in
assets_all
if
asset
not
in
system_user
.
assets
.
all
()
]
)
system_user
.
assets
.
add
(
*
(
tuple
(
assets_all
)))
push_system_user
(
assets_need_push
,
system_user
)
apps/perms/views.py
View file @
a79c3dd1
...
@@ -6,16 +6,18 @@ import functools
...
@@ -6,16 +6,18 @@ import functools
from
django.utils.translation
import
ugettext
as
_
from
django.utils.translation
import
ugettext
as
_
from
django.conf
import
settings
from
django.conf
import
settings
from
django.db.models
import
Q
from
django.db.models
import
Q
from
django.views.generic
import
TemplateView
,
List
View
from
django.views.generic
import
ListView
,
CreateView
,
Update
View
from
django.views.generic.edit
import
CreateView
,
DeleteView
,
FormView
,
Update
View
from
django.views.generic.edit
import
DeleteView
,
Form
View
from
django.urls
import
reverse_lazy
from
django.urls
import
reverse_lazy
from
django.contrib.messages.views
import
SuccessMessageMixin
from
django.contrib.messages.views
import
SuccessMessageMixin
from
django.views.generic.detail
import
DetailView
,
SingleObjectMixin
from
django.views.generic.detail
import
DetailView
,
SingleObjectMixin
from
common.utils
import
search_object_attr
from
common.utils
import
search_object_attr
from
.hands
import
AdminUserRequiredMixin
,
User
,
UserGroup
,
SystemUser
,
Asset
,
AssetGroup
from
.hands
import
AdminUserRequiredMixin
,
User
,
UserGroup
,
SystemUser
,
\
Asset
,
AssetGroup
from
.models
import
AssetPermission
from
.models
import
AssetPermission
from
.forms
import
AssetPermissionForm
from
.forms
import
AssetPermissionForm
from
.utils
import
associate_system_users_and_assets
class
AssetPermissionListView
(
AdminUserRequiredMixin
,
ListView
):
class
AssetPermissionListView
(
AdminUserRequiredMixin
,
ListView
):
...
@@ -79,6 +81,16 @@ class AssetPermissionCreateView(AdminUserRequiredMixin,
...
@@ -79,6 +81,16 @@ class AssetPermissionCreateView(AdminUserRequiredMixin,
self
.
object
.
name
,))
self
.
object
.
name
,))
return
success_message
return
success_message
def
form_valid
(
self
,
form
):
assets
=
form
.
cleaned_data
[
'assets'
]
asset_groups
=
form
.
cleaned_data
[
'asset_groups'
]
system_users
=
form
.
cleaned_data
[
'system_users'
]
associate_system_users_and_assets
(
system_users
,
assets
,
asset_groups
)
response
=
super
(
AssetPermissionCreateView
,
self
)
.
form_valid
(
form
)
self
.
object
.
created_by
=
self
.
request
.
user
.
name
self
.
object
.
save
()
return
response
class
AssetPermissionUpdateView
(
AdminUserRequiredMixin
,
UpdateView
):
class
AssetPermissionUpdateView
(
AdminUserRequiredMixin
,
UpdateView
):
model
=
AssetPermission
model
=
AssetPermission
...
@@ -100,6 +112,13 @@ class AssetPermissionUpdateView(AdminUserRequiredMixin, UpdateView):
...
@@ -100,6 +112,13 @@ class AssetPermissionUpdateView(AdminUserRequiredMixin, UpdateView):
kwargs
=
{
'pk'
:
self
.
object
.
pk
})
kwargs
=
{
'pk'
:
self
.
object
.
pk
})
return
success_url
return
success_url
def
form_valid
(
self
,
form
):
assets
=
form
.
cleaned_data
[
'assets'
]
asset_groups
=
form
.
cleaned_data
[
'asset_groups'
]
system_users
=
form
.
cleaned_data
[
'system_users'
]
associate_system_users_and_assets
(
system_users
,
assets
,
asset_groups
)
return
super
(
AssetPermissionUpdateView
,
self
)
.
form_valid
(
form
)
class
AssetPermissionDetailView
(
AdminUserRequiredMixin
,
DetailView
):
class
AssetPermissionDetailView
(
AdminUserRequiredMixin
,
DetailView
):
template_name
=
'perms/asset_permission_detail.html'
template_name
=
'perms/asset_permission_detail.html'
...
...
apps/static/js/jumpserver.js
View file @
a79c3dd1
...
@@ -187,28 +187,28 @@ function activeNav() {
...
@@ -187,28 +187,28 @@ function activeNav() {
}
}
function
APIUpdateAttr
(
props
)
{
function
APIUpdateAttr
(
props
)
{
// props = {url: .., body: , success: , error: , method: ,}
// props = {url: .., body: , success: , error: , method: ,}
props
=
props
||
{};
props
=
props
||
{};
var
success_message
=
props
.
success_message
||
'Update Successfully!'
;
var
success_message
=
props
.
success_message
||
'Update Successfully!'
;
var
fail_message
=
props
.
fail_message
||
'Error occurred while updating.'
;
var
fail_message
=
props
.
fail_message
||
'Error occurred while updating.'
;
$
.
ajax
({
$
.
ajax
({
url
:
props
.
url
,
url
:
props
.
url
,
type
:
props
.
method
||
"PATCH"
,
type
:
props
.
method
||
"PATCH"
,
data
:
props
.
body
,
data
:
props
.
body
,
contentType
:
props
.
content_type
||
"application/json; charset=utf-8"
,
contentType
:
props
.
content_type
||
"application/json; charset=utf-8"
,
dataType
:
props
.
data_type
||
"json"
dataType
:
props
.
data_type
||
"json"
}).
done
(
function
(
data
,
textStatue
,
jqXHR
)
{
}).
done
(
function
(
data
,
textStatue
,
jqXHR
)
{
toastr
.
success
(
success_message
);
toastr
.
success
(
success_message
);
if
(
typeof
props
.
success
===
'function'
)
{
if
(
typeof
props
.
success
===
'function'
)
{
return
props
.
success
(
data
);
return
props
.
success
(
data
);
}
}
}).
fail
(
function
(
jqXHR
,
textStatue
,
errorThrown
)
{
}).
fail
(
function
(
jqXHR
,
textStatue
,
errorThrown
)
{
toastr
.
error
(
fail_message
);
toastr
.
error
(
fail_message
);
if
(
typeof
props
.
error
===
'function'
)
{
if
(
typeof
props
.
error
===
'function'
)
{
return
props
.
error
(
errorThrown
);
return
props
.
error
(
errorThrown
);
}
}
});
});
// return true;
// return true;
}
}
...
...
apps/users/authentication.py
View file @
a79c3dd1
...
@@ -107,7 +107,6 @@ class AccessKeyAuthentication(authentication.BaseAuthentication):
...
@@ -107,7 +107,6 @@ class AccessKeyAuthentication(authentication.BaseAuthentication):
if
not
access_key
.
user
.
is_active
:
if
not
access_key
.
user
.
is_active
:
raise
exceptions
.
AuthenticationFailed
(
_
(
'User disabled.'
))
raise
exceptions
.
AuthenticationFailed
(
_
(
'User disabled.'
))
return
access_key
.
user
,
None
return
access_key
.
user
,
None
...
...
apps/users/forms.py
View file @
a79c3dd1
...
@@ -31,7 +31,9 @@ class UserCreateUpdateForm(forms.ModelForm):
...
@@ -31,7 +31,9 @@ class UserCreateUpdateForm(forms.ModelForm):
'email'
:
'* required'
,
'email'
:
'* required'
,
}
}
widgets
=
{
widgets
=
{
'groups'
:
forms
.
SelectMultiple
(
attrs
=
{
'class'
:
'select2'
,
'data-placeholder'
:
_
(
'Join user groups'
)}),
'groups'
:
forms
.
SelectMultiple
(
attrs
=
{
'class'
:
'select2'
,
'data-placeholder'
:
_
(
'Join user groups'
)}),
}
}
...
@@ -41,29 +43,11 @@ class UserBulkImportForm(forms.ModelForm):
...
@@ -41,29 +43,11 @@ class UserBulkImportForm(forms.ModelForm):
fields
=
[
'username'
,
'email'
,
'enable_otp'
,
'role'
]
fields
=
[
'username'
,
'email'
,
'enable_otp'
,
'role'
]
# class UserUpdateForm(forms.ModelForm):
#
# class Meta:
# model = User
# fields = [
# 'name', 'email', 'groups', 'wechat',
# 'phone', 'enable_otp', 'role', 'date_expired', 'comment',
# ]
# help_texts = {
# 'username': '* required',
# 'email': '* required',
# 'groups': '* required'
# }
# widgets = {
# 'groups': forms.SelectMultiple(attrs={'class': 'select2', 'data-placeholder': _('Join user groups')}),
# }
class
UserGroupForm
(
forms
.
ModelForm
):
class
UserGroupForm
(
forms
.
ModelForm
):
class
Meta
:
class
Meta
:
model
=
UserGroup
model
=
UserGroup
fields
=
[
fields
=
[
'name'
,
'comment'
,
'name'
,
'comment'
]
]
help_texts
=
{
help_texts
=
{
'name'
:
'* required'
'name'
:
'* required'
...
@@ -87,7 +71,8 @@ class UserKeyForm(forms.Form):
...
@@ -87,7 +71,8 @@ class UserKeyForm(forms.Form):
def
clean_public_key
(
self
):
def
clean_public_key
(
self
):
public_key
=
self
.
cleaned_data
[
'public_key'
]
public_key
=
self
.
cleaned_data
[
'public_key'
]
if
self
.
user
.
public_key
and
public_key
==
self
.
user
.
public_key
:
if
self
.
user
.
public_key
and
public_key
==
self
.
user
.
public_key
:
raise
forms
.
ValidationError
(
_
(
'Public key should not be the same as your old one.'
))
raise
forms
.
ValidationError
(
_
(
'Public key should not be the '
'same as your old one.'
))
if
not
validate_ssh_public_key
(
public_key
):
if
not
validate_ssh_public_key
(
public_key
):
raise
forms
.
ValidationError
(
_
(
'Not a valid ssh public key'
))
raise
forms
.
ValidationError
(
_
(
'Not a valid ssh public key'
))
...
@@ -97,7 +82,8 @@ class UserKeyForm(forms.Form):
...
@@ -97,7 +82,8 @@ class UserKeyForm(forms.Form):
class
UserPrivateAssetPermissionForm
(
forms
.
ModelForm
):
class
UserPrivateAssetPermissionForm
(
forms
.
ModelForm
):
def
save
(
self
,
commit
=
True
):
def
save
(
self
,
commit
=
True
):
self
.
instance
=
super
(
UserPrivateAssetPermissionForm
,
self
)
.
save
(
commit
=
commit
)
self
.
instance
=
super
(
UserPrivateAssetPermissionForm
,
self
)
\
.
save
(
commit
=
commit
)
self
.
instance
.
users
=
[
self
.
user
]
self
.
instance
.
users
=
[
self
.
user
]
self
.
instance
.
save
()
self
.
instance
.
save
()
return
self
.
instance
return
self
.
instance
...
@@ -108,19 +94,23 @@ class UserPrivateAssetPermissionForm(forms.ModelForm):
...
@@ -108,19 +94,23 @@ class UserPrivateAssetPermissionForm(forms.ModelForm):
'assets'
,
'asset_groups'
,
'system_users'
,
'name'
,
'assets'
,
'asset_groups'
,
'system_users'
,
'name'
,
]
]
widgets
=
{
widgets
=
{
'assets'
:
forms
.
SelectMultiple
(
attrs
=
{
'class'
:
'select2'
,
'assets'
:
forms
.
SelectMultiple
(
'data-placeholder'
:
_
(
'Select assets'
)}),
attrs
=
{
'class'
:
'select2'
,
'asset_groups'
:
forms
.
SelectMultiple
(
attrs
=
{
'class'
:
'select2'
,
'data-placeholder'
:
_
(
'Select assets'
)}),
'data-placeholder'
:
_
(
'Select asset groups'
)}),
'asset_groups'
:
forms
.
SelectMultiple
(
'system_users'
:
forms
.
SelectMultiple
(
attrs
=
{
'class'
:
'select2'
,
attrs
=
{
'class'
:
'select2'
,
'data-placeholder'
:
_
(
'Select system users'
)}),
'data-placeholder'
:
_
(
'Select asset groups'
)}),
'system_users'
:
forms
.
SelectMultiple
(
attrs
=
{
'class'
:
'select2'
,
'data-placeholder'
:
_
(
'Select system users'
)}),
}
}
class
UserGroupPrivateAssetPermissionForm
(
forms
.
ModelForm
):
class
UserGroupPrivateAssetPermissionForm
(
forms
.
ModelForm
):
def
save
(
self
,
commit
=
True
):
def
save
(
self
,
commit
=
True
):
self
.
instance
=
super
(
UserGroupPrivateAssetPermissionForm
,
self
)
.
save
(
commit
=
commit
)
self
.
instance
=
super
(
UserGroupPrivateAssetPermissionForm
,
self
)
\
.
save
(
commit
=
commit
)
self
.
instance
.
user_groups
=
[
self
.
user_group
]
self
.
instance
.
user_groups
=
[
self
.
user_group
]
self
.
instance
.
save
()
self
.
instance
.
save
()
return
self
.
instance
return
self
.
instance
...
@@ -131,12 +121,15 @@ class UserGroupPrivateAssetPermissionForm(forms.ModelForm):
...
@@ -131,12 +121,15 @@ class UserGroupPrivateAssetPermissionForm(forms.ModelForm):
'assets'
,
'asset_groups'
,
'system_users'
,
'name'
,
'assets'
,
'asset_groups'
,
'system_users'
,
'name'
,
]
]
widgets
=
{
widgets
=
{
'assets'
:
forms
.
SelectMultiple
(
attrs
=
{
'class'
:
'select2'
,
'assets'
:
forms
.
SelectMultiple
(
'data-placeholder'
:
_
(
'Select assets'
)}),
attrs
=
{
'class'
:
'select2'
,
'asset_groups'
:
forms
.
SelectMultiple
(
attrs
=
{
'class'
:
'select2'
,
'data-placeholder'
:
_
(
'Select assets'
)}),
'data-placeholder'
:
_
(
'Select asset groups'
)}),
'asset_groups'
:
forms
.
SelectMultiple
(
'system_users'
:
forms
.
SelectMultiple
(
attrs
=
{
'class'
:
'select2'
,
attrs
=
{
'class'
:
'select2'
,
'data-placeholder'
:
_
(
'Select system users'
)}),
'data-placeholder'
:
_
(
'Select asset groups'
)}),
'system_users'
:
forms
.
SelectMultiple
(
attrs
=
{
'class'
:
'select2'
,
'data-placeholder'
:
_
(
'Select system users'
)}),
}
}
...
...
apps/users/views/group.py
View file @
a79c3dd1
...
@@ -44,6 +44,7 @@ class UserGroupCreateView(AdminUserRequiredMixin, CreateView):
...
@@ -44,6 +44,7 @@ class UserGroupCreateView(AdminUserRequiredMixin, CreateView):
'users'
:
users
})
'users'
:
users
})
return
context
return
context
# 需要添加组下用户, 而user并不是group的多对多,所以需要手动建立关系
def
form_valid
(
self
,
form
):
def
form_valid
(
self
,
form
):
user_group
=
form
.
save
()
user_group
=
form
.
save
()
users_id_list
=
self
.
request
.
POST
.
getlist
(
'users'
,
[])
users_id_list
=
self
.
request
.
POST
.
getlist
(
'users'
,
[])
...
...
deb_requirements.txt
→
requirements/
deb_requirements.txt
View file @
a79c3dd1
File moved
requirements/mac_requirements.py
0 → 100644
View file @
a79c3dd1
requirements.txt
→
requirements
/requirements
.txt
View file @
a79c3dd1
File moved
rpm_requirements.txt
→
r
equirements/r
pm_requirements.txt
View file @
a79c3dd1
File moved
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