Commit f3dc9b88 authored by BaiJiangJie's avatar BaiJiangJie Committed by 老广

Asset favor (#3352)

* [Update] 拆分filter org

* [Update] 修改session支持protocol搜索

* [Bugfix] 修复判断问题

* [Update] 支持收藏资产

* [update] 修改org resource queryset

* [Update] 修改form serializer 对应的多对多字段

* [Bugfix] 修复其他组织取消收藏的bug

* [Update] 去掉debug信息

* [Update] 修改remote app get queryset

* [Update] 修改remote app get queryset

* [Update] 修改没有授权时显示情况

* [Bugfix] 修复组织管理员查看用户权限失败问题

* [Update] 优化forms assets queryset设置
parent ccdb7709
# coding: utf-8 # coding: utf-8
# #
from rest_framework import generics
from orgs.mixins.api import OrgBulkModelViewSet from orgs.mixins.api import OrgBulkModelViewSet
from orgs.mixins import generics
from ..hands import IsOrgAdmin, IsAppUser from ..hands import IsOrgAdmin, IsAppUser
from ..models import RemoteApp from ..models import RemoteApp
from ..serializers import RemoteAppSerializer, RemoteAppConnectionInfoSerializer from ..serializers import RemoteAppSerializer, RemoteAppConnectionInfoSerializer
...@@ -16,14 +14,14 @@ __all__ = [ ...@@ -16,14 +14,14 @@ __all__ = [
class RemoteAppViewSet(OrgBulkModelViewSet): class RemoteAppViewSet(OrgBulkModelViewSet):
model = RemoteApp
filter_fields = ('name',) filter_fields = ('name',)
search_fields = filter_fields search_fields = filter_fields
permission_classes = (IsOrgAdmin,) permission_classes = (IsOrgAdmin,)
queryset = RemoteApp.objects.all()
serializer_class = RemoteAppSerializer serializer_class = RemoteAppSerializer
class RemoteAppConnectionInfoApi(generics.RetrieveAPIView): class RemoteAppConnectionInfoApi(generics.RetrieveAPIView):
queryset = RemoteApp.objects.all() model = RemoteApp
permission_classes = (IsAppUser, ) permission_classes = (IsAppUser, )
serializer_class = RemoteAppConnectionInfoSerializer serializer_class = RemoteAppConnectionInfoSerializer
...@@ -7,3 +7,4 @@ from .domain import * ...@@ -7,3 +7,4 @@ from .domain import *
from .cmd_filter import * from .cmd_filter import *
from .asset_user import * from .asset_user import *
from .gathered_user import * from .gathered_user import *
from .favorite_asset import *
...@@ -15,11 +15,10 @@ ...@@ -15,11 +15,10 @@
from django.db import transaction from django.db import transaction
from django.shortcuts import get_object_or_404 from django.shortcuts import get_object_or_404
from rest_framework import generics
from rest_framework.response import Response from rest_framework.response import Response
from orgs.mixins.api import OrgBulkModelViewSet from orgs.mixins.api import OrgBulkModelViewSet
from orgs.mixins import generics
from common.mixins import CommonApiMixin
from common.utils import get_logger from common.utils import get_logger
from ..hands import IsOrgAdmin from ..hands import IsOrgAdmin
from ..models import AdminUser, Asset from ..models import AdminUser, Asset
...@@ -39,22 +38,21 @@ class AdminUserViewSet(OrgBulkModelViewSet): ...@@ -39,22 +38,21 @@ class AdminUserViewSet(OrgBulkModelViewSet):
""" """
Admin user api set, for add,delete,update,list,retrieve resource Admin user api set, for add,delete,update,list,retrieve resource
""" """
model = AdminUser
filter_fields = ("name", "username") filter_fields = ("name", "username")
search_fields = filter_fields search_fields = filter_fields
queryset = AdminUser.objects.all()
serializer_class = serializers.AdminUserSerializer serializer_class = serializers.AdminUserSerializer
permission_classes = (IsOrgAdmin,) permission_classes = (IsOrgAdmin,)
class AdminUserAuthApi(generics.UpdateAPIView): class AdminUserAuthApi(generics.UpdateAPIView):
queryset = AdminUser.objects.all() model = AdminUser
serializer_class = serializers.AdminUserAuthSerializer serializer_class = serializers.AdminUserAuthSerializer
permission_classes = (IsOrgAdmin,) permission_classes = (IsOrgAdmin,)
class ReplaceNodesAdminUserApi(generics.UpdateAPIView): class ReplaceNodesAdminUserApi(generics.UpdateAPIView):
queryset = AdminUser.objects.all() model = AdminUser
serializer_class = serializers.ReplaceNodeAdminUserSerializer serializer_class = serializers.ReplaceNodeAdminUserSerializer
permission_classes = (IsOrgAdmin,) permission_classes = (IsOrgAdmin,)
...@@ -79,7 +77,7 @@ class AdminUserTestConnectiveApi(generics.RetrieveAPIView): ...@@ -79,7 +77,7 @@ class AdminUserTestConnectiveApi(generics.RetrieveAPIView):
""" """
Test asset admin user assets_connectivity Test asset admin user assets_connectivity
""" """
queryset = AdminUser.objects.all() model = AdminUser
permission_classes = (IsOrgAdmin,) permission_classes = (IsOrgAdmin,)
serializer_class = serializers.TaskIDSerializer serializer_class = serializers.TaskIDSerializer
......
...@@ -3,14 +3,14 @@ ...@@ -3,14 +3,14 @@
import random import random
from rest_framework import generics
from rest_framework.response import Response from rest_framework.response import Response
from django.shortcuts import get_object_or_404 from django.shortcuts import get_object_or_404
from common.utils import get_logger, get_object_or_none from common.utils import get_logger, get_object_or_none
from common.permissions import IsOrgAdmin, IsOrgAdminOrAppUser from common.permissions import IsOrgAdmin, IsOrgAdminOrAppUser
from orgs.mixins.api import OrgBulkModelViewSet 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 .. import serializers
from ..tasks import update_asset_hardware_info_manual, \ from ..tasks import update_asset_hardware_info_manual, \
test_asset_connectivity_manual test_asset_connectivity_manual
...@@ -29,10 +29,10 @@ class AssetViewSet(OrgBulkModelViewSet): ...@@ -29,10 +29,10 @@ class AssetViewSet(OrgBulkModelViewSet):
""" """
API endpoint that allows Asset to be viewed or edited. API endpoint that allows Asset to be viewed or edited.
""" """
model = Asset
filter_fields = ("hostname", "ip", "systemuser__id", "admin_user__id") filter_fields = ("hostname", "ip", "systemuser__id", "admin_user__id")
search_fields = ("hostname", "ip") search_fields = ("hostname", "ip")
ordering_fields = ("hostname", "ip", "port", "cpu_cores") ordering_fields = ("hostname", "ip", "port", "cpu_cores")
queryset = Asset.objects.all()
serializer_class = serializers.AssetSerializer serializer_class = serializers.AssetSerializer
permission_classes = (IsOrgAdminOrAppUser,) permission_classes = (IsOrgAdminOrAppUser,)
extra_filter_backends = [AssetByNodeFilterBackend, LabelFilterBackend] extra_filter_backends = [AssetByNodeFilterBackend, LabelFilterBackend]
...@@ -57,7 +57,7 @@ class AssetRefreshHardwareApi(generics.RetrieveAPIView): ...@@ -57,7 +57,7 @@ class AssetRefreshHardwareApi(generics.RetrieveAPIView):
""" """
Refresh asset hardware info Refresh asset hardware info
""" """
queryset = Asset.objects.all() model = Asset
serializer_class = serializers.AssetSerializer serializer_class = serializers.AssetSerializer
permission_classes = (IsOrgAdmin,) permission_classes = (IsOrgAdmin,)
...@@ -72,7 +72,7 @@ class AssetAdminUserTestApi(generics.RetrieveAPIView): ...@@ -72,7 +72,7 @@ class AssetAdminUserTestApi(generics.RetrieveAPIView):
""" """
Test asset admin user assets_connectivity Test asset admin user assets_connectivity
""" """
queryset = Asset.objects.all() model = Asset
permission_classes = (IsOrgAdmin,) permission_classes = (IsOrgAdmin,)
serializer_class = serializers.TaskIDSerializer serializer_class = serializers.TaskIDSerializer
...@@ -84,9 +84,9 @@ class AssetAdminUserTestApi(generics.RetrieveAPIView): ...@@ -84,9 +84,9 @@ class AssetAdminUserTestApi(generics.RetrieveAPIView):
class AssetGatewayApi(generics.RetrieveAPIView): class AssetGatewayApi(generics.RetrieveAPIView):
queryset = Asset.objects.all()
permission_classes = (IsOrgAdminOrAppUser,) permission_classes = (IsOrgAdminOrAppUser,)
serializer_class = serializers.GatewayWithAuthSerializer serializer_class = serializers.GatewayWithAuthSerializer
model = Asset
def retrieve(self, request, *args, **kwargs): def retrieve(self, request, *args, **kwargs):
asset_id = kwargs.get('pk') asset_id = kwargs.get('pk')
......
...@@ -13,14 +13,15 @@ __all__ = ['CommandFilterViewSet', 'CommandFilterRuleViewSet'] ...@@ -13,14 +13,15 @@ __all__ = ['CommandFilterViewSet', 'CommandFilterRuleViewSet']
class CommandFilterViewSet(OrgBulkModelViewSet): class CommandFilterViewSet(OrgBulkModelViewSet):
model = CommandFilter
filter_fields = ("name",) filter_fields = ("name",)
search_fields = filter_fields search_fields = filter_fields
permission_classes = (IsOrgAdmin,) permission_classes = (IsOrgAdmin,)
queryset = CommandFilter.objects.all()
serializer_class = serializers.CommandFilterSerializer serializer_class = serializers.CommandFilterSerializer
class CommandFilterRuleViewSet(OrgBulkModelViewSet): class CommandFilterRuleViewSet(OrgBulkModelViewSet):
model = CommandFilterRule
filter_fields = ("content",) filter_fields = ("content",)
search_fields = filter_fields search_fields = filter_fields
permission_classes = (IsOrgAdmin,) permission_classes = (IsOrgAdmin,)
......
...@@ -15,7 +15,7 @@ __all__ = ['DomainViewSet', 'GatewayViewSet', "GatewayTestConnectionApi"] ...@@ -15,7 +15,7 @@ __all__ = ['DomainViewSet', 'GatewayViewSet', "GatewayTestConnectionApi"]
class DomainViewSet(OrgBulkModelViewSet): class DomainViewSet(OrgBulkModelViewSet):
queryset = Domain.objects.all() model = Domain
permission_classes = (IsOrgAdminOrAppUser,) permission_classes = (IsOrgAdminOrAppUser,)
serializer_class = serializers.DomainSerializer serializer_class = serializers.DomainSerializer
...@@ -26,16 +26,15 @@ class DomainViewSet(OrgBulkModelViewSet): ...@@ -26,16 +26,15 @@ class DomainViewSet(OrgBulkModelViewSet):
class GatewayViewSet(OrgBulkModelViewSet): class GatewayViewSet(OrgBulkModelViewSet):
model = Gateway
filter_fields = ("domain__name", "name", "username", "ip", "domain") filter_fields = ("domain__name", "name", "username", "ip", "domain")
search_fields = filter_fields search_fields = filter_fields
queryset = Gateway.objects.all()
permission_classes = (IsOrgAdmin,) permission_classes = (IsOrgAdmin,)
serializer_class = serializers.GatewaySerializer serializer_class = serializers.GatewaySerializer
class GatewayTestConnectionApi(SingleObjectMixin, APIView): class GatewayTestConnectionApi(SingleObjectMixin, APIView):
permission_classes = (IsOrgAdmin,) permission_classes = (IsOrgAdmin,)
model = Gateway
object = None object = None
def post(self, request, *args, **kwargs): def post(self, request, *args, **kwargs):
......
# -*- 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
...@@ -13,12 +13,10 @@ __all__ = ['GatheredUserViewSet'] ...@@ -13,12 +13,10 @@ __all__ = ['GatheredUserViewSet']
class GatheredUserViewSet(OrgModelViewSet): class GatheredUserViewSet(OrgModelViewSet):
queryset = GatheredUser.objects.all() model = GatheredUser
serializer_class = GatheredUserSerializer serializer_class = GatheredUserSerializer
permission_classes = [IsOrgAdmin] permission_classes = [IsOrgAdmin]
extra_filter_backends = [AssetRelatedByNodeFilterBackend] extra_filter_backends = [AssetRelatedByNodeFilterBackend]
filter_fields = ['asset', 'username', 'present'] filter_fields = ['asset', 'username', 'present']
search_fields = ['username', 'asset__ip', 'asset__hostname'] search_fields = ['username', 'asset__ip', 'asset__hostname']
...@@ -27,6 +27,7 @@ __all__ = ['LabelViewSet'] ...@@ -27,6 +27,7 @@ __all__ = ['LabelViewSet']
class LabelViewSet(OrgBulkModelViewSet): class LabelViewSet(OrgBulkModelViewSet):
model = Label
filter_fields = ("name", "value") filter_fields = ("name", "value")
search_fields = filter_fields search_fields = filter_fields
permission_classes = (IsOrgAdmin,) permission_classes = (IsOrgAdmin,)
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
from rest_framework import generics, status from rest_framework import status
from rest_framework.serializers import ValidationError from rest_framework.serializers import ValidationError
from rest_framework.views import APIView from rest_framework.views import APIView
from rest_framework.response import Response from rest_framework.response import Response
...@@ -23,9 +23,12 @@ from django.shortcuts import get_object_or_404 ...@@ -23,9 +23,12 @@ from django.shortcuts import get_object_or_404
from common.utils import get_logger, get_object_or_none from common.utils import get_logger, get_object_or_none
from common.tree import TreeNodeSerializer from common.tree import TreeNodeSerializer
from orgs.mixins.api import OrgModelViewSet from orgs.mixins.api import OrgModelViewSet
from orgs.mixins import generics
from ..hands import IsOrgAdmin from ..hands import IsOrgAdmin
from ..models import Node 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 from .. import serializers
...@@ -40,9 +43,9 @@ __all__ = [ ...@@ -40,9 +43,9 @@ __all__ = [
class NodeViewSet(OrgModelViewSet): class NodeViewSet(OrgModelViewSet):
model = Node
filter_fields = ('value', 'key', 'id') filter_fields = ('value', 'key', 'id')
search_fields = ('value', ) search_fields = ('value', )
queryset = Node.objects.all()
permission_classes = (IsOrgAdmin,) permission_classes = (IsOrgAdmin,)
serializer_class = serializers.NodeSerializer serializer_class = serializers.NodeSerializer
...@@ -79,6 +82,7 @@ class NodeListAsTreeApi(generics.ListAPIView): ...@@ -79,6 +82,7 @@ class NodeListAsTreeApi(generics.ListAPIView):
} }
] ]
""" """
model = Node
permission_classes = (IsOrgAdmin,) permission_classes = (IsOrgAdmin,)
serializer_class = TreeNodeSerializer serializer_class = TreeNodeSerializer
...@@ -87,10 +91,6 @@ class NodeListAsTreeApi(generics.ListAPIView): ...@@ -87,10 +91,6 @@ class NodeListAsTreeApi(generics.ListAPIView):
queryset = [node.as_tree_node() for node in queryset] queryset = [node.as_tree_node() for node in queryset]
return queryset return queryset
def get_queryset(self):
queryset = Node.objects.all()
return queryset
def filter_queryset(self, queryset): def filter_queryset(self, queryset):
queryset = super().filter_queryset(queryset) queryset = super().filter_queryset(queryset)
queryset = self.to_tree_queryset(queryset) queryset = self.to_tree_queryset(queryset)
...@@ -98,7 +98,6 @@ class NodeListAsTreeApi(generics.ListAPIView): ...@@ -98,7 +98,6 @@ class NodeListAsTreeApi(generics.ListAPIView):
class NodeChildrenApi(generics.ListCreateAPIView): class NodeChildrenApi(generics.ListCreateAPIView):
queryset = Node.objects.all()
permission_classes = (IsOrgAdmin,) permission_classes = (IsOrgAdmin,)
serializer_class = serializers.NodeSerializer serializer_class = serializers.NodeSerializer
instance = None instance = None
...@@ -162,6 +161,7 @@ class NodeChildrenAsTreeApi(NodeChildrenApi): ...@@ -162,6 +161,7 @@ class NodeChildrenAsTreeApi(NodeChildrenApi):
] ]
""" """
model = Node
serializer_class = TreeNodeSerializer serializer_class = TreeNodeSerializer
http_method_names = ['get'] http_method_names = ['get']
...@@ -204,7 +204,7 @@ class NodeAssetsApi(generics.ListAPIView): ...@@ -204,7 +204,7 @@ class NodeAssetsApi(generics.ListAPIView):
class NodeAddChildrenApi(generics.UpdateAPIView): class NodeAddChildrenApi(generics.UpdateAPIView):
queryset = Node.objects.all() model = Node
permission_classes = (IsOrgAdmin,) permission_classes = (IsOrgAdmin,)
serializer_class = serializers.NodeAddChildrenSerializer serializer_class = serializers.NodeAddChildrenSerializer
instance = None instance = None
...@@ -221,8 +221,8 @@ class NodeAddChildrenApi(generics.UpdateAPIView): ...@@ -221,8 +221,8 @@ class NodeAddChildrenApi(generics.UpdateAPIView):
class NodeAddAssetsApi(generics.UpdateAPIView): class NodeAddAssetsApi(generics.UpdateAPIView):
model = Node
serializer_class = serializers.NodeAssetsSerializer serializer_class = serializers.NodeAssetsSerializer
queryset = Node.objects.all()
permission_classes = (IsOrgAdmin,) permission_classes = (IsOrgAdmin,)
instance = None instance = None
...@@ -233,8 +233,8 @@ class NodeAddAssetsApi(generics.UpdateAPIView): ...@@ -233,8 +233,8 @@ class NodeAddAssetsApi(generics.UpdateAPIView):
class NodeRemoveAssetsApi(generics.UpdateAPIView): class NodeRemoveAssetsApi(generics.UpdateAPIView):
model = Node
serializer_class = serializers.NodeAssetsSerializer serializer_class = serializers.NodeAssetsSerializer
queryset = Node.objects.all()
permission_classes = (IsOrgAdmin,) permission_classes = (IsOrgAdmin,)
instance = None instance = None
...@@ -249,8 +249,8 @@ class NodeRemoveAssetsApi(generics.UpdateAPIView): ...@@ -249,8 +249,8 @@ class NodeRemoveAssetsApi(generics.UpdateAPIView):
class NodeReplaceAssetsApi(generics.UpdateAPIView): class NodeReplaceAssetsApi(generics.UpdateAPIView):
model = Node
serializer_class = serializers.NodeAssetsSerializer serializer_class = serializers.NodeAssetsSerializer
queryset = Node.objects.all()
permission_classes = (IsOrgAdmin,) permission_classes = (IsOrgAdmin,)
instance = None instance = None
...@@ -262,8 +262,8 @@ class NodeReplaceAssetsApi(generics.UpdateAPIView): ...@@ -262,8 +262,8 @@ class NodeReplaceAssetsApi(generics.UpdateAPIView):
class RefreshNodeHardwareInfoApi(APIView): class RefreshNodeHardwareInfoApi(APIView):
permission_classes = (IsOrgAdmin,)
model = Node model = Node
permission_classes = (IsOrgAdmin,)
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):
node_id = kwargs.get('pk') node_id = kwargs.get('pk')
......
...@@ -14,13 +14,13 @@ ...@@ -14,13 +14,13 @@
# limitations under the License. # limitations under the License.
from django.shortcuts import get_object_or_404 from django.shortcuts import get_object_or_404
from rest_framework import generics
from rest_framework.response import Response from rest_framework.response import Response
from common.serializers import CeleryTaskSerializer from common.serializers import CeleryTaskSerializer
from common.utils import get_logger from common.utils import get_logger
from common.permissions import IsOrgAdmin, IsOrgAdminOrAppUser from common.permissions import IsOrgAdmin, IsOrgAdminOrAppUser
from orgs.mixins.api import OrgBulkModelViewSet from orgs.mixins.api import OrgBulkModelViewSet
from orgs.mixins import generics
from ..models import SystemUser, Asset from ..models import SystemUser, Asset
from .. import serializers from .. import serializers
from ..tasks import ( from ..tasks import (
...@@ -43,22 +43,18 @@ class SystemUserViewSet(OrgBulkModelViewSet): ...@@ -43,22 +43,18 @@ class SystemUserViewSet(OrgBulkModelViewSet):
""" """
System user api set, for add,delete,update,list,retrieve resource System user api set, for add,delete,update,list,retrieve resource
""" """
model = SystemUser
filter_fields = ("name", "username") filter_fields = ("name", "username")
search_fields = filter_fields search_fields = filter_fields
queryset = SystemUser.objects.all()
serializer_class = serializers.SystemUserSerializer serializer_class = serializers.SystemUserSerializer
permission_classes = (IsOrgAdminOrAppUser,) permission_classes = (IsOrgAdminOrAppUser,)
def get_queryset(self):
queryset = super().get_queryset().all()
return queryset
class SystemUserAuthInfoApi(generics.RetrieveUpdateDestroyAPIView): class SystemUserAuthInfoApi(generics.RetrieveUpdateDestroyAPIView):
""" """
Get system user auth info Get system user auth info
""" """
queryset = SystemUser.objects.all() model = SystemUser
permission_classes = (IsOrgAdminOrAppUser,) permission_classes = (IsOrgAdminOrAppUser,)
serializer_class = serializers.SystemUserAuthSerializer serializer_class = serializers.SystemUserAuthSerializer
...@@ -72,7 +68,7 @@ class SystemUserAssetAuthInfoApi(generics.RetrieveAPIView): ...@@ -72,7 +68,7 @@ class SystemUserAssetAuthInfoApi(generics.RetrieveAPIView):
""" """
Get system user with asset auth info Get system user with asset auth info
""" """
queryset = SystemUser.objects.all() model = SystemUser
permission_classes = (IsOrgAdminOrAppUser,) permission_classes = (IsOrgAdminOrAppUser,)
serializer_class = serializers.SystemUserAuthSerializer serializer_class = serializers.SystemUserAuthSerializer
...@@ -88,7 +84,7 @@ class SystemUserPushApi(generics.RetrieveAPIView): ...@@ -88,7 +84,7 @@ class SystemUserPushApi(generics.RetrieveAPIView):
""" """
Push system user to cluster assets api Push system user to cluster assets api
""" """
queryset = SystemUser.objects.all() model = SystemUser
permission_classes = (IsOrgAdmin,) permission_classes = (IsOrgAdmin,)
serializer_class = CeleryTaskSerializer serializer_class = CeleryTaskSerializer
...@@ -105,7 +101,7 @@ class SystemUserTestConnectiveApi(generics.RetrieveAPIView): ...@@ -105,7 +101,7 @@ class SystemUserTestConnectiveApi(generics.RetrieveAPIView):
""" """
Push system user to cluster assets api Push system user to cluster assets api
""" """
queryset = SystemUser.objects.all() model = SystemUser
permission_classes = (IsOrgAdmin,) permission_classes = (IsOrgAdmin,)
serializer_class = CeleryTaskSerializer serializer_class = CeleryTaskSerializer
...@@ -132,7 +128,7 @@ class SystemUserAssetsListView(generics.ListAPIView): ...@@ -132,7 +128,7 @@ class SystemUserAssetsListView(generics.ListAPIView):
class SystemUserPushToAssetApi(generics.RetrieveAPIView): class SystemUserPushToAssetApi(generics.RetrieveAPIView):
queryset = SystemUser.objects.all() model = SystemUser
permission_classes = (IsOrgAdmin,) permission_classes = (IsOrgAdmin,)
serializer_class = serializers.TaskIDSerializer serializer_class = serializers.TaskIDSerializer
...@@ -145,7 +141,7 @@ class SystemUserPushToAssetApi(generics.RetrieveAPIView): ...@@ -145,7 +141,7 @@ class SystemUserPushToAssetApi(generics.RetrieveAPIView):
class SystemUserTestAssetConnectivityApi(generics.RetrieveAPIView): class SystemUserTestAssetConnectivityApi(generics.RetrieveAPIView):
queryset = SystemUser.objects.all() model = SystemUser
permission_classes = (IsOrgAdmin,) permission_classes = (IsOrgAdmin,)
serializer_class = serializers.TaskIDSerializer serializer_class = serializers.TaskIDSerializer
......
...@@ -129,7 +129,7 @@ class AssetUpdateForm(OrgModelForm): ...@@ -129,7 +129,7 @@ class AssetUpdateForm(OrgModelForm):
class AssetBulkUpdateForm(OrgModelForm): class AssetBulkUpdateForm(OrgModelForm):
assets = forms.ModelMultipleChoiceField( assets = forms.ModelMultipleChoiceField(
required=True, required=True,
label=_('Select assets'), queryset=Asset.objects.all(), label=_('Select assets'), queryset=Asset.objects,
widget=forms.SelectMultiple( widget=forms.SelectMultiple(
attrs={ attrs={
'class': 'select2', 'class': 'select2',
...@@ -155,11 +155,18 @@ class AssetBulkUpdateForm(OrgModelForm): ...@@ -155,11 +155,18 @@ class AssetBulkUpdateForm(OrgModelForm):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
self.set_fields_queryset()
# 重写其他字段为不再required # 重写其他字段为不再required
for name, field in self.fields.items(): for name, field in self.fields.items():
if name != 'assets': if name != 'assets':
field.required = False 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): def save(self, commit=True):
changed_fields = [] changed_fields = []
for field in self._meta.fields: for field in self._meta.fields:
......
...@@ -12,7 +12,7 @@ __all__ = ['DomainForm', 'GatewayForm'] ...@@ -12,7 +12,7 @@ __all__ = ['DomainForm', 'GatewayForm']
class DomainForm(forms.ModelForm): class DomainForm(forms.ModelForm):
assets = forms.ModelMultipleChoiceField( assets = forms.ModelMultipleChoiceField(
queryset=Asset.objects.all(), label=_('Asset'), required=False, queryset=Asset.objects, label=_('Asset'), required=False,
widget=forms.SelectMultiple( widget=forms.SelectMultiple(
attrs={'class': 'select2', 'data-placeholder': _('Select assets')} attrs={'class': 'select2', 'data-placeholder': _('Select assets')}
) )
...@@ -23,19 +23,23 @@ class DomainForm(forms.ModelForm): ...@@ -23,19 +23,23 @@ class DomainForm(forms.ModelForm):
fields = ['name', 'comment', 'assets'] fields = ['name', 'comment', 'assets']
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
if kwargs.get('instance', None):
initial = kwargs.get('initial', {})
initial['assets'] = kwargs['instance'].assets.all()
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
self.set_fields_queryset()
# 前端渲染优化, 防止过多资产 def set_fields_queryset(self):
assets_field = self.fields.get('assets') assets_field = self.fields.get('assets')
# 没有data代表是渲染表单, 有data代表是提交创建/更新表单
if not self.data: if not self.data:
instance = kwargs.get('instance') # 有instance 代表渲染更新表单, 否则是创建表单
if instance: # 前端渲染优化, 防止过多资产, 设置assets queryset为none
assets_field.queryset = instance.assets.all() if self.instance:
assets_field.initial = self.instance.assets.all()
assets_field.queryset = self.instance.assets.all()
else: else:
assets_field.queryset = Asset.objects.none() assets_field.queryset = Asset.objects.none()
else:
assets_field.queryset = Asset.objects.all()
def save(self, commit=True): def save(self, commit=True):
instance = super().save(commit=commit) instance = super().save(commit=commit)
......
...@@ -10,7 +10,7 @@ __all__ = ['LabelForm'] ...@@ -10,7 +10,7 @@ __all__ = ['LabelForm']
class LabelForm(forms.ModelForm): class LabelForm(forms.ModelForm):
assets = forms.ModelMultipleChoiceField( assets = forms.ModelMultipleChoiceField(
queryset=Asset.objects.all(), label=_('Asset'), required=False, queryset=Asset.objects.none(), label=_('Asset'), required=False,
widget=forms.SelectMultiple( widget=forms.SelectMultiple(
attrs={'class': 'select2', 'data-placeholder': _('Select assets')} attrs={'class': 'select2', 'data-placeholder': _('Select assets')}
) )
...@@ -21,19 +21,23 @@ class LabelForm(forms.ModelForm): ...@@ -21,19 +21,23 @@ class LabelForm(forms.ModelForm):
fields = ['name', 'value', 'assets'] fields = ['name', 'value', 'assets']
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
if kwargs.get('instance', None):
initial = kwargs.get('initial', {})
initial['assets'] = kwargs['instance'].assets.all()
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
self.set_fields_queryset()
# 前端渲染优化, 防止过多资产 def set_fields_queryset(self):
assets_field = self.fields.get('assets') assets_field = self.fields.get('assets')
# 没有data代表是渲染表单, 有data代表是提交创建/更新表单
if not self.data: if not self.data:
instance = kwargs.get('instance') # 有instance 代表渲染更新表单, 否则是创建表单
if instance: # 前端渲染优化, 防止过多资产, 设置assets queryset为none
assets_field.queryset = instance.assets.all() if self.instance:
assets_field.initial = self.instance.assets.all()
assets_field.queryset = self.instance.assets.all()
else: else:
assets_field.queryset = Asset.objects.none() assets_field.queryset = Asset.objects.none()
else:
assets_field.queryset = Asset.objects.all()
def save(self, commit=True): def save(self, commit=True):
label = super().save(commit=commit) label = super().save(commit=commit)
......
# 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')},
},
),
]
...@@ -10,3 +10,4 @@ from .authbook import * ...@@ -10,3 +10,4 @@ from .authbook import *
from .utils import * from .utils import *
from .authbook import * from .authbook import *
from .gathered_user import * from .gathered_user import *
from .favorite_asset import *
# -*- 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)
...@@ -324,6 +324,8 @@ class SomeNodesMixin: ...@@ -324,6 +324,8 @@ class SomeNodesMixin:
ungrouped_value = _('ungrouped') ungrouped_value = _('ungrouped')
empty_key = '-11' empty_key = '-11'
empty_value = _("empty") empty_value = _("empty")
favorite_key = '-12'
favorite_value = _("favorite")
def is_default_node(self): def is_default_node(self):
return self.key == self.default_key return self.key == self.default_key
...@@ -363,7 +365,7 @@ class SomeNodesMixin: ...@@ -363,7 +365,7 @@ class SomeNodesMixin:
@classmethod @classmethod
def ungrouped_node(cls): def ungrouped_node(cls):
with tmp_to_org(Organization.system()): with tmp_to_org(Organization.system()):
defaults = {'value': cls.ungrouped_key} defaults = {'value': cls.ungrouped_value}
obj, created = cls.objects.get_or_create( obj, created = cls.objects.get_or_create(
defaults=defaults, key=cls.ungrouped_key defaults=defaults, key=cls.ungrouped_key
) )
...@@ -387,11 +389,21 @@ class SomeNodesMixin: ...@@ -387,11 +389,21 @@ class SomeNodesMixin:
) )
return obj 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 @classmethod
def initial_some_nodes(cls): def initial_some_nodes(cls):
cls.default_node() cls.default_node()
cls.empty_node() cls.empty_node()
cls.ungrouped_node() cls.ungrouped_node()
cls.favorite_node()
class Node(OrgModelMixin, SomeNodesMixin, TreeMixin, FamilyMixin, FullValueMixin, NodeAssetsMixin): class Node(OrgModelMixin, SomeNodesMixin, TreeMixin, FamilyMixin, FullValueMixin, NodeAssetsMixin):
...@@ -412,11 +424,11 @@ class Node(OrgModelMixin, SomeNodesMixin, TreeMixin, FamilyMixin, FullValueMixin ...@@ -412,11 +424,11 @@ class Node(OrgModelMixin, SomeNodesMixin, TreeMixin, FamilyMixin, FullValueMixin
def __str__(self): def __str__(self):
return self.value return self.value
def __eq__(self, other): # def __eq__(self, other):
if not other: # if not other:
return False # return False
return self.id == other.id # return self.id == other.id
#
def __gt__(self, other): def __gt__(self, other):
self_key = [int(k) for k in self.key.split(':')] self_key = [int(k) for k in self.key.split(':')]
other_key = [int(k) for k in other.key.split(':')] other_key = [int(k) for k in other.key.split(':')]
......
...@@ -10,3 +10,4 @@ from .domain import * ...@@ -10,3 +10,4 @@ from .domain import *
from .cmd_filter import * from .cmd_filter import *
from .asset_user import * from .asset_user import *
from .gathered_user import * from .gathered_user import *
from .favorite_asset import *
...@@ -45,7 +45,7 @@ class ReplaceNodeAdminUserSerializer(serializers.ModelSerializer): ...@@ -45,7 +45,7 @@ class ReplaceNodeAdminUserSerializer(serializers.ModelSerializer):
管理用户更新关联到的集群 管理用户更新关联到的集群
""" """
nodes = serializers.PrimaryKeyRelatedField( nodes = serializers.PrimaryKeyRelatedField(
many=True, queryset=Node.objects.all() many=True, queryset=Node.objects
) )
class Meta: class Meta:
......
...@@ -79,7 +79,7 @@ class AssetUserAuthInfoSerializer(serializers.ModelSerializer): ...@@ -79,7 +79,7 @@ class AssetUserAuthInfoSerializer(serializers.ModelSerializer):
class AssetUserPushSerializer(serializers.Serializer): 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) username = serializers.CharField(max_length=1024)
def create(self, validated_data): def create(self, validated_data):
......
# -*- 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']
...@@ -38,8 +38,10 @@ class NodeSerializer(BulkOrgResourceModelSerializer): ...@@ -38,8 +38,10 @@ class NodeSerializer(BulkOrgResourceModelSerializer):
return data return data
class NodeAssetsSerializer(serializers.ModelSerializer): class NodeAssetsSerializer(BulkOrgResourceModelSerializer):
assets = serializers.PrimaryKeyRelatedField(many=True, queryset=Asset.objects.all()) assets = serializers.PrimaryKeyRelatedField(
many=True, queryset=Asset.objects
)
class Meta: class Meta:
model = Node model = Node
......
...@@ -25,12 +25,20 @@ ...@@ -25,12 +25,20 @@
</div> </div>
</div> </div>
</form> </form>
{% include 'assets/_asset_list_modal.html' %}
{% endblock %} {% endblock %}
{% block custom_foot_js %} {% block custom_foot_js %}
<script> <script>
$(document).ready(function () { $(document).ready(function () {
$('.select2').select2(); $('.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() { }).on('click', '.field-tag', function() {
changeField(this); changeField(this);
}).on('click', '#change_all', function () { }).on('click', '#change_all', function () {
......
...@@ -21,19 +21,46 @@ ...@@ -21,19 +21,46 @@
{% block custom_foot_js %} {% block custom_foot_js %}
<script> <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 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 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 systemUsersUrl = "{% url 'api-perms:my-asset-system-users' asset_id=DEFAULT_PK %}?cache_policy=1";
var showAssetHref = false; // Need input default true 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 = { var actions = {
targets: 4, createdCell: function (td, cellData) { targets: 4, createdCell: function (td, cellData) {
var conn_btn = '<a href="{% url "luna-view" %}?login_to=' + cellData + var connBtn = '<a href="{% url "luna-view" %}?login_to=' + cellData +
'" class="btn btn-xs btn-primary" target="_blank">{% trans "Connect" %}</a>'; '" class="btn btn-xs btn-primary" target="_blank"><i class="fa fa-terminal"></i></a> ';
$(td).html(conn_btn) 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 () { $(document).ready(function () {
requestApi({
method: "GET",
url: "{% url 'api-assets:favorite-asset-list' %}",
success: function (data) {
favoriteAssets = data.map(function (i) {
return i.asset;
});
initTree(); initTree();
},
error: function () {
initTree();
},
flash_message: false
})
}).on('click', '.labels li', function () { }).on('click', '.labels li', function () {
var val = $(this).text(); var val = $(this).text();
$("#user_assets_table_filter input").val(val); $("#user_assets_table_filter input").val(val);
...@@ -67,22 +94,33 @@ $(document).ready(function () { ...@@ -67,22 +94,33 @@ $(document).ready(function () {
}; };
$('#asset_detail_tbody').html(trs) $('#asset_detail_tbody').html(trs)
$('#user_asset_detail_modal').modal(); $('#user_asset_detail_modal').modal();
}); })
.on('click', '.btn-favor', function () {
function toggle() { var $this = $(this);
if (show === 0) { var assetId = $(this).data("id");
$("#split-left").hide(500, function () { requestApi({
$("#split-right").attr("class", "col-lg-12"); url: "{% url 'api-assets:favorite-asset-list' %}",
$("#toggle-icon").attr("class", "fa fa-angle-right fa-x"); method: "POST",
show = 1; body: JSON.stringify({asset: assetId}),
flash_message: false,
success: function (data) {
var btn = disfavorBtnTmpl.replace("ID", assetId);
$this.replaceWith(btn)
}
}); });
} else { })
$("#split-right").attr("class", "col-lg-9"); .on('click', '.btn-disfavor', function () {
$("#toggle-icon").attr("class", "fa fa-angle-left fa-x"); var $this = $(this);
$("#split-left").show(500); var assetId = $(this).data("id");
show = 0; 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)
} }
} });
});
</script> </script>
{% endblock %} {% endblock %}
...@@ -22,6 +22,7 @@ router.register(r'cmd-filters', api.CommandFilterViewSet, 'cmd-filter') ...@@ -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', api.AssetUserViewSet, 'asset-user')
router.register(r'asset-users-info', api.AssetUserExportViewSet, 'asset-user-info') router.register(r'asset-users-info', api.AssetUserExportViewSet, 'asset-user-info')
router.register(r'gathered-users', api.GatheredUserViewSet, 'gathered-user') 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 = routers.NestedDefaultRouter(router, r'cmd-filters', lookup='filter')
cmd_filter_router.register(r'rules', api.CommandFilterRuleViewSet, 'cmd-filter-rule') cmd_filter_router.register(r'rules', api.CommandFilterRuleViewSet, 'cmd-filter-rule')
......
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# #
from rest_framework import viewsets
from common.permissions import IsOrgAdminOrAppUser, IsOrgAuditor from common.permissions import IsOrgAdminOrAppUser, IsOrgAuditor
from orgs.mixins.api import OrgModelViewSet
from .models import FTPLog from .models import FTPLog
from .serializers import FTPLogSerializer from .serializers import FTPLogSerializer
class FTPLogViewSet(viewsets.ModelViewSet): class FTPLogViewSet(OrgModelViewSet):
queryset = FTPLog.objects.all() model = FTPLog
serializer_class = FTPLogSerializer serializer_class = FTPLogSerializer
permission_classes = (IsOrgAdminOrAppUser | IsOrgAuditor,) permission_classes = (IsOrgAdminOrAppUser | IsOrgAuditor,)
...@@ -83,8 +83,6 @@ class LogTailApi(generics.RetrieveAPIView): ...@@ -83,8 +83,6 @@ class LogTailApi(generics.RetrieveAPIView):
return Response({"data": data, 'end': end, 'mark': new_mark}) return Response({"data": data, 'end': end, 'mark': new_mark})
class ResourcesIDCacheApi(APIView): class ResourcesIDCacheApi(APIView):
def post(self, request, *args, **kwargs): def post(self, request, *args, **kwargs):
spm = str(uuid.uuid4()) spm = str(uuid.uuid4())
......
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# #
import uuid
from django.db import models from django.db import models
from django.utils import timezone from django.utils import timezone
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
__all__ = ["NoDeleteManager", "NoDeleteModelMixin", "NoDeleteQuerySet"] __all__ = [
"NoDeleteManager", "NoDeleteModelMixin", "NoDeleteQuerySet",
"CommonModelMixin"
]
class NoDeleteQuerySet(models.query.QuerySet): class NoDeleteQuerySet(models.query.QuerySet):
...@@ -40,3 +43,13 @@ class NoDeleteModelMixin(models.Model): ...@@ -40,3 +43,13 @@ class NoDeleteModelMixin(models.Model):
self.is_discard = True self.is_discard = True
self.discard_time = timezone.now() self.discard_time = timezone.now()
return self.save() 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
...@@ -36,7 +36,7 @@ def on_request_finished_logging_db_query(sender, **kwargs): ...@@ -36,7 +36,7 @@ def on_request_finished_logging_db_query(sender, **kwargs):
queries = connection.queries queries = connection.queries
counters = defaultdict(Counter) counters = defaultdict(Counter)
for query in queries: for query in queries:
if not query['sql'].startswith('SELECT'): if not query['sql'] or not query['sql'].startswith('SELECT'):
continue continue
tables = pattern.findall(query['sql']) tables = pattern.findall(query['sql'])
table_name = ''.join(tables) table_name = ''.join(tables)
......
...@@ -51,6 +51,8 @@ class TreeNode: ...@@ -51,6 +51,8 @@ class TreeNode:
result = True result = True
elif self.pId != other.pId: elif self.pId != other.pId:
result = self.pId > other.pId result = self.pId > other.pId
elif self.id.startswith('-') and not other.id.startswith('-'):
result = False
else: else:
result = self.name > other.name result = self.name > other.name
return result return result
......
This diff is collapsed.
...@@ -5,12 +5,12 @@ from rest_framework.viewsets import ModelViewSet ...@@ -5,12 +5,12 @@ from rest_framework.viewsets import ModelViewSet
from rest_framework_bulk import BulkModelViewSet from rest_framework_bulk import BulkModelViewSet
from common.mixins import CommonApiMixin from common.mixins import CommonApiMixin
from ..utils import set_to_root_org from ..utils import set_to_root_org, filter_org_queryset
from ..models import Organization from ..models import Organization
__all__ = [ __all__ = [
'RootOrgViewMixin', 'OrgMembershipModelViewSetMixin', 'OrgModelViewSet', 'RootOrgViewMixin', 'OrgMembershipModelViewSetMixin', 'OrgModelViewSet',
'OrgBulkModelViewSet', 'OrgBulkModelViewSet', 'OrgQuerySetMixin',
] ]
...@@ -22,7 +22,15 @@ class RootOrgViewMixin: ...@@ -22,7 +22,15 @@ class RootOrgViewMixin:
class OrgQuerySetMixin: class OrgQuerySetMixin:
def get_queryset(self): def get_queryset(self):
queryset = super().get_queryset().all() 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'): if hasattr(self, 'swagger_fake_view'):
return queryset[:1] return queryset[:1]
if hasattr(self, 'action') and self.action == 'list' and \ if hasattr(self, 'action') and self.action == 'list' and \
......
# -*- 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
...@@ -9,6 +9,7 @@ from django.core.exceptions import ValidationError ...@@ -9,6 +9,7 @@ from django.core.exceptions import ValidationError
from common.utils import get_logger from common.utils import get_logger
from ..utils import ( from ..utils import (
set_current_org, get_current_org, current_org, set_current_org, get_current_org, current_org,
get_org_filters
) )
from ..models import Organization from ..models import Organization
...@@ -19,41 +20,37 @@ __all__ = [ ...@@ -19,41 +20,37 @@ __all__ = [
] ]
class OrgManager(models.Manager): class OrgQuerySet(models.QuerySet):
pass
class OrgManager(models.Manager):
def get_queryset(self): def get_queryset(self):
queryset = super(OrgManager, self).get_queryset() queryset = super().get_queryset()
kwargs = {} kwargs = get_org_filters()
if kwargs:
_current_org = get_current_org() return queryset.filter(**kwargs)
if _current_org is None: return queryset
kwargs['id'] = None
elif _current_org.is_real(): def set_current_org(self, org):
kwargs['org_id'] = _current_org.id if isinstance(org, str):
elif _current_org.is_default(): org = Organization.get_instance(org)
queryset = queryset.filter(org_id="") set_current_org(org)
return self
def all(self):
# print("Call all: {}".format(current_org))
# #
# lines = traceback.format_stack() # lines = traceback.format_stack()
# print(">>>>>>>>>>>>>>>>>>>>>>>>>>>>") # print(">>>>>>>>>>>>>>>>>>>>>>>>>>>>")
# for line in lines[-10:-1]: # for line in lines[-10:-1]:
# print(line) # print(line)
# print("<<<<<<<<<<<<<<<<<<<<<<<<<<<<") # print("<<<<<<<<<<<<<<<<<<<<<<<<<<<<")
queryset = queryset.filter(**kwargs)
return queryset
def all(self):
if not current_org: if not current_org:
msg = 'You can `objects.set_current_org(org).all()` then run it' msg = 'You can `objects.set_current_org(org).all()` then run it'
return self return self
else: else:
return super(OrgManager, self).all() return super().all()
def set_current_org(self, org):
if isinstance(org, str):
org = Organization.get_instance(org)
set_current_org(org)
return self
class OrgModelMixin(models.Model): class OrgModelMixin(models.Model):
...@@ -65,9 +62,12 @@ class OrgModelMixin(models.Model): ...@@ -65,9 +62,12 @@ class OrgModelMixin(models.Model):
def save(self, *args, **kwargs): def save(self, *args, **kwargs):
org = get_current_org() 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 self.org_id = org.id
elif org is not None and org.is_default(): elif org.is_default():
self.org_id = '' self.org_id = ''
return super().save(*args, **kwargs) return super().save(*args, **kwargs)
......
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# #
import traceback
from werkzeug.local import LocalProxy from werkzeug.local import LocalProxy
from contextlib import contextmanager from contextlib import contextmanager
...@@ -82,4 +83,31 @@ def tmp_to_org(org): ...@@ -82,4 +83,31 @@ def tmp_to_org(org):
set_current_org(ori_org) set_current_org(ori_org)
def get_org_filters():
kwargs = {}
_current_org = get_current_org()
if _current_org is 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(">>>>>>>>>>>>>>>>>>>>>>>>>>>>")
# for line in lines[-10:-1]:
# print(line)
# print("<<<<<<<<<<<<<<<<<<<<<<<<<<<<")
queryset = queryset.filter(**kwargs)
return queryset
current_org = LocalProxy(get_current_org) current_org = LocalProxy(get_current_org)
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# #
from django.utils import timezone
from django.db.models import Q from django.db.models import Q
from rest_framework.views import Response from rest_framework.views import Response
from django.shortcuts import get_object_or_404 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 common.permissions import IsOrgAdmin
from orgs.mixins.api import OrgModelViewSet
from orgs.mixins import generics
from common.utils import get_object_or_none from common.utils import get_object_or_none
from ..models import AssetPermission from ..models import AssetPermission
from ..hands import ( from ..hands import (
...@@ -24,15 +23,21 @@ __all__ = [ ...@@ -24,15 +23,21 @@ __all__ = [
] ]
class AssetPermissionViewSet(viewsets.ModelViewSet): class AssetPermissionViewSet(OrgModelViewSet):
""" """
资产授权列表的增删改查api 资产授权列表的增删改查api
""" """
queryset = AssetPermission.objects.all() model = AssetPermission
serializer_class = serializers.AssetPermissionCreateUpdateSerializer serializer_class = serializers.AssetPermissionCreateUpdateSerializer
filter_fields = ['name'] filter_fields = ['name']
permission_classes = (IsOrgAdmin,) 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): def get_serializer_class(self):
if self.action in ("list", 'retrieve') and \ if self.action in ("list", 'retrieve') and \
self.request.query_params.get("display"): self.request.query_params.get("display"):
...@@ -160,19 +165,14 @@ class AssetPermissionViewSet(viewsets.ModelViewSet): ...@@ -160,19 +165,14 @@ class AssetPermissionViewSet(viewsets.ModelViewSet):
queryset = queryset.distinct() queryset = queryset.distinct()
return queryset 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页面会调用 将用户从授权中移除,Detail页面会调用
""" """
model = AssetPermission
permission_classes = (IsOrgAdmin,) permission_classes = (IsOrgAdmin,)
serializer_class = serializers.AssetPermissionUpdateUserSerializer serializer_class = serializers.AssetPermissionUpdateUserSerializer
queryset = AssetPermission.objects.all()
def update(self, request, *args, **kwargs): def update(self, request, *args, **kwargs):
perm = self.get_object() perm = self.get_object()
...@@ -187,10 +187,10 @@ class AssetPermissionRemoveUserApi(RetrieveUpdateAPIView): ...@@ -187,10 +187,10 @@ class AssetPermissionRemoveUserApi(RetrieveUpdateAPIView):
return Response({"error": serializer.errors}) return Response({"error": serializer.errors})
class AssetPermissionAddUserApi(RetrieveUpdateAPIView): class AssetPermissionAddUserApi(generics.RetrieveUpdateAPIView):
model = AssetPermission
permission_classes = (IsOrgAdmin,) permission_classes = (IsOrgAdmin,)
serializer_class = serializers.AssetPermissionUpdateUserSerializer serializer_class = serializers.AssetPermissionUpdateUserSerializer
queryset = AssetPermission.objects.all()
def update(self, request, *args, **kwargs): def update(self, request, *args, **kwargs):
perm = self.get_object() perm = self.get_object()
...@@ -205,13 +205,13 @@ class AssetPermissionAddUserApi(RetrieveUpdateAPIView): ...@@ -205,13 +205,13 @@ class AssetPermissionAddUserApi(RetrieveUpdateAPIView):
return Response({"error": serializer.errors}) return Response({"error": serializer.errors})
class AssetPermissionRemoveAssetApi(RetrieveUpdateAPIView): class AssetPermissionRemoveAssetApi(generics.RetrieveUpdateAPIView):
""" """
将用户从授权中移除,Detail页面会调用 将用户从授权中移除,Detail页面会调用
""" """
model = AssetPermission
permission_classes = (IsOrgAdmin,) permission_classes = (IsOrgAdmin,)
serializer_class = serializers.AssetPermissionUpdateAssetSerializer serializer_class = serializers.AssetPermissionUpdateAssetSerializer
queryset = AssetPermission.objects.all()
def update(self, request, *args, **kwargs): def update(self, request, *args, **kwargs):
perm = self.get_object() perm = self.get_object()
...@@ -226,10 +226,10 @@ class AssetPermissionRemoveAssetApi(RetrieveUpdateAPIView): ...@@ -226,10 +226,10 @@ class AssetPermissionRemoveAssetApi(RetrieveUpdateAPIView):
return Response({"error": serializer.errors}) return Response({"error": serializer.errors})
class AssetPermissionAddAssetApi(RetrieveUpdateAPIView): class AssetPermissionAddAssetApi(generics.RetrieveUpdateAPIView):
model = AssetPermission
permission_classes = (IsOrgAdmin,) permission_classes = (IsOrgAdmin,)
serializer_class = serializers.AssetPermissionUpdateAssetSerializer serializer_class = serializers.AssetPermissionUpdateAssetSerializer
queryset = AssetPermission.objects.all()
def update(self, request, *args, **kwargs): def update(self, request, *args, **kwargs):
perm = self.get_object() perm = self.get_object()
...@@ -244,7 +244,7 @@ class AssetPermissionAddAssetApi(RetrieveUpdateAPIView): ...@@ -244,7 +244,7 @@ class AssetPermissionAddAssetApi(RetrieveUpdateAPIView):
return Response({"error": serializer.errors}) return Response({"error": serializer.errors})
class AssetPermissionAssetsApi(ListAPIView): class AssetPermissionAssetsApi(generics.ListAPIView):
permission_classes = (IsOrgAdmin,) permission_classes = (IsOrgAdmin,)
serializer_class = serializers.AssetPermissionAssetsSerializer serializer_class = serializers.AssetPermissionAssetsSerializer
filter_fields = ("hostname", "ip") filter_fields = ("hostname", "ip")
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
from rest_framework.generics import get_object_or_404 from rest_framework.generics import get_object_or_404
from common.permissions import IsValidUser, IsOrgAdminOrAppUser from common.permissions import IsValidUser, IsOrgAdminOrAppUser
from common.utils import get_logger 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 from ..hands import User, UserGroup
...@@ -17,15 +17,24 @@ __all__ = [ ...@@ -17,15 +17,24 @@ __all__ = [
class UserPermissionMixin: class UserPermissionMixin:
permission_classes = (IsOrgAdminOrAppUser,) permission_classes = (IsOrgAdminOrAppUser,)
current_org = None
obj = None obj = None
def initial(self, *args, **kwargs): def initial(self, *args, **kwargs):
super().initial(*args, *kwargs) super().initial(*args, *kwargs)
self.current_org = get_current_org()
set_to_root_org()
self.obj = self.get_obj() self.obj = self.get_obj()
def get(self, request, *args, **kwargs): # def dispatch(self, request, *args, **kwargs):
set_to_root_org() # """不能这么做,校验权限时拿不到组织了"""
return super().get(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): def get_obj(self):
user_id = self.kwargs.get('pk', '') user_id = self.kwargs.get('pk', '')
...@@ -40,6 +49,13 @@ class UserPermissionMixin: ...@@ -40,6 +49,13 @@ class UserPermissionMixin:
self.permission_classes = (IsValidUser,) self.permission_classes = (IsValidUser,)
return super().get_permissions() 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: class UserGroupPermissionMixin:
obj = None obj = None
......
# coding: utf-8 # coding: utf-8
# #
from rest_framework import viewsets, generics
from rest_framework.views import Response from rest_framework.views import Response
from common.permissions import IsOrgAdmin from common.permissions import IsOrgAdmin
from orgs.mixins.api import OrgModelViewSet
from orgs.mixins import generics
from ..models import RemoteAppPermission from ..models import RemoteAppPermission
from ..serializers import ( from ..serializers import (
RemoteAppPermissionSerializer, RemoteAppPermissionSerializer,
...@@ -20,18 +21,18 @@ __all__ = [ ...@@ -20,18 +21,18 @@ __all__ = [
] ]
class RemoteAppPermissionViewSet(viewsets.ModelViewSet): class RemoteAppPermissionViewSet(OrgModelViewSet):
model = RemoteAppPermission
filter_fields = ('name', ) filter_fields = ('name', )
search_fields = filter_fields search_fields = filter_fields
queryset = RemoteAppPermission.objects.all()
serializer_class = RemoteAppPermissionSerializer serializer_class = RemoteAppPermissionSerializer
permission_classes = (IsOrgAdmin,) permission_classes = (IsOrgAdmin,)
class RemoteAppPermissionAddUserApi(generics.RetrieveUpdateAPIView): class RemoteAppPermissionAddUserApi(generics.RetrieveUpdateAPIView):
model = RemoteAppPermission
permission_classes = (IsOrgAdmin,) permission_classes = (IsOrgAdmin,)
serializer_class = RemoteAppPermissionUpdateUserSerializer serializer_class = RemoteAppPermissionUpdateUserSerializer
queryset = RemoteAppPermission.objects.all()
def update(self, request, *args, **kwargs): def update(self, request, *args, **kwargs):
perm = self.get_object() perm = self.get_object()
...@@ -46,9 +47,9 @@ class RemoteAppPermissionAddUserApi(generics.RetrieveUpdateAPIView): ...@@ -46,9 +47,9 @@ class RemoteAppPermissionAddUserApi(generics.RetrieveUpdateAPIView):
class RemoteAppPermissionRemoveUserApi(generics.RetrieveUpdateAPIView): class RemoteAppPermissionRemoveUserApi(generics.RetrieveUpdateAPIView):
model = RemoteAppPermission
permission_classes = (IsOrgAdmin,) permission_classes = (IsOrgAdmin,)
serializer_class = RemoteAppPermissionUpdateUserSerializer serializer_class = RemoteAppPermissionUpdateUserSerializer
queryset = RemoteAppPermission.objects.all()
def update(self, request, *args, **kwargs): def update(self, request, *args, **kwargs):
perm = self.get_object() perm = self.get_object()
...@@ -63,9 +64,9 @@ class RemoteAppPermissionRemoveUserApi(generics.RetrieveUpdateAPIView): ...@@ -63,9 +64,9 @@ class RemoteAppPermissionRemoveUserApi(generics.RetrieveUpdateAPIView):
class RemoteAppPermissionAddRemoteAppApi(generics.RetrieveUpdateAPIView): class RemoteAppPermissionAddRemoteAppApi(generics.RetrieveUpdateAPIView):
model = RemoteAppPermission
permission_classes = (IsOrgAdmin,) permission_classes = (IsOrgAdmin,)
serializer_class = RemoteAppPermissionUpdateRemoteAppSerializer serializer_class = RemoteAppPermissionUpdateRemoteAppSerializer
queryset = RemoteAppPermission.objects.all()
def update(self, request, *args, **kwargs): def update(self, request, *args, **kwargs):
perm = self.get_object() perm = self.get_object()
...@@ -80,9 +81,9 @@ class RemoteAppPermissionAddRemoteAppApi(generics.RetrieveUpdateAPIView): ...@@ -80,9 +81,9 @@ class RemoteAppPermissionAddRemoteAppApi(generics.RetrieveUpdateAPIView):
class RemoteAppPermissionRemoveRemoteAppApi(generics.RetrieveUpdateAPIView): class RemoteAppPermissionRemoveRemoteAppApi(generics.RetrieveUpdateAPIView):
model = RemoteAppPermission
permission_classes = (IsOrgAdmin,) permission_classes = (IsOrgAdmin,)
serializer_class = RemoteAppPermissionUpdateRemoteAppSerializer serializer_class = RemoteAppPermissionUpdateRemoteAppSerializer
queryset = RemoteAppPermission.objects.all()
def update(self, request, *args, **kwargs): def update(self, request, *args, **kwargs):
perm = self.get_object() perm = self.get_object()
......
...@@ -34,7 +34,7 @@ class UserNodeTreeMixin: ...@@ -34,7 +34,7 @@ class UserNodeTreeMixin:
for node in nodes: for node in nodes:
assets_amount = self.tree.valid_assets_amount(node.key) assets_amount = self.tree.valid_assets_amount(node.key)
if assets_amount == 0 and node.key != Node.empty_key: if assets_amount == 0 and not node.key.startswith('-'):
continue continue
node.assets_amount = assets_amount node.assets_amount = assets_amount
data = ParserNode.parse_node_to_tree_node(node) data = ParserNode.parse_node_to_tree_node(node)
......
...@@ -3,12 +3,10 @@ ...@@ -3,12 +3,10 @@
import uuid import uuid
from django.shortcuts import get_object_or_404 from django.shortcuts import get_object_or_404
from rest_framework.views import APIView, Response 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.permissions import IsValidUser, IsOrgAdminOrAppUser
from common.tree import TreeNodeSerializer from common.tree import TreeNodeSerializer
from orgs.mixins import generics
from ..utils import ( from ..utils import (
RemoteAppPermissionUtil, construct_remote_apps_tree_root, RemoteAppPermissionUtil, construct_remote_apps_tree_root,
parse_remote_app_to_tree_node, parse_remote_app_to_tree_node,
...@@ -25,7 +23,7 @@ __all__ = [ ...@@ -25,7 +23,7 @@ __all__ = [
] ]
class UserGrantedRemoteAppsApi(ListAPIView): class UserGrantedRemoteAppsApi(generics.ListAPIView):
permission_classes = (IsOrgAdminOrAppUser,) permission_classes = (IsOrgAdminOrAppUser,)
serializer_class = RemoteAppSerializer serializer_class = RemoteAppSerializer
filter_fields = ['name', 'id'] filter_fields = ['name', 'id']
...@@ -68,7 +66,7 @@ class UserGrantedRemoteAppsAsTreeApi(UserGrantedRemoteAppsApi): ...@@ -68,7 +66,7 @@ class UserGrantedRemoteAppsAsTreeApi(UserGrantedRemoteAppsApi):
return super().get_serializer(data, many=True) return super().get_serializer(data, many=True)
class UserGrantedRemoteAppSystemUsersApi(UserPermissionMixin, ListAPIView): class UserGrantedRemoteAppSystemUsersApi(UserPermissionMixin, generics.ListAPIView):
permission_classes = (IsOrgAdminOrAppUser,) permission_classes = (IsOrgAdminOrAppUser,)
serializer_class = serializers.RemoteAppSystemUserSerializer serializer_class = serializers.RemoteAppSystemUserSerializer
only_fields = serializers.RemoteAppSystemUserSerializer.Meta.only_fields only_fields = serializers.RemoteAppSystemUserSerializer.Meta.only_fields
...@@ -110,7 +108,7 @@ class ValidateUserRemoteAppPermissionApi(APIView): ...@@ -110,7 +108,7 @@ class ValidateUserRemoteAppPermissionApi(APIView):
# RemoteApp permission # RemoteApp permission
class UserGroupGrantedRemoteAppsApi(ListAPIView): class UserGroupGrantedRemoteAppsApi(generics.ListAPIView):
permission_classes = (IsOrgAdminOrAppUser, ) permission_classes = (IsOrgAdminOrAppUser, )
serializer_class = RemoteAppSerializer serializer_class = RemoteAppSerializer
......
...@@ -2,10 +2,15 @@ ...@@ -2,10 +2,15 @@
# #
from users.models import User, UserGroup 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 assets.serializers import NodeSerializer
from applications.serializers import RemoteAppSerializer from applications.serializers import RemoteAppSerializer
from applications.models import RemoteApp from applications.models import RemoteApp
__all__ = [
'User', 'UserGroup',
'Asset', 'SystemUser', 'Node', 'Label', 'FavoriteAsset',
'NodeSerializer', 'RemoteAppSerializer',
'RemoteApp'
]
...@@ -13,7 +13,7 @@ from common.utils import get_logger, timeit, lazyproperty ...@@ -13,7 +13,7 @@ from common.utils import get_logger, timeit, lazyproperty
from common.tree import TreeNode from common.tree import TreeNode
from assets.utils import TreeService from assets.utils import TreeService
from ..models import AssetPermission from ..models import AssetPermission
from ..hands import Node, Asset, SystemUser from ..hands import Node, Asset, SystemUser, User, FavoriteAsset
logger = get_logger(__file__) logger = get_logger(__file__)
...@@ -293,6 +293,20 @@ class AssetPermissionUtilV2(AssetPermissionUtilCacheMixin): ...@@ -293,6 +293,20 @@ class AssetPermissionUtilV2(AssetPermissionUtilCacheMixin):
parent=user_tree.root, 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): def set_user_tree_to_local(self, user_tree):
self._user_tree = user_tree self._user_tree = user_tree
self._user_tree_filter_id = self._filter_id self._user_tree_filter_id = self._filter_id
...@@ -323,6 +337,7 @@ class AssetPermissionUtilV2(AssetPermissionUtilCacheMixin): ...@@ -323,6 +337,7 @@ class AssetPermissionUtilV2(AssetPermissionUtilCacheMixin):
self.add_single_assets_node_to_user_tree(user_tree) self.add_single_assets_node_to_user_tree(user_tree)
self.parse_user_tree_to_full_tree(user_tree) self.parse_user_tree_to_full_tree(user_tree)
self.add_empty_node_if_need(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_cache_if_need(user_tree)
self.set_user_tree_to_local(user_tree) self.set_user_tree_to_local(user_tree)
return user_tree return user_tree
......
...@@ -267,7 +267,7 @@ function requestApi(props) { ...@@ -267,7 +267,7 @@ function requestApi(props) {
$.ajax({ $.ajax({
url: props.url, url: props.url,
type: props.method || "PATCH", type: props.method || "PATCH",
data: props.body, data: props.body || props.data,
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) {
...@@ -579,6 +579,9 @@ jumpserver.initServerSideDataTable = function (options) { ...@@ -579,6 +579,9 @@ jumpserver.initServerSideDataTable = function (options) {
ajax: { ajax: {
url: options.ajax_url, url: options.ajax_url,
error: function (jqXHR, textStatus, errorThrown) { error: function (jqXHR, textStatus, errorThrown) {
if (jqXHR.responseText && jqXHR.responseText.indexOf("%(value)s") !== -1 ) {
return
}
var msg = gettext("Unknown error occur"); var msg = gettext("Unknown error occur");
if (jqXHR.responseJSON) { if (jqXHR.responseJSON) {
if (jqXHR.responseJSON.error) { if (jqXHR.responseJSON.error) {
...@@ -953,8 +956,13 @@ function initPopover($container, $progress, $idPassword, $el, password_check_rul ...@@ -953,8 +956,13 @@ function initPopover($container, $progress, $idPassword, $el, password_check_rul
function rootNodeAddDom(ztree, callback) { function rootNodeAddDom(ztree, callback) {
var refreshIcon = "<a id='tree-refresh'><i class='fa fa-refresh'></i></a>"; var refreshIcon = "<a id='tree-refresh'><i class='fa fa-refresh'></i></a>";
var rootNode = ztree.getNodes()[0]; var rootNode = ztree.getNodes()[0];
if (rootNode) {
var $rootNodeRef = $("#" + rootNode.tId + "_a"); var $rootNodeRef = $("#" + rootNode.tId + "_a");
$rootNodeRef.after(refreshIcon); $rootNodeRef.after(refreshIcon);
} else {
$rootNodeRef = $('#' + ztree.setting.treeId);
$rootNodeRef.html(refreshIcon);
}
var refreshIconRef = $('#tree-refresh'); var refreshIconRef = $('#tree-refresh');
refreshIconRef.bind('click', function () { refreshIconRef.bind('click', function () {
ztree.destroy(); ztree.destroy();
......
...@@ -24,10 +24,10 @@ logger = get_logger(__name__) ...@@ -24,10 +24,10 @@ logger = get_logger(__name__)
class SessionViewSet(OrgBulkModelViewSet): class SessionViewSet(OrgBulkModelViewSet):
queryset = Session.objects.all() model = Session
serializer_class = serializers.SessionSerializer serializer_class = serializers.SessionSerializer
permission_classes = (IsOrgAdminOrAppUser, ) permission_classes = (IsOrgAdminOrAppUser, )
filter_fields = [ filterset_fields = [
"user", "asset", "system_user", "remote_addr", "user", "asset", "system_user", "remote_addr",
"protocol", "terminal", "is_finished", "protocol", "terminal", "is_finished",
] ]
......
...@@ -72,6 +72,7 @@ ...@@ -72,6 +72,7 @@
<li><a class="search-item" data-value="asset">{% trans 'Asset' %}</a></li> <li><a class="search-item" data-value="asset">{% trans 'Asset' %}</a></li>
<li><a class="search-item" data-value="system_user">{% trans 'System user' %}</a></li> <li><a class="search-item" data-value="system_user">{% trans 'System user' %}</a></li>
<li><a class="search-item" data-value="remote_addr">{% trans 'Remote addr' %}</a></li> <li><a class="search-item" data-value="remote_addr">{% trans 'Remote addr' %}</a></li>
<li><a class="search-item" data-value="protocol">{% trans 'Protocol' %}</a></li>
{# <li><a class="search-item" data-value="protocol">{% trans 'Protocol' %}</a></li>#} {# <li><a class="search-item" data-value="protocol">{% trans 'Protocol' %}</a></li>#}
</ul> </ul>
{% endblock %} {% endblock %}
......
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# #
from rest_framework import generics
from ..serializers import ( from ..serializers import (
UserGroupSerializer, UserGroupSerializer,
UserGroupListSerializer, UserGroupListSerializer,
...@@ -10,6 +8,7 @@ from ..serializers import ( ...@@ -10,6 +8,7 @@ from ..serializers import (
) )
from ..models import UserGroup from ..models import UserGroup
from orgs.mixins.api import OrgBulkModelViewSet from orgs.mixins.api import OrgBulkModelViewSet
from orgs.mixins import generics
from common.permissions import IsOrgAdmin from common.permissions import IsOrgAdmin
...@@ -17,9 +16,9 @@ __all__ = ['UserGroupViewSet', 'UserGroupUpdateUserApi'] ...@@ -17,9 +16,9 @@ __all__ = ['UserGroupViewSet', 'UserGroupUpdateUserApi']
class UserGroupViewSet(OrgBulkModelViewSet): class UserGroupViewSet(OrgBulkModelViewSet):
model = UserGroup
filter_fields = ("name",) filter_fields = ("name",)
search_fields = filter_fields search_fields = filter_fields
queryset = UserGroup.objects.all()
serializer_class = UserGroupSerializer serializer_class = UserGroupSerializer
permission_classes = (IsOrgAdmin,) permission_classes = (IsOrgAdmin,)
...@@ -31,6 +30,6 @@ class UserGroupViewSet(OrgBulkModelViewSet): ...@@ -31,6 +30,6 @@ class UserGroupViewSet(OrgBulkModelViewSet):
class UserGroupUpdateUserApi(generics.RetrieveUpdateAPIView): class UserGroupUpdateUserApi(generics.RetrieveUpdateAPIView):
queryset = UserGroup.objects.all() model = UserGroup
serializer_class = UserGroupUpdateMemberSerializer serializer_class = UserGroupUpdateMemberSerializer
permission_classes = (IsOrgAdmin,) permission_classes = (IsOrgAdmin,)
...@@ -17,7 +17,7 @@ from common.permissions import ( ...@@ -17,7 +17,7 @@ from common.permissions import (
from common.mixins import CommonApiMixin from common.mixins import CommonApiMixin
from common.utils import get_logger from common.utils import get_logger
from orgs.utils import current_org from orgs.utils import current_org
from .. import serializers from .. import serializers, utils
from ..models import User from ..models import User
from ..signals import post_user_create from ..signals import post_user_create
...@@ -30,13 +30,21 @@ __all__ = [ ...@@ -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') filter_fields = ('username', 'email', 'name', 'id')
search_fields = filter_fields search_fields = filter_fields
queryset = User.objects.exclude(role=User.ROLE_APP)
serializer_class = serializers.UserSerializer serializer_class = serializers.UserSerializer
permission_classes = (IsOrgAdmin, CanUpdateDeleteUser) permission_classes = (IsOrgAdmin, CanUpdateDeleteUser)
def get_queryset(self):
return super().get_queryset().prefetch_related('groups')
def send_created_signal(self, users): def send_created_signal(self, users):
if not isinstance(users, list): if not isinstance(users, list):
users = [users] users = [users]
...@@ -51,11 +59,6 @@ class UserViewSet(CommonApiMixin, BulkModelViewSet): ...@@ -51,11 +59,6 @@ class UserViewSet(CommonApiMixin, BulkModelViewSet):
current_org.users.add(*users) current_org.users.add(*users)
self.send_created_signal(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): def get_permissions(self):
if self.action in ["retrieve", "list"]: if self.action in ["retrieve", "list"]:
self.permission_classes = (IsOrgAdminOrAppUser,) self.permission_classes = (IsOrgAdminOrAppUser,)
...@@ -79,9 +82,8 @@ class UserViewSet(CommonApiMixin, BulkModelViewSet): ...@@ -79,9 +82,8 @@ class UserViewSet(CommonApiMixin, BulkModelViewSet):
return super().perform_bulk_update(serializer) return super().perform_bulk_update(serializer)
class UserChangePasswordApi(generics.RetrieveUpdateAPIView): class UserChangePasswordApi(UserQuerysetMixin, generics.RetrieveUpdateAPIView):
permission_classes = (IsOrgAdmin,) permission_classes = (IsOrgAdmin,)
queryset = User.objects.all()
serializer_class = serializers.ChangeUserPasswordSerializer serializer_class = serializers.ChangeUserPasswordSerializer
def perform_update(self, serializer): def perform_update(self, serializer):
...@@ -90,13 +92,12 @@ class UserChangePasswordApi(generics.RetrieveUpdateAPIView): ...@@ -90,13 +92,12 @@ class UserChangePasswordApi(generics.RetrieveUpdateAPIView):
user.save() user.save()
class UserUpdateGroupApi(generics.RetrieveUpdateAPIView): class UserUpdateGroupApi(UserQuerysetMixin, generics.RetrieveUpdateAPIView):
queryset = User.objects.all()
serializer_class = serializers.UserUpdateGroupSerializer serializer_class = serializers.UserUpdateGroupSerializer
permission_classes = (IsOrgAdmin,) permission_classes = (IsOrgAdmin,)
class UserResetPasswordApi(generics.UpdateAPIView): class UserResetPasswordApi(UserQuerysetMixin, generics.UpdateAPIView):
queryset = User.objects.all() queryset = User.objects.all()
serializer_class = serializers.UserSerializer serializer_class = serializers.UserSerializer
permission_classes = (IsAuthenticated,) permission_classes = (IsAuthenticated,)
...@@ -111,8 +112,7 @@ class UserResetPasswordApi(generics.UpdateAPIView): ...@@ -111,8 +112,7 @@ class UserResetPasswordApi(generics.UpdateAPIView):
send_reset_password_mail(user) send_reset_password_mail(user)
class UserResetPKApi(generics.UpdateAPIView): class UserResetPKApi(UserQuerysetMixin, generics.UpdateAPIView):
queryset = User.objects.all()
serializer_class = serializers.UserSerializer serializer_class = serializers.UserSerializer
permission_classes = (IsAuthenticated,) permission_classes = (IsAuthenticated,)
...@@ -125,8 +125,7 @@ class UserResetPKApi(generics.UpdateAPIView): ...@@ -125,8 +125,7 @@ class UserResetPKApi(generics.UpdateAPIView):
# 废弃 # 废弃
class UserUpdatePKApi(generics.UpdateAPIView): class UserUpdatePKApi(UserQuerysetMixin, generics.UpdateAPIView):
queryset = User.objects.all()
serializer_class = serializers.UserPKUpdateSerializer serializer_class = serializers.UserPKUpdateSerializer
permission_classes = (IsCurrentUserOrReadOnly,) permission_classes = (IsCurrentUserOrReadOnly,)
...@@ -136,8 +135,7 @@ class UserUpdatePKApi(generics.UpdateAPIView): ...@@ -136,8 +135,7 @@ class UserUpdatePKApi(generics.UpdateAPIView):
user.save() user.save()
class UserUnblockPKApi(generics.UpdateAPIView): class UserUnblockPKApi(UserQuerysetMixin, generics.UpdateAPIView):
queryset = User.objects.all()
permission_classes = (IsOrgAdmin,) permission_classes = (IsOrgAdmin,)
serializer_class = serializers.UserSerializer serializer_class = serializers.UserSerializer
key_prefix_limit = "_LOGIN_LIMIT_{}_{}" key_prefix_limit = "_LOGIN_LIMIT_{}_{}"
...@@ -165,8 +163,7 @@ class UserProfileApi(generics.RetrieveAPIView): ...@@ -165,8 +163,7 @@ class UserProfileApi(generics.RetrieveAPIView):
return super().retrieve(request, *args, **kwargs) return super().retrieve(request, *args, **kwargs)
class UserResetOTPApi(generics.RetrieveAPIView): class UserResetOTPApi(UserQuerysetMixin, generics.RetrieveAPIView):
queryset = User.objects.all()
permission_classes = (IsOrgAdmin,) permission_classes = (IsOrgAdmin,)
serializer_class = serializers.ResetOTPSerializer serializer_class = serializers.ResetOTPSerializer
......
...@@ -5,9 +5,8 @@ from django.utils.translation import gettext_lazy as _ ...@@ -5,9 +5,8 @@ from django.utils.translation import gettext_lazy as _
from common.utils import validate_ssh_public_key from common.utils import validate_ssh_public_key
from orgs.mixins.forms import OrgModelForm from orgs.mixins.forms import OrgModelForm
from orgs.utils import current_org
from .models import User, UserGroup 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): class UserCheckPasswordForm(forms.Form):
...@@ -267,15 +266,23 @@ class UserBulkUpdateForm(OrgModelForm): ...@@ -267,15 +266,23 @@ class UserBulkUpdateForm(OrgModelForm):
users = forms.ModelMultipleChoiceField( users = forms.ModelMultipleChoiceField(
required=True, required=True,
label=_('Select users'), label=_('Select users'),
queryset=User.objects.all(), queryset=User.objects.none(),
widget=forms.SelectMultiple( widget=forms.SelectMultiple(
attrs={ attrs={
'class': 'select2', 'class': 'users-select2',
'data-placeholder': _('Select users') '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: class Meta:
model = User model = User
fields = ['users', 'groups', 'date_expired'] fields = ['users', 'groups', 'date_expired']
...@@ -320,25 +327,19 @@ class UserGroupForm(OrgModelForm): ...@@ -320,25 +327,19 @@ class UserGroupForm(OrgModelForm):
) )
def __init__(self, **kwargs): 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) super().__init__(**kwargs)
if 'initial' not in kwargs: self.set_fields_queryset()
return
def set_fields_queryset(self):
users_field = self.fields.get('users') users_field = self.fields.get('users')
if instance: if self.instance:
users_field.queryset = instance.users.all() users_field.initial = self.instance.users.all()
users_field.queryset = self.instance.users.all()
else: else:
users_field.queryset = User.objects.none() users_field.queryset = User.objects.none()
def save(self, commit=True): def save(self, commit=True):
group = super().save(commit=commit) raise Exception("Save by restful api")
users = self.cleaned_data['users']
group.users.set(users)
return group
class Meta: class Meta:
model = UserGroup model = UserGroup
......
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# #
import copy
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from rest_framework import serializers from rest_framework import serializers
...@@ -12,6 +11,7 @@ from common.serializers import AdaptedBulkListSerializer ...@@ -12,6 +11,7 @@ from common.serializers import AdaptedBulkListSerializer
from common.permissions import CanUpdateDeleteUser from common.permissions import CanUpdateDeleteUser
from orgs.mixins.serializers import BulkOrgResourceModelSerializer from orgs.mixins.serializers import BulkOrgResourceModelSerializer
from ..models import User, UserGroup from ..models import User, UserGroup
from .. import utils
__all__ = [ __all__ = [
...@@ -118,7 +118,9 @@ class UserPKUpdateSerializer(serializers.ModelSerializer): ...@@ -118,7 +118,9 @@ class UserPKUpdateSerializer(serializers.ModelSerializer):
class UserUpdateGroupSerializer(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: class Meta:
model = User model = User
...@@ -127,7 +129,7 @@ class UserUpdateGroupSerializer(serializers.ModelSerializer): ...@@ -127,7 +129,7 @@ class UserUpdateGroupSerializer(serializers.ModelSerializer):
class UserGroupSerializer(BulkOrgResourceModelSerializer): class UserGroupSerializer(BulkOrgResourceModelSerializer):
users = serializers.PrimaryKeyRelatedField( users = serializers.PrimaryKeyRelatedField(
required=False, many=True, queryset=User.objects.all(), label=_('User') required=False, many=True, queryset=User.objects, label=_('User')
) )
class Meta: class Meta:
...@@ -141,6 +143,14 @@ class UserGroupSerializer(BulkOrgResourceModelSerializer): ...@@ -141,6 +143,14 @@ class UserGroupSerializer(BulkOrgResourceModelSerializer):
'created_by': {'label': _('Created by'), 'read_only': True} '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): def validate_users(self, users):
for user in users: for user in users:
if user.is_super_auditor: if user.is_super_auditor:
...@@ -154,12 +164,20 @@ class UserGroupListSerializer(UserGroupSerializer): ...@@ -154,12 +164,20 @@ class UserGroupListSerializer(UserGroupSerializer):
class UserGroupUpdateMemberSerializer(serializers.ModelSerializer): class UserGroupUpdateMemberSerializer(serializers.ModelSerializer):
users = serializers.PrimaryKeyRelatedField(many=True, queryset=User.objects.all()) users = serializers.PrimaryKeyRelatedField(many=True, queryset=User.objects)
class Meta: class Meta:
model = UserGroup model = UserGroup
fields = ['id', 'users'] 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): class ChangeUserPasswordSerializer(serializers.ModelSerializer):
......
{% load i18n %} {% load i18n %}
<div class="col-lg-3" style="padding-left: 0px"> <div class="col-lg-3" style="padding-left: 0" id="split-left">
<div class="ibox float-e-margins"> <div class="ibox float-e-margins">
<div class="ibox-content mailbox-content" style="padding-top: 0"> <div class="ibox-content mailbox-content" style="padding-top: 0">
<div class="file-manager "> <div class="file-manager ">
...@@ -11,7 +11,12 @@ ...@@ -11,7 +11,12 @@
</div> </div>
</div> </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="mail-box-header">
{# <div class="btn-group" style="float: right">#} {# <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>#} {# <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() { ...@@ -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 () { $(document).ready(function () {
{#loadLabels()#} {#loadLabels()#}
}).on('click', '.labels-menu li', function () { }).on('click', '.labels-menu li', function () {
......
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
<script> <script>
$(document).ready(function () { $(document).ready(function () {
$('.select2').select2(); $('.select2').select2();
usersSelect2Init('.users-select2')
}).on('click', '.field-tag', function() { }).on('click', '.field-tag', function() {
changeField(this); changeField(this);
}).on('click', '#change_all', function () { }).on('click', '#change_all', function () {
......
...@@ -34,7 +34,7 @@ ...@@ -34,7 +34,7 @@
{% block custom_foot_js %} {% block custom_foot_js %}
<script> <script>
var assetTableUrl = "{% url 'api-perms:user-group-assets' pk=object.id %}?cache_policy=1"; 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 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 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 var showAssetHref = true; // Need input default true
......
...@@ -325,3 +325,7 @@ def construct_user_email(username, email): ...@@ -325,3 +325,7 @@ def construct_user_email(username, email):
email = '{}@{}'.format(username, settings.EMAIL_SUFFIX) email = '{}@{}'.format(username, settings.EMAIL_SUFFIX)
return email return email
def get_current_org_members(exclude=()):
from orgs.utils import current_org
return current_org.get_org_members(exclude=exclude)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment