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
673ebbec
Commit
673ebbec
authored
Oct 21, 2019
by
ibuler
Browse files
Options
Browse Files
Download
Plain Diff
[Update] Merge with dev
parents
c2f78b11
f3dc9b88
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
55 changed files
with
536 additions
and
211 deletions
+536
-211
remote_app.py
apps/applications/api/remote_app.py
+3
-5
__init__.py
apps/assets/api/__init__.py
+1
-0
admin_user.py
apps/assets/api/admin_user.py
+5
-7
asset.py
apps/assets/api/asset.py
+7
-8
cmd_filter.py
apps/assets/api/cmd_filter.py
+2
-1
domain.py
apps/assets/api/domain.py
+2
-3
favorite_asset.py
apps/assets/api/favorite_asset.py
+27
-0
gathered_user.py
apps/assets/api/gathered_user.py
+1
-3
label.py
apps/assets/api/label.py
+1
-0
node.py
apps/assets/api/node.py
+13
-13
system_user.py
apps/assets/api/system_user.py
+8
-12
asset.py
apps/assets/forms/asset.py
+8
-1
domain.py
apps/assets/forms/domain.py
+12
-8
label.py
apps/assets/forms/label.py
+12
-8
0042_favoriteasset.py
apps/assets/migrations/0042_favoriteasset.py
+31
-0
__init__.py
apps/assets/models/__init__.py
+1
-0
favorite_asset.py
apps/assets/models/favorite_asset.py
+20
-0
node.py
apps/assets/models/node.py
+18
-6
__init__.py
apps/assets/serializers/__init__.py
+1
-0
admin_user.py
apps/assets/serializers/admin_user.py
+1
-1
asset_user.py
apps/assets/serializers/asset_user.py
+1
-1
favorite_asset.py
apps/assets/serializers/favorite_asset.py
+23
-0
node.py
apps/assets/serializers/node.py
+4
-2
asset_bulk_update.html
apps/assets/templates/assets/asset_bulk_update.html
+8
-0
user_asset_list.html
apps/assets/templates/assets/user_asset_list.html
+59
-21
api_urls.py
apps/assets/urls/api_urls.py
+1
-0
api.py
apps/audits/api.py
+4
-4
api.py
apps/common/api.py
+0
-2
models.py
apps/common/mixins/models.py
+15
-2
signals_handlers.py
apps/common/signals_handlers.py
+1
-1
tree.py
apps/common/tree.py
+2
-0
django.mo
apps/locale/zh/LC_MESSAGES/django.mo
+0
-0
django.po
apps/locale/zh/LC_MESSAGES/django.po
+0
-0
api.py
apps/orgs/mixins/api.py
+9
-3
generics.py
apps/orgs/mixins/generics.py
+41
-0
models.py
apps/orgs/mixins/models.py
+6
-3
utils.py
apps/orgs/utils.py
+8
-2
asset_permission.py
apps/perms/api/asset_permission.py
+19
-19
mixin.py
apps/perms/api/mixin.py
+20
-4
remote_app_permission.py
apps/perms/api/remote_app_permission.py
+8
-7
mixin.py
apps/perms/api/user_permission/mixin.py
+1
-1
user_remote_app_permission.py
apps/perms/api/user_remote_app_permission.py
+4
-6
hands.py
apps/perms/hands.py
+7
-2
asset_permission.py
apps/perms/utils/asset_permission.py
+16
-1
jumpserver.js
apps/static/js/jumpserver.js
+8
-3
session.py
apps/terminal/api/session.py
+1
-1
group.py
apps/users/api/group.py
+3
-4
user.py
apps/users/api/user.py
+18
-21
forms.py
apps/users/forms.py
+18
-17
v1.py
apps/users/serializers/v1.py
+22
-4
_granted_assets.html
apps/users/templates/users/_granted_assets.html
+28
-2
user_bulk_update.html
apps/users/templates/users/user_bulk_update.html
+1
-0
user_group_create_update.html
apps/users/templates/users/user_group_create_update.html
+1
-1
user_group_granted_asset.html
apps/users/templates/users/user_group_granted_asset.html
+1
-1
utils.py
apps/users/utils.py
+4
-0
No files found.
apps/applications/api/remote_app.py
View file @
673ebbec
# coding: utf-8
#
from
rest_framework
import
generics
from
orgs.mixins.api
import
OrgBulkModelViewSet
from
orgs.mixins
import
generics
from
..hands
import
IsOrgAdmin
,
IsAppUser
from
..models
import
RemoteApp
from
..serializers
import
RemoteAppSerializer
,
RemoteAppConnectionInfoSerializer
...
...
@@ -16,14 +14,14 @@ __all__ = [
class
RemoteAppViewSet
(
OrgBulkModelViewSet
):
model
=
RemoteApp
filter_fields
=
(
'name'
,)
search_fields
=
filter_fields
permission_classes
=
(
IsOrgAdmin
,)
queryset
=
RemoteApp
.
objects
.
all
()
serializer_class
=
RemoteAppSerializer
class
RemoteAppConnectionInfoApi
(
generics
.
RetrieveAPIView
):
queryset
=
RemoteApp
.
objects
.
all
()
model
=
RemoteApp
permission_classes
=
(
IsAppUser
,
)
serializer_class
=
RemoteAppConnectionInfoSerializer
apps/assets/api/__init__.py
View file @
673ebbec
...
...
@@ -7,3 +7,4 @@ from .domain import *
from
.cmd_filter
import
*
from
.asset_user
import
*
from
.gathered_user
import
*
from
.favorite_asset
import
*
apps/assets/api/admin_user.py
View file @
673ebbec
...
...
@@ -15,11 +15,10 @@
from
django.db
import
transaction
from
django.shortcuts
import
get_object_or_404
from
rest_framework
import
generics
from
rest_framework.response
import
Response
from
orgs.mixins.api
import
OrgBulkModelViewSet
from
orgs.mixins
import
generics
from
common.mixins
import
CommonApiMixin
from
common.utils
import
get_logger
from
..hands
import
IsOrgAdmin
from
..models
import
AdminUser
,
Asset
...
...
@@ -39,22 +38,21 @@ class AdminUserViewSet(OrgBulkModelViewSet):
"""
Admin user api set, for add,delete,update,list,retrieve resource
"""
model
=
AdminUser
filter_fields
=
(
"name"
,
"username"
)
search_fields
=
filter_fields
queryset
=
AdminUser
.
objects
.
all
()
serializer_class
=
serializers
.
AdminUserSerializer
permission_classes
=
(
IsOrgAdmin
,)
class
AdminUserAuthApi
(
generics
.
UpdateAPIView
):
queryset
=
AdminUser
.
objects
.
all
()
model
=
AdminUser
serializer_class
=
serializers
.
AdminUserAuthSerializer
permission_classes
=
(
IsOrgAdmin
,)
class
ReplaceNodesAdminUserApi
(
generics
.
UpdateAPIView
):
queryset
=
AdminUser
.
objects
.
all
()
model
=
AdminUser
serializer_class
=
serializers
.
ReplaceNodeAdminUserSerializer
permission_classes
=
(
IsOrgAdmin
,)
...
...
@@ -79,7 +77,7 @@ class AdminUserTestConnectiveApi(generics.RetrieveAPIView):
"""
Test asset admin user assets_connectivity
"""
queryset
=
AdminUser
.
objects
.
all
()
model
=
AdminUser
permission_classes
=
(
IsOrgAdmin
,)
serializer_class
=
serializers
.
TaskIDSerializer
...
...
apps/assets/api/asset.py
View file @
673ebbec
...
...
@@ -3,14 +3,14 @@
import
random
from
rest_framework
import
generics
from
rest_framework.response
import
Response
from
django.shortcuts
import
get_object_or_404
from
common.utils
import
get_logger
,
get_object_or_none
from
common.permissions
import
IsOrgAdmin
,
IsOrgAdminOrAppUser
from
orgs.mixins.api
import
OrgBulkModelViewSet
from
..models
import
Asset
,
AdminUser
,
Node
from
orgs.mixins
import
generics
from
..models
import
Asset
,
Node
from
..
import
serializers
from
..tasks
import
update_asset_hardware_info_manual
,
\
test_asset_connectivity_manual
...
...
@@ -29,10 +29,10 @@ class AssetViewSet(OrgBulkModelViewSet):
"""
API endpoint that allows Asset to be viewed or edited.
"""
model
=
Asset
filter_fields
=
(
"hostname"
,
"ip"
,
"systemuser__id"
,
"admin_user__id"
)
search_fields
=
(
"hostname"
,
"ip"
)
ordering_fields
=
(
"hostname"
,
"ip"
,
"port"
,
"cpu_cores"
)
queryset
=
Asset
.
objects
.
all
()
serializer_class
=
serializers
.
AssetSerializer
permission_classes
=
(
IsOrgAdminOrAppUser
,)
extra_filter_backends
=
[
AssetByNodeFilterBackend
,
LabelFilterBackend
]
...
...
@@ -57,7 +57,7 @@ class AssetRefreshHardwareApi(generics.RetrieveAPIView):
"""
Refresh asset hardware info
"""
queryset
=
Asset
.
objects
.
all
()
model
=
Asset
serializer_class
=
serializers
.
AssetSerializer
permission_classes
=
(
IsOrgAdmin
,)
...
...
@@ -72,7 +72,7 @@ class AssetAdminUserTestApi(generics.RetrieveAPIView):
"""
Test asset admin user assets_connectivity
"""
queryset
=
Asset
.
objects
.
all
()
model
=
Asset
permission_classes
=
(
IsOrgAdmin
,)
serializer_class
=
serializers
.
TaskIDSerializer
...
...
@@ -84,9 +84,9 @@ class AssetAdminUserTestApi(generics.RetrieveAPIView):
class
AssetGatewayApi
(
generics
.
RetrieveAPIView
):
queryset
=
Asset
.
objects
.
all
()
permission_classes
=
(
IsOrgAdminOrAppUser
,)
serializer_class
=
serializers
.
GatewayWithAuthSerializer
model
=
Asset
def
retrieve
(
self
,
request
,
*
args
,
**
kwargs
):
asset_id
=
kwargs
.
get
(
'pk'
)
...
...
@@ -98,4 +98,4 @@ class AssetGatewayApi(generics.RetrieveAPIView):
serializer
=
serializers
.
GatewayWithAuthSerializer
(
instance
=
gateway
)
return
Response
(
serializer
.
data
)
else
:
return
Response
({
"msg"
:
"Not have gateway"
},
status
=
404
)
\ No newline at end of file
return
Response
({
"msg"
:
"Not have gateway"
},
status
=
404
)
apps/assets/api/cmd_filter.py
View file @
673ebbec
...
...
@@ -13,14 +13,15 @@ __all__ = ['CommandFilterViewSet', 'CommandFilterRuleViewSet']
class
CommandFilterViewSet
(
OrgBulkModelViewSet
):
model
=
CommandFilter
filter_fields
=
(
"name"
,)
search_fields
=
filter_fields
permission_classes
=
(
IsOrgAdmin
,)
queryset
=
CommandFilter
.
objects
.
all
()
serializer_class
=
serializers
.
CommandFilterSerializer
class
CommandFilterRuleViewSet
(
OrgBulkModelViewSet
):
model
=
CommandFilterRule
filter_fields
=
(
"content"
,)
search_fields
=
filter_fields
permission_classes
=
(
IsOrgAdmin
,)
...
...
apps/assets/api/domain.py
View file @
673ebbec
...
...
@@ -15,7 +15,7 @@ __all__ = ['DomainViewSet', 'GatewayViewSet', "GatewayTestConnectionApi"]
class
DomainViewSet
(
OrgBulkModelViewSet
):
queryset
=
Domain
.
objects
.
all
()
model
=
Domain
permission_classes
=
(
IsOrgAdminOrAppUser
,)
serializer_class
=
serializers
.
DomainSerializer
...
...
@@ -26,16 +26,15 @@ class DomainViewSet(OrgBulkModelViewSet):
class
GatewayViewSet
(
OrgBulkModelViewSet
):
model
=
Gateway
filter_fields
=
(
"domain__name"
,
"name"
,
"username"
,
"ip"
,
"domain"
)
search_fields
=
filter_fields
queryset
=
Gateway
.
objects
.
all
()
permission_classes
=
(
IsOrgAdmin
,)
serializer_class
=
serializers
.
GatewaySerializer
class
GatewayTestConnectionApi
(
SingleObjectMixin
,
APIView
):
permission_classes
=
(
IsOrgAdmin
,)
model
=
Gateway
object
=
None
def
post
(
self
,
request
,
*
args
,
**
kwargs
):
...
...
apps/assets/api/favorite_asset.py
0 → 100644
View file @
673ebbec
# -*- coding: utf-8 -*-
#
from
rest_framework_bulk
import
BulkModelViewSet
from
common.permissions
import
IsValidUser
from
orgs.utils
import
tmp_to_root_org
from
..models
import
FavoriteAsset
from
..serializers
import
FavoriteAssetSerializer
__all__
=
[
'FavoriteAssetViewSet'
]
class
FavoriteAssetViewSet
(
BulkModelViewSet
):
serializer_class
=
FavoriteAssetSerializer
permission_classes
=
(
IsValidUser
,)
filter_fields
=
[
'asset'
]
def
dispatch
(
self
,
request
,
*
args
,
**
kwargs
):
with
tmp_to_root_org
():
return
super
()
.
dispatch
(
request
,
*
args
,
**
kwargs
)
def
get_queryset
(
self
):
queryset
=
FavoriteAsset
.
objects
.
filter
(
user
=
self
.
request
.
user
)
return
queryset
def
allow_bulk_destroy
(
self
,
qs
,
filtered
):
return
filtered
.
count
()
==
1
apps/assets/api/gathered_user.py
View file @
673ebbec
...
...
@@ -13,12 +13,10 @@ __all__ = ['GatheredUserViewSet']
class
GatheredUserViewSet
(
OrgModelViewSet
):
queryset
=
GatheredUser
.
objects
.
all
()
model
=
GatheredUser
serializer_class
=
GatheredUserSerializer
permission_classes
=
[
IsOrgAdmin
]
extra_filter_backends
=
[
AssetRelatedByNodeFilterBackend
]
filter_fields
=
[
'asset'
,
'username'
,
'present'
]
search_fields
=
[
'username'
,
'asset__ip'
,
'asset__hostname'
]
apps/assets/api/label.py
View file @
673ebbec
...
...
@@ -27,6 +27,7 @@ __all__ = ['LabelViewSet']
class
LabelViewSet
(
OrgBulkModelViewSet
):
model
=
Label
filter_fields
=
(
"name"
,
"value"
)
search_fields
=
filter_fields
permission_classes
=
(
IsOrgAdmin
,)
...
...
apps/assets/api/node.py
View file @
673ebbec
...
...
@@ -13,7 +13,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
from
rest_framework
import
generics
,
status
from
rest_framework
import
status
from
rest_framework.serializers
import
ValidationError
from
rest_framework.views
import
APIView
from
rest_framework.response
import
Response
...
...
@@ -23,9 +23,12 @@ from django.shortcuts import get_object_or_404
from
common.utils
import
get_logger
,
get_object_or_none
from
common.tree
import
TreeNodeSerializer
from
orgs.mixins.api
import
OrgModelViewSet
from
orgs.mixins
import
generics
from
..hands
import
IsOrgAdmin
from
..models
import
Node
from
..tasks
import
update_assets_hardware_info_util
,
test_asset_connectivity_util
from
..tasks
import
(
update_assets_hardware_info_util
,
test_asset_connectivity_util
)
from
..
import
serializers
...
...
@@ -40,9 +43,9 @@ __all__ = [
class
NodeViewSet
(
OrgModelViewSet
):
model
=
Node
filter_fields
=
(
'value'
,
'key'
,
'id'
)
search_fields
=
(
'value'
,
)
queryset
=
Node
.
objects
.
all
()
permission_classes
=
(
IsOrgAdmin
,)
serializer_class
=
serializers
.
NodeSerializer
...
...
@@ -79,6 +82,7 @@ class NodeListAsTreeApi(generics.ListAPIView):
}
]
"""
model
=
Node
permission_classes
=
(
IsOrgAdmin
,)
serializer_class
=
TreeNodeSerializer
...
...
@@ -87,10 +91,6 @@ class NodeListAsTreeApi(generics.ListAPIView):
queryset
=
[
node
.
as_tree_node
()
for
node
in
queryset
]
return
queryset
def
get_queryset
(
self
):
queryset
=
Node
.
objects
.
all
()
return
queryset
def
filter_queryset
(
self
,
queryset
):
queryset
=
super
()
.
filter_queryset
(
queryset
)
queryset
=
self
.
to_tree_queryset
(
queryset
)
...
...
@@ -98,7 +98,6 @@ class NodeListAsTreeApi(generics.ListAPIView):
class
NodeChildrenApi
(
generics
.
ListCreateAPIView
):
queryset
=
Node
.
objects
.
all
()
permission_classes
=
(
IsOrgAdmin
,)
serializer_class
=
serializers
.
NodeSerializer
instance
=
None
...
...
@@ -162,6 +161,7 @@ class NodeChildrenAsTreeApi(NodeChildrenApi):
]
"""
model
=
Node
serializer_class
=
TreeNodeSerializer
http_method_names
=
[
'get'
]
...
...
@@ -204,7 +204,7 @@ class NodeAssetsApi(generics.ListAPIView):
class
NodeAddChildrenApi
(
generics
.
UpdateAPIView
):
queryset
=
Node
.
objects
.
all
()
model
=
Node
permission_classes
=
(
IsOrgAdmin
,)
serializer_class
=
serializers
.
NodeAddChildrenSerializer
instance
=
None
...
...
@@ -221,8 +221,8 @@ class NodeAddChildrenApi(generics.UpdateAPIView):
class
NodeAddAssetsApi
(
generics
.
UpdateAPIView
):
model
=
Node
serializer_class
=
serializers
.
NodeAssetsSerializer
queryset
=
Node
.
objects
.
all
()
permission_classes
=
(
IsOrgAdmin
,)
instance
=
None
...
...
@@ -233,8 +233,8 @@ class NodeAddAssetsApi(generics.UpdateAPIView):
class
NodeRemoveAssetsApi
(
generics
.
UpdateAPIView
):
model
=
Node
serializer_class
=
serializers
.
NodeAssetsSerializer
queryset
=
Node
.
objects
.
all
()
permission_classes
=
(
IsOrgAdmin
,)
instance
=
None
...
...
@@ -249,8 +249,8 @@ class NodeRemoveAssetsApi(generics.UpdateAPIView):
class
NodeReplaceAssetsApi
(
generics
.
UpdateAPIView
):
model
=
Node
serializer_class
=
serializers
.
NodeAssetsSerializer
queryset
=
Node
.
objects
.
all
()
permission_classes
=
(
IsOrgAdmin
,)
instance
=
None
...
...
@@ -262,8 +262,8 @@ class NodeReplaceAssetsApi(generics.UpdateAPIView):
class
RefreshNodeHardwareInfoApi
(
APIView
):
permission_classes
=
(
IsOrgAdmin
,)
model
=
Node
permission_classes
=
(
IsOrgAdmin
,)
def
get
(
self
,
request
,
*
args
,
**
kwargs
):
node_id
=
kwargs
.
get
(
'pk'
)
...
...
apps/assets/api/system_user.py
View file @
673ebbec
...
...
@@ -14,13 +14,13 @@
# limitations under the License.
from
django.shortcuts
import
get_object_or_404
from
rest_framework
import
generics
from
rest_framework.response
import
Response
from
common.serializers
import
CeleryTaskSerializer
from
common.utils
import
get_logger
from
common.permissions
import
IsOrgAdmin
,
IsOrgAdminOrAppUser
from
orgs.mixins.api
import
OrgBulkModelViewSet
from
orgs.mixins
import
generics
from
..models
import
SystemUser
,
Asset
from
..
import
serializers
from
..tasks
import
(
...
...
@@ -43,22 +43,18 @@ class SystemUserViewSet(OrgBulkModelViewSet):
"""
System user api set, for add,delete,update,list,retrieve resource
"""
model
=
SystemUser
filter_fields
=
(
"name"
,
"username"
)
search_fields
=
filter_fields
queryset
=
SystemUser
.
objects
.
all
()
serializer_class
=
serializers
.
SystemUserSerializer
permission_classes
=
(
IsOrgAdminOrAppUser
,)
def
get_queryset
(
self
):
queryset
=
super
()
.
get_queryset
()
.
all
()
return
queryset
class
SystemUserAuthInfoApi
(
generics
.
RetrieveUpdateDestroyAPIView
):
"""
Get system user auth info
"""
queryset
=
SystemUser
.
objects
.
all
()
model
=
SystemUser
permission_classes
=
(
IsOrgAdminOrAppUser
,)
serializer_class
=
serializers
.
SystemUserAuthSerializer
...
...
@@ -72,7 +68,7 @@ class SystemUserAssetAuthInfoApi(generics.RetrieveAPIView):
"""
Get system user with asset auth info
"""
queryset
=
SystemUser
.
objects
.
all
()
model
=
SystemUser
permission_classes
=
(
IsOrgAdminOrAppUser
,)
serializer_class
=
serializers
.
SystemUserAuthSerializer
...
...
@@ -88,7 +84,7 @@ class SystemUserPushApi(generics.RetrieveAPIView):
"""
Push system user to cluster assets api
"""
queryset
=
SystemUser
.
objects
.
all
()
model
=
SystemUser
permission_classes
=
(
IsOrgAdmin
,)
serializer_class
=
CeleryTaskSerializer
...
...
@@ -105,7 +101,7 @@ class SystemUserTestConnectiveApi(generics.RetrieveAPIView):
"""
Push system user to cluster assets api
"""
queryset
=
SystemUser
.
objects
.
all
()
model
=
SystemUser
permission_classes
=
(
IsOrgAdmin
,)
serializer_class
=
CeleryTaskSerializer
...
...
@@ -132,7 +128,7 @@ class SystemUserAssetsListView(generics.ListAPIView):
class
SystemUserPushToAssetApi
(
generics
.
RetrieveAPIView
):
queryset
=
SystemUser
.
objects
.
all
()
model
=
SystemUser
permission_classes
=
(
IsOrgAdmin
,)
serializer_class
=
serializers
.
TaskIDSerializer
...
...
@@ -145,7 +141,7 @@ class SystemUserPushToAssetApi(generics.RetrieveAPIView):
class
SystemUserTestAssetConnectivityApi
(
generics
.
RetrieveAPIView
):
queryset
=
SystemUser
.
objects
.
all
()
model
=
SystemUser
permission_classes
=
(
IsOrgAdmin
,)
serializer_class
=
serializers
.
TaskIDSerializer
...
...
apps/assets/forms/asset.py
View file @
673ebbec
...
...
@@ -129,7 +129,7 @@ class AssetUpdateForm(OrgModelForm):
class
AssetBulkUpdateForm
(
OrgModelForm
):
assets
=
forms
.
ModelMultipleChoiceField
(
required
=
True
,
label
=
_
(
'Select assets'
),
queryset
=
Asset
.
objects
.
all
()
,
label
=
_
(
'Select assets'
),
queryset
=
Asset
.
objects
,
widget
=
forms
.
SelectMultiple
(
attrs
=
{
'class'
:
'select2'
,
...
...
@@ -155,11 +155,18 @@ class AssetBulkUpdateForm(OrgModelForm):
def
__init__
(
self
,
*
args
,
**
kwargs
):
super
()
.
__init__
(
*
args
,
**
kwargs
)
self
.
set_fields_queryset
()
# 重写其他字段为不再required
for
name
,
field
in
self
.
fields
.
items
():
if
name
!=
'assets'
:
field
.
required
=
False
def
set_fields_queryset
(
self
):
assets_field
=
self
.
fields
[
'assets'
]
if
hasattr
(
self
,
'data'
):
assets_field
.
queryset
=
Asset
.
objects
.
all
()
def
save
(
self
,
commit
=
True
):
changed_fields
=
[]
for
field
in
self
.
_meta
.
fields
:
...
...
apps/assets/forms/domain.py
View file @
673ebbec
...
...
@@ -12,7 +12,7 @@ __all__ = ['DomainForm', 'GatewayForm']
class
DomainForm
(
forms
.
ModelForm
):
assets
=
forms
.
ModelMultipleChoiceField
(
queryset
=
Asset
.
objects
.
all
()
,
label
=
_
(
'Asset'
),
required
=
False
,
queryset
=
Asset
.
objects
,
label
=
_
(
'Asset'
),
required
=
False
,
widget
=
forms
.
SelectMultiple
(
attrs
=
{
'class'
:
'select2'
,
'data-placeholder'
:
_
(
'Select assets'
)}
)
...
...
@@ -23,19 +23,23 @@ class DomainForm(forms.ModelForm):
fields
=
[
'name'
,
'comment'
,
'assets'
]
def
__init__
(
self
,
*
args
,
**
kwargs
):
if
kwargs
.
get
(
'instance'
,
None
):
initial
=
kwargs
.
get
(
'initial'
,
{})
initial
[
'assets'
]
=
kwargs
[
'instance'
]
.
assets
.
all
()
super
()
.
__init__
(
*
args
,
**
kwargs
)
self
.
set_fields_queryset
()
# 前端渲染优化, 防止过多资产
def
set_fields_queryset
(
self
):
assets_field
=
self
.
fields
.
get
(
'assets'
)
# 没有data代表是渲染表单, 有data代表是提交创建/更新表单
if
not
self
.
data
:
instance
=
kwargs
.
get
(
'instance'
)
if
instance
:
assets_field
.
queryset
=
instance
.
assets
.
all
()
# 有instance 代表渲染更新表单, 否则是创建表单
# 前端渲染优化, 防止过多资产, 设置assets queryset为none
if
self
.
instance
:
assets_field
.
initial
=
self
.
instance
.
assets
.
all
()
assets_field
.
queryset
=
self
.
instance
.
assets
.
all
()
else
:
assets_field
.
queryset
=
Asset
.
objects
.
none
()
else
:
assets_field
.
queryset
=
Asset
.
objects
.
all
()
def
save
(
self
,
commit
=
True
):
instance
=
super
()
.
save
(
commit
=
commit
)
...
...
apps/assets/forms/label.py
View file @
673ebbec
...
...
@@ -10,7 +10,7 @@ __all__ = ['LabelForm']
class
LabelForm
(
forms
.
ModelForm
):
assets
=
forms
.
ModelMultipleChoiceField
(
queryset
=
Asset
.
objects
.
all
(),
label
=
_
(
'Asset'
),
required
=
False
,
queryset
=
Asset
.
objects
.
none
(),
label
=
_
(
'Asset'
),
required
=
False
,
widget
=
forms
.
SelectMultiple
(
attrs
=
{
'class'
:
'select2'
,
'data-placeholder'
:
_
(
'Select assets'
)}
)
...
...
@@ -21,19 +21,23 @@ class LabelForm(forms.ModelForm):
fields
=
[
'name'
,
'value'
,
'assets'
]
def
__init__
(
self
,
*
args
,
**
kwargs
):
if
kwargs
.
get
(
'instance'
,
None
):
initial
=
kwargs
.
get
(
'initial'
,
{})
initial
[
'assets'
]
=
kwargs
[
'instance'
]
.
assets
.
all
()
super
()
.
__init__
(
*
args
,
**
kwargs
)
self
.
set_fields_queryset
()
# 前端渲染优化, 防止过多资产
def
set_fields_queryset
(
self
):
assets_field
=
self
.
fields
.
get
(
'assets'
)
# 没有data代表是渲染表单, 有data代表是提交创建/更新表单
if
not
self
.
data
:
instance
=
kwargs
.
get
(
'instance'
)
if
instance
:
assets_field
.
queryset
=
instance
.
assets
.
all
()
# 有instance 代表渲染更新表单, 否则是创建表单
# 前端渲染优化, 防止过多资产, 设置assets queryset为none
if
self
.
instance
:
assets_field
.
initial
=
self
.
instance
.
assets
.
all
()
assets_field
.
queryset
=
self
.
instance
.
assets
.
all
()
else
:
assets_field
.
queryset
=
Asset
.
objects
.
none
()
else
:
assets_field
.
queryset
=
Asset
.
objects
.
all
()
def
save
(
self
,
commit
=
True
):
label
=
super
()
.
save
(
commit
=
commit
)
...
...
apps/assets/migrations/0042_favoriteasset.py
0 → 100644
View file @
673ebbec
# Generated by Django 2.2.5 on 2019-10-16 08:38
from
django.conf
import
settings
from
django.db
import
migrations
,
models
import
django.db.models.deletion
import
uuid
class
Migration
(
migrations
.
Migration
):
dependencies
=
[
migrations
.
swappable_dependency
(
settings
.
AUTH_USER_MODEL
),
(
'assets'
,
'0041_gathereduser'
),
]
operations
=
[
migrations
.
CreateModel
(
name
=
'FavoriteAsset'
,
fields
=
[
(
'id'
,
models
.
UUIDField
(
default
=
uuid
.
uuid4
,
primary_key
=
True
,
serialize
=
False
)),
(
'created_by'
,
models
.
CharField
(
blank
=
True
,
max_length
=
32
,
null
=
True
,
verbose_name
=
'Created by'
)),
(
'date_created'
,
models
.
DateTimeField
(
auto_now_add
=
True
,
null
=
True
,
verbose_name
=
'Date created'
)),
(
'date_updated'
,
models
.
DateTimeField
(
auto_now
=
True
,
verbose_name
=
'Date updated'
)),
(
'asset'
,
models
.
ForeignKey
(
on_delete
=
django
.
db
.
models
.
deletion
.
CASCADE
,
to
=
'assets.Asset'
)),
(
'user'
,
models
.
ForeignKey
(
on_delete
=
django
.
db
.
models
.
deletion
.
CASCADE
,
to
=
settings
.
AUTH_USER_MODEL
)),
],
options
=
{
'unique_together'
:
{(
'user'
,
'asset'
)},
},
),
]
apps/assets/models/__init__.py
View file @
673ebbec
...
...
@@ -10,3 +10,4 @@ from .authbook import *
from
.utils
import
*
from
.authbook
import
*
from
.gathered_user
import
*
from
.favorite_asset
import
*
apps/assets/models/favorite_asset.py
0 → 100644
View file @
673ebbec
# -*- coding: utf-8 -*-
#
from
django.db
import
models
from
common.mixins.models
import
CommonModelMixin
__all__
=
[
'FavoriteAsset'
]
class
FavoriteAsset
(
CommonModelMixin
):
user
=
models
.
ForeignKey
(
'users.User'
,
on_delete
=
models
.
CASCADE
)
asset
=
models
.
ForeignKey
(
'assets.Asset'
,
on_delete
=
models
.
CASCADE
)
class
Meta
:
unique_together
=
(
'user'
,
'asset'
)
@classmethod
def
get_user_favorite_assets_id
(
cls
,
user
):
return
cls
.
objects
.
filter
(
user
=
user
)
.
values_list
(
'asset'
,
flat
=
True
)
apps/assets/models/node.py
View file @
673ebbec
...
...
@@ -324,6 +324,8 @@ class SomeNodesMixin:
ungrouped_value
=
_
(
'ungrouped'
)
empty_key
=
'-11'
empty_value
=
_
(
"empty"
)
favorite_key
=
'-12'
favorite_value
=
_
(
"favorite"
)
def
is_default_node
(
self
):
return
self
.
key
==
self
.
default_key
...
...
@@ -363,7 +365,7 @@ class SomeNodesMixin:
@classmethod
def
ungrouped_node
(
cls
):
with
tmp_to_org
(
Organization
.
system
()):
defaults
=
{
'value'
:
cls
.
ungrouped_
key
}
defaults
=
{
'value'
:
cls
.
ungrouped_
value
}
obj
,
created
=
cls
.
objects
.
get_or_create
(
defaults
=
defaults
,
key
=
cls
.
ungrouped_key
)
...
...
@@ -387,11 +389,21 @@ class SomeNodesMixin:
)
return
obj
@classmethod
def
favorite_node
(
cls
):
with
tmp_to_org
(
Organization
.
system
()):
defaults
=
{
'value'
:
cls
.
favorite_value
}
obj
,
created
=
cls
.
objects
.
get_or_create
(
defaults
=
defaults
,
key
=
cls
.
favorite_key
)
return
obj
@classmethod
def
initial_some_nodes
(
cls
):
cls
.
default_node
()
cls
.
empty_node
()
cls
.
ungrouped_node
()
cls
.
favorite_node
()
class
Node
(
OrgModelMixin
,
SomeNodesMixin
,
TreeMixin
,
FamilyMixin
,
FullValueMixin
,
NodeAssetsMixin
):
...
...
@@ -412,11 +424,11 @@ class Node(OrgModelMixin, SomeNodesMixin, TreeMixin, FamilyMixin, FullValueMixin
def
__str__
(
self
):
return
self
.
value
def
__eq__
(
self
,
other
):
if
not
other
:
return
False
return
self
.
id
==
other
.
id
#
def __eq__(self, other):
#
if not other:
#
return False
#
return self.id == other.id
#
def
__gt__
(
self
,
other
):
self_key
=
[
int
(
k
)
for
k
in
self
.
key
.
split
(
':'
)]
other_key
=
[
int
(
k
)
for
k
in
other
.
key
.
split
(
':'
)]
...
...
apps/assets/serializers/__init__.py
View file @
673ebbec
...
...
@@ -10,3 +10,4 @@ from .domain import *
from
.cmd_filter
import
*
from
.asset_user
import
*
from
.gathered_user
import
*
from
.favorite_asset
import
*
apps/assets/serializers/admin_user.py
View file @
673ebbec
...
...
@@ -45,7 +45,7 @@ class ReplaceNodeAdminUserSerializer(serializers.ModelSerializer):
管理用户更新关联到的集群
"""
nodes
=
serializers
.
PrimaryKeyRelatedField
(
many
=
True
,
queryset
=
Node
.
objects
.
all
()
many
=
True
,
queryset
=
Node
.
objects
)
class
Meta
:
...
...
apps/assets/serializers/asset_user.py
View file @
673ebbec
...
...
@@ -79,7 +79,7 @@ class AssetUserAuthInfoSerializer(serializers.ModelSerializer):
class
AssetUserPushSerializer
(
serializers
.
Serializer
):
asset
=
serializers
.
PrimaryKeyRelatedField
(
queryset
=
Asset
.
objects
.
all
()
,
label
=
_
(
"Asset"
))
asset
=
serializers
.
PrimaryKeyRelatedField
(
queryset
=
Asset
.
objects
,
label
=
_
(
"Asset"
))
username
=
serializers
.
CharField
(
max_length
=
1024
)
def
create
(
self
,
validated_data
):
...
...
apps/assets/serializers/favorite_asset.py
0 → 100644
View file @
673ebbec
# -*- coding: utf-8 -*-
#
from
rest_framework
import
serializers
from
orgs.utils
import
tmp_to_root_org
from
common.serializers
import
AdaptedBulkListSerializer
from
common.mixins
import
BulkSerializerMixin
from
..models
import
FavoriteAsset
__all__
=
[
'FavoriteAssetSerializer'
]
class
FavoriteAssetSerializer
(
BulkSerializerMixin
,
serializers
.
ModelSerializer
):
user
=
serializers
.
HiddenField
(
default
=
serializers
.
CurrentUserDefault
()
)
class
Meta
:
list_serializer_class
=
AdaptedBulkListSerializer
model
=
FavoriteAsset
fields
=
[
'user'
,
'asset'
]
apps/assets/serializers/node.py
View file @
673ebbec
...
...
@@ -38,8 +38,10 @@ class NodeSerializer(BulkOrgResourceModelSerializer):
return
data
class
NodeAssetsSerializer
(
serializers
.
ModelSerializer
):
assets
=
serializers
.
PrimaryKeyRelatedField
(
many
=
True
,
queryset
=
Asset
.
objects
.
all
())
class
NodeAssetsSerializer
(
BulkOrgResourceModelSerializer
):
assets
=
serializers
.
PrimaryKeyRelatedField
(
many
=
True
,
queryset
=
Asset
.
objects
)
class
Meta
:
model
=
Node
...
...
apps/assets/templates/assets/asset_bulk_update.html
View file @
673ebbec
...
...
@@ -25,12 +25,20 @@
</div>
</div>
</form>
{% include 'assets/_asset_list_modal.html' %}
{% endblock %}
{% block custom_foot_js %}
<script>
$
(
document
).
ready
(
function
()
{
$
(
'.select2'
).
select2
();
$
(
"#id_assets"
).
parent
().
find
(
".select2-selection"
).
on
(
'click'
,
function
(
e
)
{
if
(
$
(
e
.
target
).
attr
(
'class'
)
!==
'select2-selection__choice__remove'
){
e
.
preventDefault
();
e
.
stopPropagation
();
$
(
"#asset_list_modal"
).
modal
();
}
})
}).
on
(
'click'
,
'.field-tag'
,
function
()
{
changeField
(
this
);
}).
on
(
'click'
,
'#change_all'
,
function
()
{
...
...
apps/assets/templates/assets/user_asset_list.html
View file @
673ebbec
...
...
@@ -21,19 +21,46 @@
{% block custom_foot_js %}
<script>
var
treeUrl
=
"{% url 'api-perms:my-nodes-children-as-tree' %}?
&
cache_policy=1"
;
var
treeUrl
=
"{% url 'api-perms:my-nodes-children-as-tree' %}?cache_policy=1"
;
var
assetTableUrl
=
"{% url 'api-perms:my-assets' %}?cache_policy=1"
;
var
selectUrl
=
'{% url "api-perms:my-node-assets" node_id=DEFAULT_PK %}?cache_policy=1&all=1'
;
var
systemUsersUrl
=
"{% url 'api-perms:my-asset-system-users' asset_id=DEFAULT_PK %}?cache_policy=1"
;
var
showAssetHref
=
false
;
// Need input default true
var
favoriteAssets
=
[];
var
favorBtnTmpl
=
'<a class="btn btn-xs btn-default btn-favor" data-id="ID"><i class="fa fa-star-o"></i></a>'
;
var
disfavorBtnTmpl
=
'<a class="btn btn-xs btn-default btn-disfavor" data-id="ID"><i class="fa fa-star"></i></a>'
;
var
actions
=
{
targets
:
4
,
createdCell
:
function
(
td
,
cellData
)
{
var
conn_btn
=
'<a href="{% url "luna-view" %}?login_to='
+
cellData
+
'" class="btn btn-xs btn-primary" target="_blank">{% trans "Connect" %}</a>'
;
$
(
td
).
html
(
conn_btn
)
var
connBtn
=
'<a href="{% url "luna-view" %}?login_to='
+
cellData
+
'" class="btn btn-xs btn-primary" target="_blank"><i class="fa fa-terminal"></i></a> '
;
var
favorBtn
=
favorBtnTmpl
.
replace
(
"ID"
,
cellData
);
var
disfavorBtn
=
disfavorBtnTmpl
.
replace
(
"ID"
,
cellData
);
var
btn
=
connBtn
;
if
(
favoriteAssets
.
indexOf
(
cellData
)
===
-
1
)
{
btn
+=
favorBtn
}
else
{
btn
+=
disfavorBtn
;
}
$
(
td
).
html
(
btn
)
}};
$
(
document
).
ready
(
function
()
{
initTree
();
requestApi
({
method
:
"GET"
,
url
:
"{% url 'api-assets:favorite-asset-list' %}"
,
success
:
function
(
data
)
{
favoriteAssets
=
data
.
map
(
function
(
i
)
{
return
i
.
asset
;
});
initTree
();
},
error
:
function
()
{
initTree
();
},
flash_message
:
false
})
}).
on
(
'click'
,
'.labels li'
,
function
()
{
var
val
=
$
(
this
).
text
();
$
(
"#user_assets_table_filter input"
).
val
(
val
);
...
...
@@ -67,22 +94,33 @@ $(document).ready(function () {
};
$
(
'#asset_detail_tbody'
).
html
(
trs
)
$
(
'#user_asset_detail_modal'
).
modal
();
})
.
on
(
'click'
,
'.btn-favor'
,
function
()
{
var
$this
=
$
(
this
);
var
assetId
=
$
(
this
).
data
(
"id"
);
requestApi
({
url
:
"{% url 'api-assets:favorite-asset-list' %}"
,
method
:
"POST"
,
body
:
JSON
.
stringify
({
asset
:
assetId
}),
flash_message
:
false
,
success
:
function
(
data
)
{
var
btn
=
disfavorBtnTmpl
.
replace
(
"ID"
,
assetId
);
$this
.
replaceWith
(
btn
)
}
});
})
.
on
(
'click'
,
'.btn-disfavor'
,
function
()
{
var
$this
=
$
(
this
);
var
assetId
=
$
(
this
).
data
(
"id"
);
requestApi
({
url
:
"{% url 'api-assets:favorite-asset-list' %}?asset="
+
assetId
,
method
:
"DELETE"
,
flash_message
:
false
,
success
:
function
(
data
)
{
var
btn
=
favorBtnTmpl
.
replace
(
"ID"
,
assetId
);
$this
.
replaceWith
(
btn
)
}
});
});
function
toggle
()
{
if
(
show
===
0
)
{
$
(
"#split-left"
).
hide
(
500
,
function
()
{
$
(
"#split-right"
).
attr
(
"class"
,
"col-lg-12"
);
$
(
"#toggle-icon"
).
attr
(
"class"
,
"fa fa-angle-right fa-x"
);
show
=
1
;
});
}
else
{
$
(
"#split-right"
).
attr
(
"class"
,
"col-lg-9"
);
$
(
"#toggle-icon"
).
attr
(
"class"
,
"fa fa-angle-left fa-x"
);
$
(
"#split-left"
).
show
(
500
);
show
=
0
;
}
}
</script>
{% endblock %}
apps/assets/urls/api_urls.py
View file @
673ebbec
...
...
@@ -22,6 +22,7 @@ router.register(r'cmd-filters', api.CommandFilterViewSet, 'cmd-filter')
router
.
register
(
r'asset-users'
,
api
.
AssetUserViewSet
,
'asset-user'
)
router
.
register
(
r'asset-users-info'
,
api
.
AssetUserExportViewSet
,
'asset-user-info'
)
router
.
register
(
r'gathered-users'
,
api
.
GatheredUserViewSet
,
'gathered-user'
)
router
.
register
(
r'favorite-assets'
,
api
.
FavoriteAssetViewSet
,
'favorite-asset'
)
cmd_filter_router
=
routers
.
NestedDefaultRouter
(
router
,
r'cmd-filters'
,
lookup
=
'filter'
)
cmd_filter_router
.
register
(
r'rules'
,
api
.
CommandFilterRuleViewSet
,
'cmd-filter-rule'
)
...
...
apps/audits/api.py
View file @
673ebbec
# -*- coding: utf-8 -*-
#
from
rest_framework
import
viewsets
from
common.permissions
import
IsOrgAdminOrAppUser
,
IsOrgAuditor
from
orgs.mixins.api
import
OrgModelViewSet
from
.models
import
FTPLog
from
.serializers
import
FTPLogSerializer
class
FTPLogViewSet
(
viewsets
.
ModelViewSet
):
queryset
=
FTPLog
.
objects
.
all
()
class
FTPLogViewSet
(
Org
ModelViewSet
):
model
=
FTPLog
serializer_class
=
FTPLogSerializer
permission_classes
=
(
IsOrgAdminOrAppUser
|
IsOrgAuditor
,)
apps/common/api.py
View file @
673ebbec
...
...
@@ -83,8 +83,6 @@ class LogTailApi(generics.RetrieveAPIView):
return
Response
({
"data"
:
data
,
'end'
:
end
,
'mark'
:
new_mark
})
class
ResourcesIDCacheApi
(
APIView
):
def
post
(
self
,
request
,
*
args
,
**
kwargs
):
spm
=
str
(
uuid
.
uuid4
())
...
...
apps/common/mixins/models.py
View file @
673ebbec
# -*- coding: utf-8 -*-
#
import
uuid
from
django.db
import
models
from
django.utils
import
timezone
from
django.utils.translation
import
ugettext_lazy
as
_
__all__
=
[
"NoDeleteManager"
,
"NoDeleteModelMixin"
,
"NoDeleteQuerySet"
]
__all__
=
[
"NoDeleteManager"
,
"NoDeleteModelMixin"
,
"NoDeleteQuerySet"
,
"CommonModelMixin"
]
class
NoDeleteQuerySet
(
models
.
query
.
QuerySet
):
...
...
@@ -40,3 +43,13 @@ class NoDeleteModelMixin(models.Model):
self
.
is_discard
=
True
self
.
discard_time
=
timezone
.
now
()
return
self
.
save
()
class
CommonModelMixin
(
models
.
Model
):
id
=
models
.
UUIDField
(
default
=
uuid
.
uuid4
,
primary_key
=
True
)
created_by
=
models
.
CharField
(
max_length
=
32
,
null
=
True
,
blank
=
True
,
verbose_name
=
_
(
'Created by'
))
date_created
=
models
.
DateTimeField
(
auto_now_add
=
True
,
null
=
True
,
blank
=
True
,
verbose_name
=
_
(
'Date created'
))
date_updated
=
models
.
DateTimeField
(
auto_now
=
True
,
verbose_name
=
_
(
'Date updated'
))
class
Meta
:
abstract
=
True
apps/common/signals_handlers.py
View file @
673ebbec
...
...
@@ -36,7 +36,7 @@ def on_request_finished_logging_db_query(sender, **kwargs):
queries
=
connection
.
queries
counters
=
defaultdict
(
Counter
)
for
query
in
queries
:
if
not
query
[
'sql'
]
.
startswith
(
'SELECT'
):
if
not
query
[
'sql'
]
or
not
query
[
'sql'
]
.
startswith
(
'SELECT'
):
continue
tables
=
pattern
.
findall
(
query
[
'sql'
])
table_name
=
''
.
join
(
tables
)
...
...
apps/common/tree.py
View file @
673ebbec
...
...
@@ -51,6 +51,8 @@ class TreeNode:
result
=
True
elif
self
.
pId
!=
other
.
pId
:
result
=
self
.
pId
>
other
.
pId
elif
self
.
id
.
startswith
(
'-'
)
and
not
other
.
id
.
startswith
(
'-'
):
result
=
False
else
:
result
=
self
.
name
>
other
.
name
return
result
...
...
apps/locale/zh/LC_MESSAGES/django.mo
View file @
673ebbec
No preview for this file type
apps/locale/zh/LC_MESSAGES/django.po
View file @
673ebbec
This diff is collapsed.
Click to expand it.
apps/orgs/mixins/api.py
View file @
673ebbec
...
...
@@ -10,7 +10,7 @@ from ..models import Organization
__all__
=
[
'RootOrgViewMixin'
,
'OrgMembershipModelViewSetMixin'
,
'OrgModelViewSet'
,
'OrgBulkModelViewSet'
,
'OrgBulkModelViewSet'
,
'OrgQuerySetMixin'
,
]
...
...
@@ -22,8 +22,14 @@ class RootOrgViewMixin:
class
OrgQuerySetMixin
:
def
get_queryset
(
self
):
queryset
=
super
()
.
get_queryset
()
queryset
=
filter_org_queryset
(
queryset
)
if
hasattr
(
self
,
'model'
):
queryset
=
self
.
model
.
objects
.
all
()
else
:
assert
self
.
queryset
is
None
,
(
"'
%
s' should not include a `queryset` attribute"
%
self
.
__class__
.
__name__
)
queryset
=
super
()
.
get_queryset
()
if
hasattr
(
self
,
'swagger_fake_view'
):
return
queryset
[:
1
]
...
...
apps/orgs/mixins/generics.py
0 → 100644
View file @
673ebbec
# -*- coding: utf-8 -*-
#
from
rest_framework
import
generics
from
.api
import
OrgQuerySetMixin
class
ListAPIView
(
OrgQuerySetMixin
,
generics
.
ListAPIView
):
pass
class
RetrieveAPIView
(
OrgQuerySetMixin
,
generics
.
RetrieveAPIView
):
pass
class
CreateAPIView
(
OrgQuerySetMixin
,
generics
.
CreateAPIView
):
pass
class
DestroyAPIView
(
OrgQuerySetMixin
,
generics
.
DestroyAPIView
):
pass
class
ListCreateAPIView
(
OrgQuerySetMixin
,
generics
.
ListCreateAPIView
):
pass
class
UpdateAPIView
(
OrgQuerySetMixin
,
generics
.
UpdateAPIView
):
pass
class
RetrieveUpdateAPIView
(
OrgQuerySetMixin
,
generics
.
RetrieveUpdateAPIView
):
pass
class
RetrieveDestroyAPIView
(
OrgQuerySetMixin
,
generics
.
RetrieveDestroyAPIView
):
pass
class
RetrieveUpdateDestroyAPIView
(
OrgQuerySetMixin
,
generics
.
RetrieveUpdateDestroyAPIView
):
pass
apps/orgs/mixins/models.py
View file @
673ebbec
...
...
@@ -8,7 +8,7 @@ from django.core.exceptions import ValidationError
from
common.utils
import
get_logger
from
..utils
import
(
set_current_org
,
get_current_org
,
current_org
,
filter_org_queryset
,
filter_org_queryset
)
from
..models
import
Organization
...
...
@@ -48,9 +48,12 @@ class OrgModelMixin(models.Model):
def
save
(
self
,
*
args
,
**
kwargs
):
org
=
get_current_org
()
if
org
is
not
None
and
(
org
.
is_real
()
or
org
.
is_system
()):
if
org
is
None
:
return
super
()
.
save
(
*
args
,
**
kwargs
)
if
org
.
is_real
()
or
org
.
is_system
():
self
.
org_id
=
org
.
id
elif
org
is
not
None
and
org
.
is_default
():
elif
org
.
is_default
():
self
.
org_id
=
''
return
super
()
.
save
(
*
args
,
**
kwargs
)
...
...
apps/orgs/utils.py
View file @
673ebbec
...
...
@@ -83,17 +83,23 @@ def tmp_to_org(org):
set_current_org
(
ori_org
)
def
filter_org_queryset
(
queryset
):
def
get_org_filters
(
):
kwargs
=
{}
_current_org
=
get_current_org
()
if
_current_org
is
None
:
return
queryset
.
none
()
return
kwargs
if
_current_org
.
is_real
():
kwargs
[
'org_id'
]
=
_current_org
.
id
elif
_current_org
.
is_default
():
kwargs
[
"org_id"
]
=
''
return
kwargs
def
filter_org_queryset
(
queryset
):
kwargs
=
get_org_filters
()
#
# lines = traceback.format_stack()
# print(">>>>>>>>>>>>>>>>>>>>>>>>>>>>")
...
...
apps/perms/api/asset_permission.py
View file @
673ebbec
# -*- coding: utf-8 -*-
#
from
django.utils
import
timezone
from
django.db.models
import
Q
from
rest_framework.views
import
Response
from
django.shortcuts
import
get_object_or_404
from
rest_framework.generics
import
RetrieveUpdateAPIView
,
ListAPIView
from
rest_framework
import
viewsets
from
common.permissions
import
IsOrgAdmin
from
orgs.mixins.api
import
OrgModelViewSet
from
orgs.mixins
import
generics
from
common.utils
import
get_object_or_none
from
..models
import
AssetPermission
from
..hands
import
(
...
...
@@ -24,15 +23,21 @@ __all__ = [
]
class
AssetPermissionViewSet
(
viewsets
.
ModelViewSet
):
class
AssetPermissionViewSet
(
Org
ModelViewSet
):
"""
资产授权列表的增删改查api
"""
queryset
=
AssetPermission
.
objects
.
all
()
model
=
AssetPermission
serializer_class
=
serializers
.
AssetPermissionCreateUpdateSerializer
filter_fields
=
[
'name'
]
permission_classes
=
(
IsOrgAdmin
,)
def
get_queryset
(
self
):
queryset
=
super
()
.
get_queryset
()
.
prefetch_related
(
"nodes"
,
"assets"
,
"users"
,
"user_groups"
,
"system_users"
)
return
queryset
def
get_serializer_class
(
self
):
if
self
.
action
in
(
"list"
,
'retrieve'
)
and
\
self
.
request
.
query_params
.
get
(
"display"
):
...
...
@@ -160,19 +165,14 @@ class AssetPermissionViewSet(viewsets.ModelViewSet):
queryset
=
queryset
.
distinct
()
return
queryset
def
get_queryset
(
self
):
return
self
.
queryset
.
all
()
.
prefetch_related
(
"nodes"
,
"assets"
,
"users"
,
"user_groups"
,
"system_users"
)
class
AssetPermissionRemoveUserApi
(
RetrieveUpdateAPIView
):
class
AssetPermissionRemoveUserApi
(
generics
.
RetrieveUpdateAPIView
):
"""
将用户从授权中移除,Detail页面会调用
"""
model
=
AssetPermission
permission_classes
=
(
IsOrgAdmin
,)
serializer_class
=
serializers
.
AssetPermissionUpdateUserSerializer
queryset
=
AssetPermission
.
objects
.
all
()
def
update
(
self
,
request
,
*
args
,
**
kwargs
):
perm
=
self
.
get_object
()
...
...
@@ -187,10 +187,10 @@ class AssetPermissionRemoveUserApi(RetrieveUpdateAPIView):
return
Response
({
"error"
:
serializer
.
errors
})
class
AssetPermissionAddUserApi
(
RetrieveUpdateAPIView
):
class
AssetPermissionAddUserApi
(
generics
.
RetrieveUpdateAPIView
):
model
=
AssetPermission
permission_classes
=
(
IsOrgAdmin
,)
serializer_class
=
serializers
.
AssetPermissionUpdateUserSerializer
queryset
=
AssetPermission
.
objects
.
all
()
def
update
(
self
,
request
,
*
args
,
**
kwargs
):
perm
=
self
.
get_object
()
...
...
@@ -205,13 +205,13 @@ class AssetPermissionAddUserApi(RetrieveUpdateAPIView):
return
Response
({
"error"
:
serializer
.
errors
})
class
AssetPermissionRemoveAssetApi
(
RetrieveUpdateAPIView
):
class
AssetPermissionRemoveAssetApi
(
generics
.
RetrieveUpdateAPIView
):
"""
将用户从授权中移除,Detail页面会调用
"""
model
=
AssetPermission
permission_classes
=
(
IsOrgAdmin
,)
serializer_class
=
serializers
.
AssetPermissionUpdateAssetSerializer
queryset
=
AssetPermission
.
objects
.
all
()
def
update
(
self
,
request
,
*
args
,
**
kwargs
):
perm
=
self
.
get_object
()
...
...
@@ -226,10 +226,10 @@ class AssetPermissionRemoveAssetApi(RetrieveUpdateAPIView):
return
Response
({
"error"
:
serializer
.
errors
})
class
AssetPermissionAddAssetApi
(
RetrieveUpdateAPIView
):
class
AssetPermissionAddAssetApi
(
generics
.
RetrieveUpdateAPIView
):
model
=
AssetPermission
permission_classes
=
(
IsOrgAdmin
,)
serializer_class
=
serializers
.
AssetPermissionUpdateAssetSerializer
queryset
=
AssetPermission
.
objects
.
all
()
def
update
(
self
,
request
,
*
args
,
**
kwargs
):
perm
=
self
.
get_object
()
...
...
@@ -244,7 +244,7 @@ class AssetPermissionAddAssetApi(RetrieveUpdateAPIView):
return
Response
({
"error"
:
serializer
.
errors
})
class
AssetPermissionAssetsApi
(
ListAPIView
):
class
AssetPermissionAssetsApi
(
generics
.
ListAPIView
):
permission_classes
=
(
IsOrgAdmin
,)
serializer_class
=
serializers
.
AssetPermissionAssetsSerializer
filter_fields
=
(
"hostname"
,
"ip"
)
...
...
apps/perms/api/mixin.py
View file @
673ebbec
...
...
@@ -4,7 +4,7 @@
from
rest_framework.generics
import
get_object_or_404
from
common.permissions
import
IsValidUser
,
IsOrgAdminOrAppUser
from
common.utils
import
get_logger
from
orgs.utils
import
set_to_root_org
from
orgs.utils
import
set_to_root_org
,
get_current_org
,
set_current_org
,
tmp_to_root_org
from
..hands
import
User
,
UserGroup
...
...
@@ -17,15 +17,24 @@ __all__ = [
class
UserPermissionMixin
:
permission_classes
=
(
IsOrgAdminOrAppUser
,)
current_org
=
None
obj
=
None
def
initial
(
self
,
*
args
,
**
kwargs
):
super
()
.
initial
(
*
args
,
*
kwargs
)
self
.
current_org
=
get_current_org
()
set_to_root_org
()
self
.
obj
=
self
.
get_obj
()
def
get
(
self
,
request
,
*
args
,
**
kwargs
):
set_to_root_org
()
return
super
()
.
get
(
request
,
*
args
,
**
kwargs
)
# def dispatch(self, request, *args, **kwargs):
# """不能这么做,校验权限时拿不到组织了"""
# with tmp_to_root_org():
# return super().dispatch(request, *args, **kwargs)
# def get(self, request, *args, **kwargs):
# """有的api重写了get方法"""
# with tmp_to_root_org():
# return super().get(request, *args, **kwargs)
def
get_obj
(
self
):
user_id
=
self
.
kwargs
.
get
(
'pk'
,
''
)
...
...
@@ -40,6 +49,13 @@ class UserPermissionMixin:
self
.
permission_classes
=
(
IsValidUser
,)
return
super
()
.
get_permissions
()
def
finalize_response
(
self
,
request
,
response
,
*
args
,
**
kwargs
):
response
=
super
()
.
finalize_response
(
request
,
response
,
*
args
,
**
kwargs
)
org
=
getattr
(
self
,
'current_org'
,
None
)
if
org
:
set_current_org
(
org
)
return
response
class
UserGroupPermissionMixin
:
obj
=
None
...
...
apps/perms/api/remote_app_permission.py
View file @
673ebbec
# coding: utf-8
#
from
rest_framework
import
viewsets
,
generics
from
rest_framework.views
import
Response
from
common.permissions
import
IsOrgAdmin
from
orgs.mixins.api
import
OrgModelViewSet
from
orgs.mixins
import
generics
from
..models
import
RemoteAppPermission
from
..serializers
import
(
RemoteAppPermissionSerializer
,
...
...
@@ -20,18 +21,18 @@ __all__ = [
]
class
RemoteAppPermissionViewSet
(
viewsets
.
ModelViewSet
):
class
RemoteAppPermissionViewSet
(
OrgModelViewSet
):
model
=
RemoteAppPermission
filter_fields
=
(
'name'
,
)
search_fields
=
filter_fields
queryset
=
RemoteAppPermission
.
objects
.
all
()
serializer_class
=
RemoteAppPermissionSerializer
permission_classes
=
(
IsOrgAdmin
,)
class
RemoteAppPermissionAddUserApi
(
generics
.
RetrieveUpdateAPIView
):
model
=
RemoteAppPermission
permission_classes
=
(
IsOrgAdmin
,)
serializer_class
=
RemoteAppPermissionUpdateUserSerializer
queryset
=
RemoteAppPermission
.
objects
.
all
()
def
update
(
self
,
request
,
*
args
,
**
kwargs
):
perm
=
self
.
get_object
()
...
...
@@ -46,9 +47,9 @@ class RemoteAppPermissionAddUserApi(generics.RetrieveUpdateAPIView):
class
RemoteAppPermissionRemoveUserApi
(
generics
.
RetrieveUpdateAPIView
):
model
=
RemoteAppPermission
permission_classes
=
(
IsOrgAdmin
,)
serializer_class
=
RemoteAppPermissionUpdateUserSerializer
queryset
=
RemoteAppPermission
.
objects
.
all
()
def
update
(
self
,
request
,
*
args
,
**
kwargs
):
perm
=
self
.
get_object
()
...
...
@@ -63,9 +64,9 @@ class RemoteAppPermissionRemoveUserApi(generics.RetrieveUpdateAPIView):
class
RemoteAppPermissionAddRemoteAppApi
(
generics
.
RetrieveUpdateAPIView
):
model
=
RemoteAppPermission
permission_classes
=
(
IsOrgAdmin
,)
serializer_class
=
RemoteAppPermissionUpdateRemoteAppSerializer
queryset
=
RemoteAppPermission
.
objects
.
all
()
def
update
(
self
,
request
,
*
args
,
**
kwargs
):
perm
=
self
.
get_object
()
...
...
@@ -80,9 +81,9 @@ class RemoteAppPermissionAddRemoteAppApi(generics.RetrieveUpdateAPIView):
class
RemoteAppPermissionRemoveRemoteAppApi
(
generics
.
RetrieveUpdateAPIView
):
model
=
RemoteAppPermission
permission_classes
=
(
IsOrgAdmin
,)
serializer_class
=
RemoteAppPermissionUpdateRemoteAppSerializer
queryset
=
RemoteAppPermission
.
objects
.
all
()
def
update
(
self
,
request
,
*
args
,
**
kwargs
):
perm
=
self
.
get_object
()
...
...
apps/perms/api/user_permission/mixin.py
View file @
673ebbec
...
...
@@ -34,7 +34,7 @@ class UserNodeTreeMixin:
for
node
in
nodes
:
assets_amount
=
self
.
tree
.
valid_assets_amount
(
node
.
key
)
if
assets_amount
==
0
and
no
de
.
key
!=
Node
.
empty_key
:
if
assets_amount
==
0
and
no
t
node
.
key
.
startswith
(
'-'
)
:
continue
node
.
assets_amount
=
assets_amount
data
=
ParserNode
.
parse_node_to_tree_node
(
node
)
...
...
apps/perms/api/user_remote_app_permission.py
View file @
673ebbec
...
...
@@ -3,12 +3,10 @@
import
uuid
from
django.shortcuts
import
get_object_or_404
from
rest_framework.views
import
APIView
,
Response
from
rest_framework.generics
import
(
ListAPIView
,
get_object_or_404
,
)
from
common.permissions
import
IsValidUser
,
IsOrgAdminOrAppUser
from
common.tree
import
TreeNodeSerializer
from
orgs.mixins
import
generics
from
..utils
import
(
RemoteAppPermissionUtil
,
construct_remote_apps_tree_root
,
parse_remote_app_to_tree_node
,
...
...
@@ -25,7 +23,7 @@ __all__ = [
]
class
UserGrantedRemoteAppsApi
(
ListAPIView
):
class
UserGrantedRemoteAppsApi
(
generics
.
ListAPIView
):
permission_classes
=
(
IsOrgAdminOrAppUser
,)
serializer_class
=
RemoteAppSerializer
filter_fields
=
[
'name'
,
'id'
]
...
...
@@ -68,7 +66,7 @@ class UserGrantedRemoteAppsAsTreeApi(UserGrantedRemoteAppsApi):
return
super
()
.
get_serializer
(
data
,
many
=
True
)
class
UserGrantedRemoteAppSystemUsersApi
(
UserPermissionMixin
,
ListAPIView
):
class
UserGrantedRemoteAppSystemUsersApi
(
UserPermissionMixin
,
generics
.
ListAPIView
):
permission_classes
=
(
IsOrgAdminOrAppUser
,)
serializer_class
=
serializers
.
RemoteAppSystemUserSerializer
only_fields
=
serializers
.
RemoteAppSystemUserSerializer
.
Meta
.
only_fields
...
...
@@ -110,7 +108,7 @@ class ValidateUserRemoteAppPermissionApi(APIView):
# RemoteApp permission
class
UserGroupGrantedRemoteAppsApi
(
ListAPIView
):
class
UserGroupGrantedRemoteAppsApi
(
generics
.
ListAPIView
):
permission_classes
=
(
IsOrgAdminOrAppUser
,
)
serializer_class
=
RemoteAppSerializer
...
...
apps/perms/hands.py
View file @
673ebbec
...
...
@@ -2,10 +2,15 @@
#
from
users.models
import
User
,
UserGroup
from
assets.models
import
Asset
,
SystemUser
,
Node
,
Label
from
assets.models
import
Asset
,
SystemUser
,
Node
,
Label
,
FavoriteAsset
from
assets.serializers
import
NodeSerializer
from
applications.serializers
import
RemoteAppSerializer
from
applications.models
import
RemoteApp
__all__
=
[
'User'
,
'UserGroup'
,
'Asset'
,
'SystemUser'
,
'Node'
,
'Label'
,
'FavoriteAsset'
,
'NodeSerializer'
,
'RemoteAppSerializer'
,
'RemoteApp'
]
apps/perms/utils/asset_permission.py
View file @
673ebbec
...
...
@@ -13,7 +13,7 @@ from common.utils import get_logger, timeit, lazyproperty
from
common.tree
import
TreeNode
from
assets.utils
import
TreeService
from
..models
import
AssetPermission
from
..hands
import
Node
,
Asset
,
SystemUser
from
..hands
import
Node
,
Asset
,
SystemUser
,
User
,
FavoriteAsset
logger
=
get_logger
(
__file__
)
...
...
@@ -293,6 +293,20 @@ class AssetPermissionUtilV2(AssetPermissionUtilCacheMixin):
parent
=
user_tree
.
root
,
)
def
add_favorite_node_if_need
(
self
,
user_tree
):
if
not
isinstance
(
self
.
object
,
User
):
return
node_key
=
Node
.
favorite_key
node_value
=
Node
.
favorite_value
user_tree
.
create_node
(
identifier
=
node_key
,
tag
=
node_value
,
parent
=
user_tree
.
root
,
)
assets_id
=
FavoriteAsset
.
get_user_favorite_assets_id
(
self
.
object
)
all_valid_assets
=
user_tree
.
all_valid_assets
(
user_tree
.
root
)
valid_assets_id
=
set
(
assets_id
)
&
all_valid_assets
user_tree
.
set_assets
(
node_key
,
valid_assets_id
)
def
set_user_tree_to_local
(
self
,
user_tree
):
self
.
_user_tree
=
user_tree
self
.
_user_tree_filter_id
=
self
.
_filter_id
...
...
@@ -323,6 +337,7 @@ class AssetPermissionUtilV2(AssetPermissionUtilCacheMixin):
self
.
add_single_assets_node_to_user_tree
(
user_tree
)
self
.
parse_user_tree_to_full_tree
(
user_tree
)
self
.
add_empty_node_if_need
(
user_tree
)
self
.
add_favorite_node_if_need
(
user_tree
)
self
.
set_user_tree_to_cache_if_need
(
user_tree
)
self
.
set_user_tree_to_local
(
user_tree
)
return
user_tree
...
...
apps/static/js/jumpserver.js
View file @
673ebbec
...
...
@@ -271,7 +271,7 @@ function requestApi(props) {
$
.
ajax
({
url
:
props
.
url
,
type
:
props
.
method
||
"PATCH"
,
data
:
props
.
body
,
data
:
props
.
body
||
props
.
data
,
contentType
:
props
.
content_type
||
"application/json; charset=utf-8"
,
dataType
:
props
.
data_type
||
"json"
}).
done
(
function
(
data
,
textStatue
,
jqXHR
)
{
...
...
@@ -960,8 +960,13 @@ function initPopover($container, $progress, $idPassword, $el, password_check_rul
function
rootNodeAddDom
(
ztree
,
callback
)
{
var
refreshIcon
=
"<a id='tree-refresh'><i class='fa fa-refresh'></i></a>"
;
var
rootNode
=
ztree
.
getNodes
()[
0
];
var
$rootNodeRef
=
$
(
"#"
+
rootNode
.
tId
+
"_a"
);
$rootNodeRef
.
after
(
refreshIcon
);
if
(
rootNode
)
{
var
$rootNodeRef
=
$
(
"#"
+
rootNode
.
tId
+
"_a"
);
$rootNodeRef
.
after
(
refreshIcon
);
}
else
{
$rootNodeRef
=
$
(
'#'
+
ztree
.
setting
.
treeId
);
$rootNodeRef
.
html
(
refreshIcon
);
}
var
refreshIconRef
=
$
(
'#tree-refresh'
);
refreshIconRef
.
bind
(
'click'
,
function
()
{
ztree
.
destroy
();
...
...
apps/terminal/api/session.py
View file @
673ebbec
...
...
@@ -24,7 +24,7 @@ logger = get_logger(__name__)
class
SessionViewSet
(
OrgBulkModelViewSet
):
queryset
=
Session
.
objects
.
all
()
model
=
Session
serializer_class
=
serializers
.
SessionSerializer
permission_classes
=
(
IsOrgAdminOrAppUser
,
)
filterset_fields
=
[
...
...
apps/users/api/group.py
View file @
673ebbec
# -*- coding: utf-8 -*-
#
from
rest_framework
import
generics
from
..serializers
import
(
UserGroupSerializer
,
UserGroupListSerializer
,
...
...
@@ -10,6 +8,7 @@ from ..serializers import (
)
from
..models
import
UserGroup
from
orgs.mixins.api
import
OrgBulkModelViewSet
from
orgs.mixins
import
generics
from
common.permissions
import
IsOrgAdmin
...
...
@@ -17,9 +16,9 @@ __all__ = ['UserGroupViewSet', 'UserGroupUpdateUserApi']
class
UserGroupViewSet
(
OrgBulkModelViewSet
):
model
=
UserGroup
filter_fields
=
(
"name"
,)
search_fields
=
filter_fields
queryset
=
UserGroup
.
objects
.
all
()
serializer_class
=
UserGroupSerializer
permission_classes
=
(
IsOrgAdmin
,)
...
...
@@ -31,6 +30,6 @@ class UserGroupViewSet(OrgBulkModelViewSet):
class
UserGroupUpdateUserApi
(
generics
.
RetrieveUpdateAPIView
):
queryset
=
UserGroup
.
objects
.
all
()
model
=
UserGroup
serializer_class
=
UserGroupUpdateMemberSerializer
permission_classes
=
(
IsOrgAdmin
,)
apps/users/api/user.py
View file @
673ebbec
...
...
@@ -17,7 +17,7 @@ from common.permissions import (
from
common.mixins
import
CommonApiMixin
from
common.utils
import
get_logger
from
orgs.utils
import
current_org
from
..
import
serializers
from
..
import
serializers
,
utils
from
..models
import
User
from
..signals
import
post_user_create
...
...
@@ -30,13 +30,21 @@ __all__ = [
]
class
UserViewSet
(
CommonApiMixin
,
BulkModelViewSet
):
class
UserQuerysetMixin
:
def
get_queryset
(
self
):
queryset
=
utils
.
get_current_org_members
()
return
queryset
class
UserViewSet
(
CommonApiMixin
,
UserQuerysetMixin
,
BulkModelViewSet
):
filter_fields
=
(
'username'
,
'email'
,
'name'
,
'id'
)
search_fields
=
filter_fields
queryset
=
User
.
objects
.
exclude
(
role
=
User
.
ROLE_APP
)
serializer_class
=
serializers
.
UserSerializer
permission_classes
=
(
IsOrgAdmin
,
CanUpdateDeleteUser
)
def
get_queryset
(
self
):
return
super
()
.
get_queryset
()
.
prefetch_related
(
'groups'
)
def
send_created_signal
(
self
,
users
):
if
not
isinstance
(
users
,
list
):
users
=
[
users
]
...
...
@@ -51,11 +59,6 @@ class UserViewSet(CommonApiMixin, BulkModelViewSet):
current_org
.
users
.
add
(
*
users
)
self
.
send_created_signal
(
users
)
def
get_queryset
(
self
):
queryset
=
current_org
.
get_org_members
()
\
.
prefetch_related
(
'groups'
)
return
queryset
def
get_permissions
(
self
):
if
self
.
action
in
[
"retrieve"
,
"list"
]:
self
.
permission_classes
=
(
IsOrgAdminOrAppUser
,)
...
...
@@ -79,9 +82,8 @@ class UserViewSet(CommonApiMixin, BulkModelViewSet):
return
super
()
.
perform_bulk_update
(
serializer
)
class
UserChangePasswordApi
(
generics
.
RetrieveUpdateAPIView
):
class
UserChangePasswordApi
(
UserQuerysetMixin
,
generics
.
RetrieveUpdateAPIView
):
permission_classes
=
(
IsOrgAdmin
,)
queryset
=
User
.
objects
.
all
()
serializer_class
=
serializers
.
ChangeUserPasswordSerializer
def
perform_update
(
self
,
serializer
):
...
...
@@ -90,13 +92,12 @@ class UserChangePasswordApi(generics.RetrieveUpdateAPIView):
user
.
save
()
class
UserUpdateGroupApi
(
generics
.
RetrieveUpdateAPIView
):
queryset
=
User
.
objects
.
all
()
class
UserUpdateGroupApi
(
UserQuerysetMixin
,
generics
.
RetrieveUpdateAPIView
):
serializer_class
=
serializers
.
UserUpdateGroupSerializer
permission_classes
=
(
IsOrgAdmin
,)
class
UserResetPasswordApi
(
generics
.
UpdateAPIView
):
class
UserResetPasswordApi
(
UserQuerysetMixin
,
generics
.
UpdateAPIView
):
queryset
=
User
.
objects
.
all
()
serializer_class
=
serializers
.
UserSerializer
permission_classes
=
(
IsAuthenticated
,)
...
...
@@ -111,8 +112,7 @@ class UserResetPasswordApi(generics.UpdateAPIView):
send_reset_password_mail
(
user
)
class
UserResetPKApi
(
generics
.
UpdateAPIView
):
queryset
=
User
.
objects
.
all
()
class
UserResetPKApi
(
UserQuerysetMixin
,
generics
.
UpdateAPIView
):
serializer_class
=
serializers
.
UserSerializer
permission_classes
=
(
IsAuthenticated
,)
...
...
@@ -125,8 +125,7 @@ class UserResetPKApi(generics.UpdateAPIView):
# 废弃
class
UserUpdatePKApi
(
generics
.
UpdateAPIView
):
queryset
=
User
.
objects
.
all
()
class
UserUpdatePKApi
(
UserQuerysetMixin
,
generics
.
UpdateAPIView
):
serializer_class
=
serializers
.
UserPKUpdateSerializer
permission_classes
=
(
IsCurrentUserOrReadOnly
,)
...
...
@@ -136,8 +135,7 @@ class UserUpdatePKApi(generics.UpdateAPIView):
user
.
save
()
class
UserUnblockPKApi
(
generics
.
UpdateAPIView
):
queryset
=
User
.
objects
.
all
()
class
UserUnblockPKApi
(
UserQuerysetMixin
,
generics
.
UpdateAPIView
):
permission_classes
=
(
IsOrgAdmin
,)
serializer_class
=
serializers
.
UserSerializer
key_prefix_limit
=
"_LOGIN_LIMIT_{}_{}"
...
...
@@ -165,8 +163,7 @@ class UserProfileApi(generics.RetrieveAPIView):
return
super
()
.
retrieve
(
request
,
*
args
,
**
kwargs
)
class
UserResetOTPApi
(
generics
.
RetrieveAPIView
):
queryset
=
User
.
objects
.
all
()
class
UserResetOTPApi
(
UserQuerysetMixin
,
generics
.
RetrieveAPIView
):
permission_classes
=
(
IsOrgAdmin
,)
serializer_class
=
serializers
.
ResetOTPSerializer
...
...
apps/users/forms.py
View file @
673ebbec
...
...
@@ -5,9 +5,8 @@ from django.utils.translation import gettext_lazy as _
from
common.utils
import
validate_ssh_public_key
from
orgs.mixins.forms
import
OrgModelForm
from
orgs.utils
import
current_org
from
.models
import
User
,
UserGroup
from
.utils
import
check_password_rules
from
.utils
import
check_password_rules
,
get_current_org_members
class
UserCheckPasswordForm
(
forms
.
Form
):
...
...
@@ -267,15 +266,23 @@ class UserBulkUpdateForm(OrgModelForm):
users
=
forms
.
ModelMultipleChoiceField
(
required
=
True
,
label
=
_
(
'Select users'
),
queryset
=
User
.
objects
.
all
(),
queryset
=
User
.
objects
.
none
(),
widget
=
forms
.
SelectMultiple
(
attrs
=
{
'class'
:
'select2'
,
'class'
:
'
users-
select2'
,
'data-placeholder'
:
_
(
'Select users'
)
}
)
)
def
__init__
(
self
,
*
args
,
**
kwargs
):
super
()
.
__init__
(
*
args
,
**
kwargs
)
self
.
set_fields_queryset
()
def
set_fields_queryset
(
self
):
users_field
=
self
.
fields
[
'users'
]
users_field
.
queryset
=
get_current_org_members
()
class
Meta
:
model
=
User
fields
=
[
'users'
,
'groups'
,
'date_expired'
]
...
...
@@ -320,25 +327,19 @@ class UserGroupForm(OrgModelForm):
)
def
__init__
(
self
,
**
kwargs
):
instance
=
kwargs
.
get
(
'instance'
)
if
instance
:
initial
=
kwargs
.
get
(
'initial'
,
{})
initial
.
update
({
'users'
:
instance
.
users
.
all
()})
kwargs
[
'initial'
]
=
initial
super
()
.
__init__
(
**
kwargs
)
if
'initial'
not
in
kwargs
:
return
self
.
set_fields_queryset
()
def
set_fields_queryset
(
self
):
users_field
=
self
.
fields
.
get
(
'users'
)
if
instance
:
users_field
.
queryset
=
instance
.
users
.
all
()
if
self
.
instance
:
users_field
.
initial
=
self
.
instance
.
users
.
all
()
users_field
.
queryset
=
self
.
instance
.
users
.
all
()
else
:
users_field
.
queryset
=
User
.
objects
.
none
()
def
save
(
self
,
commit
=
True
):
group
=
super
()
.
save
(
commit
=
commit
)
users
=
self
.
cleaned_data
[
'users'
]
group
.
users
.
set
(
users
)
return
group
raise
Exception
(
"Save by restful api"
)
class
Meta
:
model
=
UserGroup
...
...
apps/users/serializers/v1.py
View file @
673ebbec
# -*- coding: utf-8 -*-
#
import
copy
from
django.utils.translation
import
ugettext_lazy
as
_
from
rest_framework
import
serializers
...
...
@@ -12,6 +11,7 @@ from common.serializers import AdaptedBulkListSerializer
from
common.permissions
import
CanUpdateDeleteUser
from
orgs.mixins.serializers
import
BulkOrgResourceModelSerializer
from
..models
import
User
,
UserGroup
from
..
import
utils
__all__
=
[
...
...
@@ -118,7 +118,9 @@ class UserPKUpdateSerializer(serializers.ModelSerializer):
class
UserUpdateGroupSerializer
(
serializers
.
ModelSerializer
):
groups
=
serializers
.
PrimaryKeyRelatedField
(
many
=
True
,
queryset
=
UserGroup
.
objects
.
all
())
groups
=
serializers
.
PrimaryKeyRelatedField
(
many
=
True
,
queryset
=
UserGroup
.
objects
)
class
Meta
:
model
=
User
...
...
@@ -127,7 +129,7 @@ class UserUpdateGroupSerializer(serializers.ModelSerializer):
class
UserGroupSerializer
(
BulkOrgResourceModelSerializer
):
users
=
serializers
.
PrimaryKeyRelatedField
(
required
=
False
,
many
=
True
,
queryset
=
User
.
objects
.
all
()
,
label
=
_
(
'User'
)
required
=
False
,
many
=
True
,
queryset
=
User
.
objects
,
label
=
_
(
'User'
)
)
class
Meta
:
...
...
@@ -141,6 +143,14 @@ class UserGroupSerializer(BulkOrgResourceModelSerializer):
'created_by'
:
{
'label'
:
_
(
'Created by'
),
'read_only'
:
True
}
}
def
__init__
(
self
,
*
args
,
**
kwargs
):
super
()
.
__init__
(
*
args
,
**
kwargs
)
self
.
set_fields_queryset
()
def
set_fields_queryset
(
self
):
users_field
=
self
.
fields
[
'users'
]
users_field
.
child_relation
.
queryset
=
utils
.
get_current_org_members
()
def
validate_users
(
self
,
users
):
for
user
in
users
:
if
user
.
is_super_auditor
:
...
...
@@ -154,12 +164,20 @@ class UserGroupListSerializer(UserGroupSerializer):
class
UserGroupUpdateMemberSerializer
(
serializers
.
ModelSerializer
):
users
=
serializers
.
PrimaryKeyRelatedField
(
many
=
True
,
queryset
=
User
.
objects
.
all
()
)
users
=
serializers
.
PrimaryKeyRelatedField
(
many
=
True
,
queryset
=
User
.
objects
)
class
Meta
:
model
=
UserGroup
fields
=
[
'id'
,
'users'
]
def
__init__
(
self
,
*
args
,
**
kwargs
):
super
()
.
__init__
(
*
args
,
**
kwargs
)
self
.
set_fields_queryset
()
def
set_fields_queryset
(
self
):
users_field
=
self
.
fields
[
'users'
]
users_field
.
child_relation
.
queryset
=
utils
.
get_current_org_members
()
class
ChangeUserPasswordSerializer
(
serializers
.
ModelSerializer
):
...
...
apps/users/templates/users/_granted_assets.html
View file @
673ebbec
{% load i18n %}
<div
class=
"col-lg-3"
style=
"padding-left: 0
px
"
>
<div
class=
"col-lg-3"
style=
"padding-left: 0
"
id=
"split-left
"
>
<div
class=
"ibox float-e-margins"
>
<div
class=
"ibox-content mailbox-content"
style=
"padding-top: 0"
>
<div
class=
"file-manager "
>
...
...
@@ -11,7 +11,12 @@
</div>
</div>
</div>
<div
class=
"col-lg-9 animated fadeInRight"
>
<div
class=
"col-lg-9 animated fadeInRight"
id=
"split-right"
>
<div
class=
"tree-toggle"
>
<div
class=
"btn btn-sm btn-primary tree-toggle-btn"
onclick=
"toggle()"
>
<i
class=
"fa fa-angle-left fa-x"
id=
"toggle-icon"
></i>
</div>
</div>
<div
class=
"mail-box-header"
>
{#
<div
class=
"btn-group"
style=
"float: right"
>
#}
{#
<button
data-toggle=
"dropdown"
class=
"btn btn-default btn-sm labels dropdown-toggle"
>
{% trans 'Label' %}
<span
class=
"caret"
></span></button>
#}
...
...
@@ -174,6 +179,27 @@ function loadLabels() {
}
}
var
show
=
0
;
function
toggle
()
{
if
(
show
===
0
)
{
$
(
"#split-left"
).
hide
(
500
,
function
()
{
$
(
"#split-right"
).
attr
(
"class"
,
"col-lg-12"
);
$
(
"#toggle-icon"
).
attr
(
"class"
,
"fa fa-angle-right fa-x"
);
show
=
1
;
});
}
else
{
$
(
"#split-right"
).
attr
(
"class"
,
"col-lg-9"
);
$
(
"#toggle-icon"
).
attr
(
"class"
,
"fa fa-angle-left fa-x"
);
$
(
"#split-left"
).
show
(
500
);
show
=
0
;
}
setTimeout
(
function
()
{
$
(
".table"
).
css
(
"width"
,
"100%"
);
{
#
assetTable
.
columns
.
adjust
();
#
}
},
500
)
}
$
(
document
).
ready
(
function
()
{
{
#
loadLabels
()
#
}
}).
on
(
'click'
,
'.labels-menu li'
,
function
()
{
...
...
apps/users/templates/users/user_bulk_update.html
View file @
673ebbec
...
...
@@ -31,6 +31,7 @@
<script>
$
(
document
).
ready
(
function
()
{
$
(
'.select2'
).
select2
();
usersSelect2Init
(
'.users-select2'
)
}).
on
(
'click'
,
'.field-tag'
,
function
()
{
changeField
(
this
);
}).
on
(
'click'
,
'#change_all'
,
function
()
{
...
...
apps/users/templates/users/user_group_create_update.html
View file @
673ebbec
...
...
@@ -28,7 +28,7 @@
{% bootstrap_field form.comment layout="horizontal" %}
<div
class=
"form-group"
>
<div
class=
"col-sm-4 col-sm-offset-2"
>
<button
class=
"btn btn-white"
type=
"reset"
>
{% trans '
Cancel
' %}
</button>
<button
class=
"btn btn-white"
type=
"reset"
>
{% trans '
Reset
' %}
</button>
<button
id=
"submit_button"
class=
"btn btn-primary"
type=
"submit"
>
{% trans 'Confirm' %}
</button>
</div>
</div>
...
...
apps/users/templates/users/user_group_granted_asset.html
View file @
673ebbec
...
...
@@ -34,7 +34,7 @@
{% block custom_foot_js %}
<script>
var
assetTableUrl
=
"{% url 'api-perms:user-group-assets' pk=object.id %}?cache_policy=1"
;
var
selectUrl
=
'{% url "api-perms:user-group-node-assets" pk=object.id node_id=DEFAULT_PK %}?
&
cache_policy=1&all=1'
;
var
selectUrl
=
'{% url "api-perms:user-group-node-assets" pk=object.id node_id=DEFAULT_PK %}?cache_policy=1&all=1'
;
var
treeUrl
=
"{% url 'api-perms:user-group-nodes-children-as-tree' pk=object.id %}?cache_policy=1"
;
var
systemUsersUrl
=
"{% url 'api-perms:user-group-asset-system-users' pk=object.id asset_id=DEFAULT_PK %}?cache_policy=1"
;
var
showAssetHref
=
true
;
// Need input default true
...
...
apps/users/utils.py
View file @
673ebbec
...
...
@@ -325,3 +325,7 @@ def construct_user_email(username, email):
email
=
'{}@{}'
.
format
(
username
,
settings
.
EMAIL_SUFFIX
)
return
email
def
get_current_org_members
(
exclude
=
()):
from
orgs.utils
import
current_org
return
current_org
.
get_org_members
(
exclude
=
exclude
)
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