diff --git a/apps/assets/models/node.py b/apps/assets/models/node.py index 968ea2c68..517996086 100644 --- a/apps/assets/models/node.py +++ b/apps/assets/models/node.py @@ -209,7 +209,7 @@ class Node(OrgModelMixin): set_current_org(Organization.root()) org_nodes_roots = cls.objects.filter(key__regex=r'^[0-9]+$') org_nodes_roots_keys = org_nodes_roots.values_list('key', flat=True) or [0] - key = max([int(k) for k in org_nodes_roots_keys]) + 1 + key = str(max([int(k) for k in org_nodes_roots_keys]) + 1) set_current_org(_current_org) root = cls.objects.create(key=key, value=_current_org.name) return root diff --git a/apps/common/permissions.py b/apps/common/permissions.py index 827d388c1..20554e071 100644 --- a/apps/common/permissions.py +++ b/apps/common/permissions.py @@ -86,9 +86,7 @@ class AdminUserRequiredMixin(UserPassesTestMixin): return redirect('orgs:switch-a-org') if not current_org.can_admin_by(request.user): - print("{} cannot admin {}".format(request.user, current_org)) if request.user.is_org_admin: - print("Is org admin") return redirect('orgs:switch-a-org') return HttpResponseForbidden() return super().dispatch(request, *args, **kwargs) diff --git a/apps/jumpserver/views.py b/apps/jumpserver/views.py index 2d90d2047..d70225582 100644 --- a/apps/jumpserver/views.py +++ b/apps/jumpserver/views.py @@ -28,6 +28,8 @@ class IndexView(LoginRequiredMixin, TemplateView): return self.handle_no_permission() if not request.user.is_org_admin: return redirect('assets:user-asset-list') + if not current_org or not current_org.can_admin_by(request.user): + return redirect('orgs:switch-a-org') return super(IndexView, self).dispatch(request, *args, **kwargs) @staticmethod diff --git a/apps/orgs/mixins.py b/apps/orgs/mixins.py index a7ccfa223..29ec794f1 100644 --- a/apps/orgs/mixins.py +++ b/apps/orgs/mixins.py @@ -148,14 +148,12 @@ class OrgModelMixin(models.Model): class OrgViewGenericMixin: def dispatch(self, request, *args, **kwargs): - print("Current org: {}".format(current_org)) if not current_org: return redirect('orgs:switch-a-org') if not current_org.can_admin_by(request.user): print("{} cannot admin {}".format(request.user, current_org)) if request.user.is_org_admin: - print("Is org admin") return redirect('orgs:switch-a-org') return HttpResponseForbidden() else: diff --git a/apps/perms/api.py b/apps/perms/api.py index c0edc09f2..bfc22bf4d 100644 --- a/apps/perms/api.py +++ b/apps/perms/api.py @@ -6,13 +6,14 @@ from rest_framework.views import APIView, Response from rest_framework.generics import ListAPIView, get_object_or_404, RetrieveUpdateAPIView from rest_framework import viewsets -from common.utils import set_or_append_attr_bulk, get_object_or_none +from common.utils import set_or_append_attr_bulk from common.permissions import IsValidUser, IsOrgAdmin, IsOrgAdminOrAppUser from orgs.mixins import RootOrgViewMixin from .utils import AssetPermissionUtil from .models import AssetPermission from .hands import AssetGrantedSerializer, User, UserGroup, Asset, Node, \ NodeGrantedSerializer, SystemUser, NodeSerializer +from orgs.utils import set_to_root_org from . import serializers @@ -55,14 +56,21 @@ class AssetPermissionViewSet(viewsets.ModelViewSet): return permissions -class UserGrantedAssetsApi(RootOrgViewMixin, ListAPIView): +class UserGrantedAssetsApi(ListAPIView): """ 用户授权的所有资产 """ permission_classes = (IsOrgAdminOrAppUser,) serializer_class = AssetGrantedSerializer - + + def change_org_if_need(self): + if self.request.user.is_superuser or \ + self.request.user.is_app or \ + self.kwargs.get('pk') is None: + set_to_root_org() + def get_queryset(self): + self.change_org_if_need() user_id = self.kwargs.get('pk', '') queryset = [] @@ -84,11 +92,21 @@ class UserGrantedAssetsApi(RootOrgViewMixin, ListAPIView): return super().get_permissions() -class UserGrantedNodesApi(RootOrgViewMixin, ListAPIView): +class UserGrantedNodesApi(ListAPIView): + """ + 查询用户授权的所有节点的API, 如果是超级用户或者是 app,切换到root org + """ permission_classes = (IsOrgAdmin,) serializer_class = NodeSerializer + + def change_org_if_need(self): + if self.request.user.is_superuser or \ + self.request.user.is_app or \ + self.kwargs.get('pk') is None: + set_to_root_org() def get_queryset(self): + self.change_org_if_need() user_id = self.kwargs.get('pk', '') if user_id: user = get_object_or_404(User, id=user_id) @@ -104,11 +122,21 @@ class UserGrantedNodesApi(RootOrgViewMixin, ListAPIView): return super().get_permissions() -class UserGrantedNodesWithAssetsApi(RootOrgViewMixin, ListAPIView): +class UserGrantedNodesWithAssetsApi(ListAPIView): + """ + 用户授权的节点并带着节点下资产的api + """ permission_classes = (IsOrgAdminOrAppUser,) serializer_class = NodeGrantedSerializer + + def change_org_if_need(self): + if self.request.user.is_superuser or \ + self.request.user.is_app or \ + self.kwargs.get('pk') is None: + set_to_root_org() def get_queryset(self): + self.change_org_if_need() user_id = self.kwargs.get('pk', '') queryset = [] if not user_id: @@ -133,11 +161,21 @@ class UserGrantedNodesWithAssetsApi(RootOrgViewMixin, ListAPIView): return super().get_permissions() -class UserGrantedNodeAssetsApi(RootOrgViewMixin, ListAPIView): +class UserGrantedNodeAssetsApi(ListAPIView): + """ + 查询用户授权的节点下的资产的api, 与上面api不同的是,只返回某个节点下的资产 + """ permission_classes = (IsOrgAdminOrAppUser,) serializer_class = AssetGrantedSerializer + + def change_org_if_need(self): + if self.request.user.is_superuser or \ + self.request.user.is_app or \ + self.kwargs.get('pk') is None: + set_to_root_org() def get_queryset(self): + self.change_org_if_need() user_id = self.kwargs.get('pk', '') node_id = self.kwargs.get('node_id') diff --git a/apps/users/api/auth.py b/apps/users/api/auth.py index f9ac158d6..4abd2839b 100644 --- a/apps/users/api/auth.py +++ b/apps/users/api/auth.py @@ -12,19 +12,21 @@ from rest_framework.response import Response from rest_framework.views import APIView from common.utils import get_logger, get_request_ip +from common.permissions import IsOrgAdminOrAppUser +from orgs.mixins import RootOrgViewMixin from ..serializers import UserSerializer from ..tasks import write_login_log_async from ..models import User, LoginLog from ..utils import check_user_valid, generate_token, \ - check_otp_code, increase_login_failed_count, is_block_login, clean_failed_count -from common.permissions import IsOrgAdminOrAppUser + check_otp_code, increase_login_failed_count, is_block_login, \ + clean_failed_count from ..hands import Asset, SystemUser logger = get_logger(__name__) -class UserAuthApi(APIView): +class UserAuthApi(RootOrgViewMixin, APIView): permission_classes = (AllowAny,) serializer_class = UserSerializer @@ -112,7 +114,7 @@ class UserAuthApi(APIView): write_login_log_async.delay(**data) -class UserConnectionTokenApi(APIView): +class UserConnectionTokenApi(RootOrgViewMixin, APIView): permission_classes = (IsOrgAdminOrAppUser,) def post(self, request): @@ -176,7 +178,7 @@ class UserToken(APIView): return Response({'error': msg}, status=406) -class UserOtpAuthApi(APIView): +class UserOtpAuthApi(RootOrgViewMixin, APIView): permission_classes = (AllowAny,) serializer_class = UserSerializer diff --git a/utils/disable_user_mfa.py b/utils/disable_user_mfa.py new file mode 100644 index 000000000..ba98a9db8 --- /dev/null +++ b/utils/disable_user_mfa.py @@ -0,0 +1,24 @@ +#!/bin/bash +# + +username=$1 + +if [ -z "${username}" ];then + echo "No username specify, exit" + exit 1 +fi + +function disable_user_mfa() { +python ../apps/manage.py shell << EOF +import sys +from users.models import User +user = User.objects.filter(username="${username}") +if not user: + print("No user found") + sys.exit(1) +user.update(otp_level=0) +print("Disable user ${username} success") +EOF +} + +disable_user_mfa