Commit 673ebbec authored by ibuler's avatar ibuler

[Update] Merge with dev

parents c2f78b11 f3dc9b88
# 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')
...@@ -98,4 +98,4 @@ class AssetGatewayApi(generics.RetrieveAPIView): ...@@ -98,4 +98,4 @@ class AssetGatewayApi(generics.RetrieveAPIView):
serializer = serializers.GatewayWithAuthSerializer(instance=gateway) serializer = serializers.GatewayWithAuthSerializer(instance=gateway)
return Response(serializer.data) return Response(serializer.data)
else: else:
return Response({"msg": "Not have gateway"}, status=404) return Response({"msg": "Not have gateway"}, status=404)
\ No newline at end of file
...@@ -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 () {
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 () { }).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 () {
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> </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
......
...@@ -8,7 +8,7 @@ msgid "" ...@@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: Jumpserver 0.3.3\n" "Project-Id-Version: Jumpserver 0.3.3\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-10-12 17:06+0800\n" "POT-Creation-Date: 2019-10-17 16:09+0800\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: ibuler <ibuler@qq.com>\n" "Last-Translator: ibuler <ibuler@qq.com>\n"
"Language-Team: Jumpserver team<ibuler@qq.com>\n" "Language-Team: Jumpserver team<ibuler@qq.com>\n"
...@@ -193,11 +193,11 @@ msgstr "参数" ...@@ -193,11 +193,11 @@ msgstr "参数"
#: assets/templates/assets/cmd_filter_detail.html:77 #: assets/templates/assets/cmd_filter_detail.html:77
#: assets/templates/assets/domain_detail.html:72 #: assets/templates/assets/domain_detail.html:72
#: assets/templates/assets/system_user_detail.html:100 #: assets/templates/assets/system_user_detail.html:100
#: ops/templates/ops/adhoc_detail.html:86 orgs/models.py:16 #: common/mixins/models.py:50 ops/templates/ops/adhoc_detail.html:86
#: perms/models/base.py:54 #: orgs/models.py:16 perms/models/base.py:54
#: perms/templates/perms/asset_permission_detail.html:98 #: perms/templates/perms/asset_permission_detail.html:98
#: perms/templates/perms/remote_app_permission_detail.html:90 #: perms/templates/perms/remote_app_permission_detail.html:90
#: users/models/user.py:414 users/serializers/v1.py:141 #: users/models/user.py:414 users/serializers/v1.py:143
#: users/templates/users/user_detail.html:111 #: users/templates/users/user_detail.html:111
#: xpack/plugins/change_auth_plan/models.py:108 #: xpack/plugins/change_auth_plan/models.py:108
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:113 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:113
...@@ -216,7 +216,8 @@ msgstr "创建者" ...@@ -216,7 +216,8 @@ msgstr "创建者"
#: assets/models/label.py:25 assets/templates/assets/admin_user_detail.html:64 #: assets/models/label.py:25 assets/templates/assets/admin_user_detail.html:64
#: assets/templates/assets/cmd_filter_detail.html:69 #: assets/templates/assets/cmd_filter_detail.html:69
#: assets/templates/assets/domain_detail.html:68 #: assets/templates/assets/domain_detail.html:68
#: assets/templates/assets/system_user_detail.html:96 ops/models/adhoc.py:45 #: assets/templates/assets/system_user_detail.html:96
#: common/mixins/models.py:51 ops/models/adhoc.py:45
#: ops/templates/ops/adhoc_detail.html:90 ops/templates/ops/task_detail.html:64 #: ops/templates/ops/adhoc_detail.html:90 ops/templates/ops/task_detail.html:64
#: orgs/models.py:17 perms/models/base.py:55 #: orgs/models.py:17 perms/models/base.py:55
#: perms/templates/perms/asset_permission_detail.html:94 #: perms/templates/perms/asset_permission_detail.html:94
...@@ -310,6 +311,7 @@ msgstr "远程应用" ...@@ -310,6 +311,7 @@ msgstr "远程应用"
#: users/templates/users/_user.html:50 #: users/templates/users/_user.html:50
#: users/templates/users/user_bulk_update.html:23 #: users/templates/users/user_bulk_update.html:23
#: users/templates/users/user_detail.html:178 #: users/templates/users/user_detail.html:178
#: users/templates/users/user_group_create_update.html:31
#: users/templates/users/user_password_update.html:75 #: users/templates/users/user_password_update.html:75
#: users/templates/users/user_profile.html:209 #: users/templates/users/user_profile.html:209
#: users/templates/users/user_profile_update.html:67 #: users/templates/users/user_profile_update.html:67
...@@ -522,7 +524,7 @@ msgstr "创建远程应用" ...@@ -522,7 +524,7 @@ msgstr "创建远程应用"
#: settings/templates/settings/terminal_setting.html:107 #: settings/templates/settings/terminal_setting.html:107
#: terminal/templates/terminal/session_list.html:36 #: terminal/templates/terminal/session_list.html:36
#: terminal/templates/terminal/terminal_list.html:36 #: terminal/templates/terminal/terminal_list.html:36
#: users/templates/users/_granted_assets.html:29 #: users/templates/users/_granted_assets.html:34
#: users/templates/users/user_group_list.html:38 #: users/templates/users/user_group_list.html:38
#: users/templates/users/user_list.html:41 #: users/templates/users/user_list.html:41
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_list.html:60 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_list.html:60
...@@ -537,7 +539,6 @@ msgid "Action" ...@@ -537,7 +539,6 @@ msgid "Action"
msgstr "动作" msgstr "动作"
#: applications/templates/applications/user_remote_app_list.html:52 #: applications/templates/applications/user_remote_app_list.html:52
#: assets/templates/assets/user_asset_list.html:32
#: perms/models/asset_permission.py:32 #: perms/models/asset_permission.py:32
msgid "Connect" msgid "Connect"
msgstr "连接" msgstr "连接"
...@@ -564,11 +565,11 @@ msgstr "远程应用详情" ...@@ -564,11 +565,11 @@ msgstr "远程应用详情"
msgid "My RemoteApp" msgid "My RemoteApp"
msgstr "我的远程应用" msgstr "我的远程应用"
#: assets/api/node.py:58 #: assets/api/node.py:61
msgid "You can't update the root node name" msgid "You can't update the root node name"
msgstr "不能修改根节点名称" msgstr "不能修改根节点名称"
#: assets/api/node.py:65 #: assets/api/node.py:68
msgid "Deletion failed and the node contains children or assets" msgid "Deletion failed and the node contains children or assets"
msgstr "删除失败,节点包含子节点或资产" msgstr "删除失败,节点包含子节点或资产"
...@@ -626,13 +627,13 @@ msgstr "标签" ...@@ -626,13 +627,13 @@ msgstr "标签"
#: assets/forms/asset.py:65 assets/forms/asset.py:112 #: assets/forms/asset.py:65 assets/forms/asset.py:112
#: assets/models/asset.py:144 assets/models/domain.py:26 #: assets/models/asset.py:144 assets/models/domain.py:26
#: assets/models/domain.py:52 assets/templates/assets/asset_detail.html:78 #: assets/models/domain.py:52 assets/templates/assets/asset_detail.html:78
#: assets/templates/assets/user_asset_list.html:53 #: assets/templates/assets/user_asset_list.html:80
#: xpack/plugins/orgs/templates/orgs/org_list.html:18 #: xpack/plugins/orgs/templates/orgs/org_list.html:18
msgid "Domain" msgid "Domain"
msgstr "网域" msgstr "网域"
#: assets/forms/asset.py:69 assets/forms/asset.py:103 assets/forms/asset.py:116 #: assets/forms/asset.py:69 assets/forms/asset.py:103 assets/forms/asset.py:116
#: assets/forms/asset.py:152 assets/models/node.py:409 #: assets/forms/asset.py:152 assets/models/node.py:421
#: assets/templates/assets/asset_create.html:42 #: assets/templates/assets/asset_create.html:42
#: perms/forms/asset_permission.py:83 perms/forms/asset_permission.py:90 #: perms/forms/asset_permission.py:83 perms/forms/asset_permission.py:90
#: perms/templates/perms/asset_permission_list.html:53 #: perms/templates/perms/asset_permission_list.html:53
...@@ -700,7 +701,7 @@ msgstr "SSH网关,支持代理SSH,RDP和VNC" ...@@ -700,7 +701,7 @@ msgstr "SSH网关,支持代理SSH,RDP和VNC"
#: ops/models/adhoc.py:189 perms/templates/perms/asset_permission_list.html:70 #: ops/models/adhoc.py:189 perms/templates/perms/asset_permission_list.html:70
#: perms/templates/perms/asset_permission_user.html:55 #: perms/templates/perms/asset_permission_user.html:55
#: perms/templates/perms/remote_app_permission_user.html:54 #: perms/templates/perms/remote_app_permission_user.html:54
#: settings/templates/settings/_ldap_list_users_modal.html:30 users/forms.py:14 #: settings/templates/settings/_ldap_list_users_modal.html:30 users/forms.py:13
#: users/models/user.py:371 users/templates/users/_select_user_modal.html:14 #: users/models/user.py:371 users/templates/users/_select_user_modal.html:14
#: users/templates/users/user_detail.html:67 #: users/templates/users/user_detail.html:67
#: users/templates/users/user_list.html:36 #: users/templates/users/user_list.html:36
...@@ -727,7 +728,7 @@ msgstr "密码或密钥密码" ...@@ -727,7 +728,7 @@ msgstr "密码或密钥密码"
#: authentication/forms.py:15 #: authentication/forms.py:15
#: authentication/templates/authentication/login.html:68 #: authentication/templates/authentication/login.html:68
#: authentication/templates/authentication/new_login.html:95 #: authentication/templates/authentication/new_login.html:95
#: settings/forms.py:114 users/forms.py:16 users/forms.py:28 #: settings/forms.py:114 users/forms.py:15 users/forms.py:27
#: users/templates/users/reset_password.html:53 #: users/templates/users/reset_password.html:53
#: users/templates/users/user_password_authentication.html:18 #: users/templates/users/user_password_authentication.html:18
#: users/templates/users/user_password_update.html:44 #: users/templates/users/user_password_update.html:44
...@@ -788,10 +789,10 @@ msgstr "使用逗号分隔多个命令,如: /bin/whoami,/sbin/ifconfig" ...@@ -788,10 +789,10 @@ msgstr "使用逗号分隔多个命令,如: /bin/whoami,/sbin/ifconfig"
#: assets/templates/assets/asset_detail.html:62 #: assets/templates/assets/asset_detail.html:62
#: assets/templates/assets/asset_list.html:97 #: assets/templates/assets/asset_list.html:97
#: assets/templates/assets/domain_gateway_list.html:68 #: assets/templates/assets/domain_gateway_list.html:68
#: assets/templates/assets/user_asset_list.html:49 #: assets/templates/assets/user_asset_list.html:76
#: audits/templates/audits/login_log_list.html:60 #: audits/templates/audits/login_log_list.html:60
#: perms/templates/perms/asset_permission_asset.html:58 settings/forms.py:144 #: perms/templates/perms/asset_permission_asset.html:58 settings/forms.py:144
#: users/templates/users/_granted_assets.html:26 #: users/templates/users/_granted_assets.html:31
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_asset_list.html:54 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_asset_list.html:54
#: xpack/plugins/gathered_user/templates/gathered_user/gathered_user_list.html:73 #: xpack/plugins/gathered_user/templates/gathered_user/gathered_user_list.html:73
msgid "IP" msgid "IP"
...@@ -805,10 +806,10 @@ msgstr "IP" ...@@ -805,10 +806,10 @@ msgstr "IP"
#: assets/templates/assets/_asset_user_list.html:19 #: assets/templates/assets/_asset_user_list.html:19
#: assets/templates/assets/asset_detail.html:58 #: assets/templates/assets/asset_detail.html:58
#: assets/templates/assets/asset_list.html:96 #: assets/templates/assets/asset_list.html:96
#: assets/templates/assets/user_asset_list.html:48 #: assets/templates/assets/user_asset_list.html:75
#: perms/templates/perms/asset_permission_asset.html:57 #: perms/templates/perms/asset_permission_asset.html:57
#: perms/templates/perms/asset_permission_list.html:73 settings/forms.py:143 #: perms/templates/perms/asset_permission_list.html:73 settings/forms.py:143
#: users/templates/users/_granted_assets.html:25 #: users/templates/users/_granted_assets.html:30
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_asset_list.html:53 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_asset_list.html:53
#: xpack/plugins/gathered_user/templates/gathered_user/gathered_user_list.html:72 #: xpack/plugins/gathered_user/templates/gathered_user/gathered_user_list.html:72
msgid "Hostname" msgid "Hostname"
...@@ -820,18 +821,19 @@ msgstr "主机名" ...@@ -820,18 +821,19 @@ msgstr "主机名"
#: assets/templates/assets/system_user_detail.html:70 #: assets/templates/assets/system_user_detail.html:70
#: assets/templates/assets/system_user_list.html:53 #: assets/templates/assets/system_user_list.html:53
#: terminal/templates/terminal/session_list.html:31 #: terminal/templates/terminal/session_list.html:31
#: terminal/templates/terminal/session_list.html:75
msgid "Protocol" msgid "Protocol"
msgstr "协议" msgstr "协议"
#: assets/models/asset.py:142 assets/serializers/asset.py:68 #: assets/models/asset.py:142 assets/serializers/asset.py:68
#: assets/templates/assets/asset_create.html:24 #: assets/templates/assets/asset_create.html:24
#: assets/templates/assets/user_asset_list.html:50 #: assets/templates/assets/user_asset_list.html:77
#: perms/serializers/user_permission.py:48 #: perms/serializers/user_permission.py:48
msgid "Protocols" msgid "Protocols"
msgstr "协议组" msgstr "协议组"
#: assets/models/asset.py:143 assets/templates/assets/asset_detail.html:102 #: assets/models/asset.py:143 assets/templates/assets/asset_detail.html:102
#: assets/templates/assets/user_asset_list.html:51 #: assets/templates/assets/user_asset_list.html:78
msgid "Platform" msgid "Platform"
msgstr "系统平台" msgstr "系统平台"
...@@ -938,7 +940,8 @@ msgid "SSH public key" ...@@ -938,7 +940,8 @@ msgid "SSH public key"
msgstr "ssh公钥" msgstr "ssh公钥"
#: assets/models/base.py:35 assets/models/gathered_user.py:21 #: assets/models/base.py:35 assets/models/gathered_user.py:21
#: assets/templates/assets/cmd_filter_detail.html:73 ops/models/adhoc.py:46 #: assets/templates/assets/cmd_filter_detail.html:73 common/mixins/models.py:52
#: ops/models/adhoc.py:46
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:109 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:109
#: xpack/plugins/gathered_user/templates/gathered_user/gathered_user_list.html:76 #: xpack/plugins/gathered_user/templates/gathered_user/gathered_user_list.html:76
msgid "Date updated" msgid "Date updated"
...@@ -1105,9 +1108,9 @@ msgstr "默认资产组" ...@@ -1105,9 +1108,9 @@ msgstr "默认资产组"
#: terminal/models.py:156 terminal/templates/terminal/command_list.html:29 #: terminal/models.py:156 terminal/templates/terminal/command_list.html:29
#: terminal/templates/terminal/command_list.html:65 #: terminal/templates/terminal/command_list.html:65
#: terminal/templates/terminal/session_list.html:27 #: terminal/templates/terminal/session_list.html:27
#: terminal/templates/terminal/session_list.html:71 users/forms.py:312 #: terminal/templates/terminal/session_list.html:71 users/forms.py:319
#: users/models/user.py:127 users/models/user.py:143 users/models/user.py:500 #: users/models/user.py:127 users/models/user.py:143 users/models/user.py:500
#: users/serializers/v1.py:130 users/templates/users/user_group_detail.html:78 #: users/serializers/v1.py:132 users/templates/users/user_group_detail.html:78
#: users/templates/users/user_group_list.html:36 users/views/user.py:250 #: users/templates/users/user_group_list.html:36 users/views/user.py:250
#: xpack/plugins/orgs/forms.py:28 #: xpack/plugins/orgs/forms.py:28
#: xpack/plugins/orgs/templates/orgs/org_detail.html:113 #: xpack/plugins/orgs/templates/orgs/org_detail.html:113
...@@ -1115,7 +1118,7 @@ msgstr "默认资产组" ...@@ -1115,7 +1118,7 @@ msgstr "默认资产组"
msgid "User" msgid "User"
msgstr "用户" msgstr "用户"
#: assets/models/label.py:19 assets/models/node.py:400 #: assets/models/label.py:19 assets/models/node.py:412
#: assets/templates/assets/label_list.html:15 settings/models.py:30 #: assets/templates/assets/label_list.html:15 settings/models.py:30
msgid "Value" msgid "Value"
msgstr "值" msgstr "值"
...@@ -1136,7 +1139,11 @@ msgstr "未分组" ...@@ -1136,7 +1139,11 @@ msgstr "未分组"
msgid "empty" msgid "empty"
msgstr "空" msgstr "空"
#: assets/models/node.py:399 #: assets/models/node.py:328
msgid "favorite"
msgstr "收藏夹"
#: assets/models/node.py:411
msgid "Key" msgid "Key"
msgstr "键" msgstr "键"
...@@ -1190,7 +1197,7 @@ msgstr "Shell" ...@@ -1190,7 +1197,7 @@ msgstr "Shell"
msgid "Login mode" msgid "Login mode"
msgstr "登录模式" msgstr "登录模式"
#: assets/models/user.py:162 assets/templates/assets/user_asset_list.html:52 #: assets/models/user.py:162 assets/templates/assets/user_asset_list.html:79
#: audits/models.py:20 audits/templates/audits/ftp_log_list.html:52 #: audits/models.py:20 audits/templates/audits/ftp_log_list.html:52
#: audits/templates/audits/ftp_log_list.html:75 #: audits/templates/audits/ftp_log_list.html:75
#: perms/forms/asset_permission.py:86 perms/forms/remote_app_permission.py:43 #: perms/forms/asset_permission.py:86 perms/forms/remote_app_permission.py:43
...@@ -1206,7 +1213,7 @@ msgstr "登录模式" ...@@ -1206,7 +1213,7 @@ msgstr "登录模式"
#: terminal/templates/terminal/command_list.html:67 #: terminal/templates/terminal/command_list.html:67
#: terminal/templates/terminal/session_list.html:29 #: terminal/templates/terminal/session_list.html:29
#: terminal/templates/terminal/session_list.html:73 #: terminal/templates/terminal/session_list.html:73
#: users/templates/users/_granted_assets.html:27 #: users/templates/users/_granted_assets.html:32
#: xpack/plugins/orgs/templates/orgs/org_list.html:20 #: xpack/plugins/orgs/templates/orgs/org_list.html:20
msgid "System user" msgid "System user"
msgstr "系统用户" msgstr "系统用户"
...@@ -1238,7 +1245,8 @@ msgstr "协议格式 {}/{}" ...@@ -1238,7 +1245,8 @@ msgstr "协议格式 {}/{}"
msgid "Protocol duplicate: {}" msgid "Protocol duplicate: {}"
msgstr "协议重复: {}" msgstr "协议重复: {}"
#: assets/serializers/asset.py:69 assets/serializers/asset_user.py:29 #: assets/serializers/asset.py:69 assets/serializers/asset.py:143
#: assets/serializers/asset_user.py:29
#: assets/templates/assets/_asset_user_list.html:23 #: assets/templates/assets/_asset_user_list.html:23
msgid "Connectivity" msgid "Connectivity"
msgstr "连接" msgstr "连接"
...@@ -1255,7 +1263,7 @@ msgstr "组织名称" ...@@ -1255,7 +1263,7 @@ msgstr "组织名称"
msgid "Backend" msgid "Backend"
msgstr "后端" msgstr "后端"
#: assets/serializers/asset_user.py:67 users/forms.py:263 #: assets/serializers/asset_user.py:67 users/forms.py:262
#: users/models/user.py:403 users/templates/users/first_login.html:42 #: users/models/user.py:403 users/templates/users/first_login.html:42
#: users/templates/users/user_password_update.html:49 #: users/templates/users/user_password_update.html:49
#: users/templates/users/user_profile.html:69 #: users/templates/users/user_profile.html:69
...@@ -1866,7 +1874,6 @@ msgstr "删除选择资产" ...@@ -1866,7 +1874,6 @@ msgstr "删除选择资产"
#: users/templates/users/user_detail.html:392 #: users/templates/users/user_detail.html:392
#: users/templates/users/user_detail.html:418 #: users/templates/users/user_detail.html:418
#: users/templates/users/user_detail.html:486 #: users/templates/users/user_detail.html:486
#: users/templates/users/user_group_create_update.html:31
#: users/templates/users/user_group_list.html:118 #: users/templates/users/user_group_list.html:118
#: users/templates/users/user_list.html:254 #: users/templates/users/user_list.html:254
#: xpack/plugins/interface/templates/interface/interface.html:101 #: xpack/plugins/interface/templates/interface/interface.html:101
...@@ -2256,7 +2263,7 @@ msgstr "Agent" ...@@ -2256,7 +2263,7 @@ msgstr "Agent"
#: audits/models.py:85 audits/templates/audits/login_log_list.html:62 #: audits/models.py:85 audits/templates/audits/login_log_list.html:62
#: authentication/templates/authentication/_mfa_confirm_modal.html:14 #: authentication/templates/authentication/_mfa_confirm_modal.html:14
#: users/forms.py:175 users/models/user.py:395 #: users/forms.py:174 users/models/user.py:395
#: users/templates/users/first_login.html:45 #: users/templates/users/first_login.html:45
msgid "MFA" msgid "MFA"
msgstr "MFA" msgstr "MFA"
...@@ -2479,7 +2486,7 @@ msgid "" ...@@ -2479,7 +2486,7 @@ msgid ""
"after {} minutes)" "after {} minutes)"
msgstr "账号已被锁定(请联系管理员解锁 或 {}分钟后重试)" msgstr "账号已被锁定(请联系管理员解锁 或 {}分钟后重试)"
#: authentication/forms.py:66 users/forms.py:22 #: authentication/forms.py:66 users/forms.py:21
msgid "MFA code" msgid "MFA code"
msgstr "MFA 验证码" msgstr "MFA 验证码"
...@@ -2504,7 +2511,7 @@ msgid "Secret" ...@@ -2504,7 +2511,7 @@ msgid "Secret"
msgstr "密文" msgstr "密文"
#: authentication/templates/authentication/_access_key_modal.html:48 #: authentication/templates/authentication/_access_key_modal.html:48
#: users/templates/users/_granted_assets.html:75 #: users/templates/users/_granted_assets.html:80
msgid "Show" msgid "Show"
msgstr "显示" msgstr "显示"
...@@ -2712,11 +2719,11 @@ msgstr "" ...@@ -2712,11 +2719,11 @@ msgstr ""
msgid "Encrypt field using Secret Key" msgid "Encrypt field using Secret Key"
msgstr "" msgstr ""
#: common/mixins/models.py:31 #: common/mixins/models.py:34
msgid "is discard" msgid "is discard"
msgstr "" msgstr ""
#: common/mixins/models.py:32 #: common/mixins/models.py:35
msgid "discard time" msgid "discard time"
msgstr "" msgstr ""
...@@ -3104,7 +3111,7 @@ msgstr "命令执行列表" ...@@ -3104,7 +3111,7 @@ msgstr "命令执行列表"
msgid "Command execution" msgid "Command execution"
msgstr "命令执行" msgstr "命令执行"
#: orgs/mixins/models.py:61 orgs/mixins/serializers.py:26 orgs/models.py:31 #: orgs/mixins/models.py:58 orgs/mixins/serializers.py:26 orgs/models.py:31
msgid "Organization" msgid "Organization"
msgstr "组织" msgstr "组织"
...@@ -3121,7 +3128,7 @@ msgstr "空" ...@@ -3121,7 +3128,7 @@ msgstr "空"
#: perms/templates/perms/asset_permission_list.html:71 #: perms/templates/perms/asset_permission_list.html:71
#: perms/templates/perms/asset_permission_list.html:118 #: perms/templates/perms/asset_permission_list.html:118
#: perms/templates/perms/remote_app_permission_list.html:16 #: perms/templates/perms/remote_app_permission_list.html:16
#: templates/_nav.html:21 users/forms.py:286 users/models/group.py:26 #: templates/_nav.html:21 users/forms.py:293 users/models/group.py:26
#: users/models/user.py:379 users/templates/users/_select_user_modal.html:16 #: users/models/user.py:379 users/templates/users/_select_user_modal.html:16
#: users/templates/users/user_detail.html:218 #: users/templates/users/user_detail.html:218
#: users/templates/users/user_list.html:38 #: users/templates/users/user_list.html:38
...@@ -3968,7 +3975,7 @@ msgid "Commercial support" ...@@ -3968,7 +3975,7 @@ msgid "Commercial support"
msgstr "商业支持" msgstr "商业支持"
#: templates/_header_bar.html:70 templates/_nav.html:30 #: templates/_header_bar.html:70 templates/_nav.html:30
#: templates/_nav_user.html:32 users/forms.py:154 #: templates/_nav_user.html:32 users/forms.py:153
#: users/templates/users/_user.html:43 #: users/templates/users/_user.html:43
#: users/templates/users/first_login.html:39 #: users/templates/users/first_login.html:39
#: users/templates/users/user_password_update.html:40 #: users/templates/users/user_password_update.html:40
...@@ -4389,7 +4396,7 @@ msgstr "线程数" ...@@ -4389,7 +4396,7 @@ msgstr "线程数"
msgid "Boot Time" msgid "Boot Time"
msgstr "运行时间" msgstr "运行时间"
#: terminal/models.py:162 terminal/templates/terminal/session_list.html:136 #: terminal/models.py:162 terminal/templates/terminal/session_list.html:137
msgid "Replay" msgid "Replay"
msgstr "回放" msgstr "回放"
...@@ -4455,15 +4462,15 @@ msgstr "终断所选" ...@@ -4455,15 +4462,15 @@ msgstr "终断所选"
msgid "Confirm finished" msgid "Confirm finished"
msgstr "确认已完成" msgstr "确认已完成"
#: terminal/templates/terminal/session_list.html:91 #: terminal/templates/terminal/session_list.html:92
msgid "Terminate task send, waiting ..." msgid "Terminate task send, waiting ..."
msgstr "终断任务已发送,请等待" msgstr "终断任务已发送,请等待"
#: terminal/templates/terminal/session_list.html:142 #: terminal/templates/terminal/session_list.html:143
msgid "Terminate" msgid "Terminate"
msgstr "终断" msgstr "终断"
#: terminal/templates/terminal/session_list.html:173 #: terminal/templates/terminal/session_list.html:174
msgid "Finish session success" msgid "Finish session success"
msgstr "标记会话完成成功" msgstr "标记会话完成成功"
...@@ -4533,7 +4540,7 @@ msgstr "你可以使用ssh客户端工具连接终端" ...@@ -4533,7 +4540,7 @@ msgstr "你可以使用ssh客户端工具连接终端"
msgid "Could not reset self otp, use profile reset instead" msgid "Could not reset self otp, use profile reset instead"
msgstr "不能再该页面重置MFA, 请去个人信息页面重置" msgstr "不能再该页面重置MFA, 请去个人信息页面重置"
#: users/forms.py:33 users/models/user.py:383 #: users/forms.py:32 users/models/user.py:383
#: users/templates/users/_select_user_modal.html:15 #: users/templates/users/_select_user_modal.html:15
#: users/templates/users/user_detail.html:87 #: users/templates/users/user_detail.html:87
#: users/templates/users/user_list.html:37 #: users/templates/users/user_list.html:37
...@@ -4541,44 +4548,44 @@ msgstr "不能再该页面重置MFA, 请去个人信息页面重置" ...@@ -4541,44 +4548,44 @@ msgstr "不能再该页面重置MFA, 请去个人信息页面重置"
msgid "Role" msgid "Role"
msgstr "角色" msgstr "角色"
#: users/forms.py:36 users/forms.py:233 #: users/forms.py:35 users/forms.py:232
#: users/templates/users/user_update.html:30 #: users/templates/users/user_update.html:30
msgid "ssh public key" msgid "ssh public key"
msgstr "ssh公钥" msgstr "ssh公钥"
#: users/forms.py:37 users/forms.py:234 #: users/forms.py:36 users/forms.py:233
msgid "ssh-rsa AAAA..." msgid "ssh-rsa AAAA..."
msgstr "" msgstr ""
#: users/forms.py:38 #: users/forms.py:37
msgid "Paste user id_rsa.pub here." msgid "Paste user id_rsa.pub here."
msgstr "复制用户公钥到这里" msgstr "复制用户公钥到这里"
#: users/forms.py:52 users/templates/users/user_detail.html:226 #: users/forms.py:51 users/templates/users/user_detail.html:226
msgid "Join user groups" msgid "Join user groups"
msgstr "添加到用户组" msgstr "添加到用户组"
#: users/forms.py:87 users/forms.py:248 #: users/forms.py:86 users/forms.py:247
msgid "Public key should not be the same as your old one." msgid "Public key should not be the same as your old one."
msgstr "不能和原来的密钥相同" msgstr "不能和原来的密钥相同"
#: users/forms.py:91 users/forms.py:252 users/serializers/v1.py:116 #: users/forms.py:90 users/forms.py:251 users/serializers/v1.py:116
msgid "Not a valid ssh public key" msgid "Not a valid ssh public key"
msgstr "ssh密钥不合法" msgstr "ssh密钥不合法"
#: users/forms.py:104 users/views/login.py:114 users/views/user.py:287 #: users/forms.py:103 users/views/login.py:114 users/views/user.py:287
msgid "* Your password does not meet the requirements" msgid "* Your password does not meet the requirements"
msgstr "* 您的密码不符合要求" msgstr "* 您的密码不符合要求"
#: users/forms.py:125 #: users/forms.py:124
msgid "Reset link will be generated and sent to the user" msgid "Reset link will be generated and sent to the user"
msgstr "生成重置密码链接,通过邮件发送给用户" msgstr "生成重置密码链接,通过邮件发送给用户"
#: users/forms.py:126 #: users/forms.py:125
msgid "Set password" msgid "Set password"
msgstr "设置密码" msgstr "设置密码"
#: users/forms.py:133 xpack/plugins/change_auth_plan/models.py:88 #: users/forms.py:132 xpack/plugins/change_auth_plan/models.py:88
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_create_update.html:51 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_create_update.html:51
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:69 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:69
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_list.html:57 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_list.html:57
...@@ -4586,7 +4593,7 @@ msgstr "设置密码" ...@@ -4586,7 +4593,7 @@ msgstr "设置密码"
msgid "Password strategy" msgid "Password strategy"
msgstr "密码策略" msgstr "密码策略"
#: users/forms.py:160 #: users/forms.py:159
msgid "" msgid ""
"When enabled, you will enter the MFA binding process the next time you log " "When enabled, you will enter the MFA binding process the next time you log "
"in. you can also directly bind in \"personal information -> quick " "in. you can also directly bind in \"personal information -> quick "
...@@ -4595,11 +4602,11 @@ msgstr "" ...@@ -4595,11 +4602,11 @@ msgstr ""
"启用之后您将会在下次登录时进入MFA绑定流程;您也可以在(个人信息->快速修改->更" "启用之后您将会在下次登录时进入MFA绑定流程;您也可以在(个人信息->快速修改->更"
"改MFA设置)中直接绑定!" "改MFA设置)中直接绑定!"
#: users/forms.py:170 #: users/forms.py:169
msgid "* Enable MFA authentication to make the account more secure." msgid "* Enable MFA authentication to make the account more secure."
msgstr "* 启用MFA认证,使账号更加安全。" msgstr "* 启用MFA认证,使账号更加安全。"
#: users/forms.py:180 #: users/forms.py:179
msgid "" msgid ""
"In order to protect you and your company, please keep your account, password " "In order to protect you and your company, please keep your account, password "
"and key sensitive information properly. (for example: setting complex " "and key sensitive information properly. (for example: setting complex "
...@@ -4608,41 +4615,41 @@ msgstr "" ...@@ -4608,41 +4615,41 @@ msgstr ""
"为了保护您和公司的安全,请妥善保管您的账户、密码和密钥等重要敏感信息;(如:" "为了保护您和公司的安全,请妥善保管您的账户、密码和密钥等重要敏感信息;(如:"
"设置复杂密码,启用MFA认证)" "设置复杂密码,启用MFA认证)"
#: users/forms.py:187 users/templates/users/first_login.html:48 #: users/forms.py:186 users/templates/users/first_login.html:48
#: users/templates/users/first_login.html:110 #: users/templates/users/first_login.html:110
#: users/templates/users/first_login.html:139 #: users/templates/users/first_login.html:139
msgid "Finish" msgid "Finish"
msgstr "完成" msgstr "完成"
#: users/forms.py:193 #: users/forms.py:192
msgid "Old password" msgid "Old password"
msgstr "原来密码" msgstr "原来密码"
#: users/forms.py:198 #: users/forms.py:197
msgid "New password" msgid "New password"
msgstr "新密码" msgstr "新密码"
#: users/forms.py:203 #: users/forms.py:202
msgid "Confirm password" msgid "Confirm password"
msgstr "确认密码" msgstr "确认密码"
#: users/forms.py:213 #: users/forms.py:212
msgid "Old password error" msgid "Old password error"
msgstr "原来密码错误" msgstr "原来密码错误"
#: users/forms.py:221 #: users/forms.py:220
msgid "Password does not match" msgid "Password does not match"
msgstr "密码不一致" msgstr "密码不一致"
#: users/forms.py:231 #: users/forms.py:230
msgid "Automatically configure and download the SSH key" msgid "Automatically configure and download the SSH key"
msgstr "自动配置并下载SSH密钥" msgstr "自动配置并下载SSH密钥"
#: users/forms.py:235 #: users/forms.py:234
msgid "Paste your id_rsa.pub here." msgid "Paste your id_rsa.pub here."
msgstr "复制你的公钥到这里" msgstr "复制你的公钥到这里"
#: users/forms.py:269 users/forms.py:274 users/forms.py:316 #: users/forms.py:268 users/forms.py:273 users/forms.py:323
#: xpack/plugins/orgs/forms.py:18 #: xpack/plugins/orgs/forms.py:18
msgid "Select users" msgid "Select users"
msgstr "选择用户" msgstr "选择用户"
...@@ -4735,7 +4742,7 @@ msgstr "角色只能为 {}" ...@@ -4735,7 +4742,7 @@ msgstr "角色只能为 {}"
msgid "Password does not match security rules" msgid "Password does not match security rules"
msgstr "密码不满足安全规则" msgstr "密码不满足安全规则"
#: users/serializers/v1.py:147 #: users/serializers/v1.py:157
msgid "Auditors cannot be join in the user group" msgid "Auditors cannot be join in the user group"
msgstr "审计员不能被加入到用户组" msgstr "审计员不能被加入到用户组"
...@@ -5932,7 +5939,7 @@ msgstr "更新同步实例任务" ...@@ -5932,7 +5939,7 @@ msgstr "更新同步实例任务"
#: xpack/plugins/gathered_user/views.py:21 #: xpack/plugins/gathered_user/views.py:21
#: xpack/plugins/gathered_user/views.py:34 #: xpack/plugins/gathered_user/views.py:34
#: xpack/plugins/gathered_user/views.py:49 #: xpack/plugins/gathered_user/views.py:49
#: xpack/plugins/gathered_user/views.py:66 #: xpack/plugins/gathered_user/views.py:69
msgid "Gathered user" msgid "Gathered user"
msgstr "收集用户" msgstr "收集用户"
...@@ -5967,7 +5974,7 @@ msgstr "创建任务" ...@@ -5967,7 +5974,7 @@ msgstr "创建任务"
msgid "Gathered user list" msgid "Gathered user list"
msgstr "收集用户列表" msgstr "收集用户列表"
#: xpack/plugins/gathered_user/views.py:67 #: xpack/plugins/gathered_user/views.py:70
msgid "Update task" msgid "Update task"
msgstr "更新任务" msgstr "更新任务"
......
...@@ -10,7 +10,7 @@ from ..models import Organization ...@@ -10,7 +10,7 @@ from ..models import Organization
__all__ = [ __all__ = [
'RootOrgViewMixin', 'OrgMembershipModelViewSetMixin', 'OrgModelViewSet', 'RootOrgViewMixin', 'OrgMembershipModelViewSetMixin', 'OrgModelViewSet',
'OrgBulkModelViewSet', 'OrgBulkModelViewSet', 'OrgQuerySetMixin',
] ]
...@@ -22,8 +22,14 @@ class RootOrgViewMixin: ...@@ -22,8 +22,14 @@ class RootOrgViewMixin:
class OrgQuerySetMixin: class OrgQuerySetMixin:
def get_queryset(self): def get_queryset(self):
queryset = super().get_queryset() if hasattr(self, 'model'):
queryset = filter_org_queryset(queryset) 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]
......
# -*- 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
...@@ -8,7 +8,7 @@ from django.core.exceptions import ValidationError ...@@ -8,7 +8,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,
filter_org_queryset, filter_org_queryset
) )
from ..models import Organization from ..models import Organization
...@@ -48,9 +48,12 @@ class OrgModelMixin(models.Model): ...@@ -48,9 +48,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)
......
...@@ -83,17 +83,23 @@ def tmp_to_org(org): ...@@ -83,17 +83,23 @@ def tmp_to_org(org):
set_current_org(ori_org) set_current_org(ori_org)
def filter_org_queryset(queryset): def get_org_filters():
kwargs = {} kwargs = {}
_current_org = get_current_org() _current_org = get_current_org()
if _current_org is None: if _current_org is None:
return queryset.none() return kwargs
if _current_org.is_real(): if _current_org.is_real():
kwargs['org_id'] = _current_org.id kwargs['org_id'] = _current_org.id
elif _current_org.is_default(): elif _current_org.is_default():
kwargs["org_id"] = '' kwargs["org_id"] = ''
return kwargs
def filter_org_queryset(queryset):
kwargs = get_org_filters()
# #
# lines = traceback.format_stack() # lines = traceback.format_stack()
# print(">>>>>>>>>>>>>>>>>>>>>>>>>>>>") # print(">>>>>>>>>>>>>>>>>>>>>>>>>>>>")
......
# -*- 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
......
...@@ -271,7 +271,7 @@ function requestApi(props) { ...@@ -271,7 +271,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) {
...@@ -960,8 +960,13 @@ function initPopover($container, $progress, $idPassword, $el, password_check_rul ...@@ -960,8 +960,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];
var $rootNodeRef = $("#" + rootNode.tId + "_a"); if (rootNode) {
$rootNodeRef.after(refreshIcon); var $rootNodeRef = $("#" + rootNode.tId + "_a");
$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,7 +24,7 @@ logger = get_logger(__name__) ...@@ -24,7 +24,7 @@ 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, )
filterset_fields = [ filterset_fields = [
......
# -*- 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 () {
......
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
{% bootstrap_field form.comment layout="horizontal" %} {% bootstrap_field form.comment layout="horizontal" %}
<div class="form-group"> <div class="form-group">
<div class="col-sm-4 col-sm-offset-2"> <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> <button id="submit_button" class="btn btn-primary" type="submit">{% trans 'Confirm' %}</button>
</div> </div>
</div> </div>
......
...@@ -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