diff --git a/apps/audits/api.py b/apps/audits/api.py index 3da41d463..9a023e3dd 100644 --- a/apps/audits/api.py +++ b/apps/audits/api.py @@ -3,7 +3,10 @@ from rest_framework.mixins import ListModelMixin, CreateModelMixin from django.db.models import F, Value from django.db.models.functions import Concat +from rest_framework.permissions import IsAuthenticated +from rest_framework import generics +from common.drf.api import JMSReadOnlyModelViewSet from common.drf.filters import DatetimeRangeFilter from common.api import CommonGenericViewSet from orgs.mixins.api import OrgGenericViewSet, OrgBulkModelViewSet, OrgRelationMixin @@ -28,7 +31,7 @@ class FTPLogViewSet(CreateModelMixin, ordering = ['-date_start'] -class UserLoginLogViewSet(ListModelMixin, CommonGenericViewSet): +class UserLoginCommonMixin: queryset = UserLoginLog.objects.all() serializer_class = UserLoginLogSerializer extra_filter_backends = [DatetimeRangeFilter] @@ -38,6 +41,9 @@ class UserLoginLogViewSet(ListModelMixin, CommonGenericViewSet): filterset_fields = ['username', 'ip', 'city', 'type', 'status', 'mfa'] search_fields = ['username', 'ip', 'city'] + +class UserLoginLogViewSet(UserLoginCommonMixin, ListModelMixin, CommonGenericViewSet): + @staticmethod def get_org_members(): users = current_org.get_members().values_list('username', flat=True) @@ -52,6 +58,15 @@ class UserLoginLogViewSet(ListModelMixin, CommonGenericViewSet): return queryset +class MyLoginLogAPIView(UserLoginCommonMixin, generics.ListAPIView): + permission_classes = [IsAuthenticated] + + def get_queryset(self): + qs = super().get_queryset() + qs = qs.filter(username=self.request.user.username) + return qs + + class OperateLogViewSet(ListModelMixin, OrgGenericViewSet): model = OperateLog serializer_class = OperateLogSerializer diff --git a/apps/audits/urls/api_urls.py b/apps/audits/urls/api_urls.py index 8cc822706..7301b67fb 100644 --- a/apps/audits/urls/api_urls.py +++ b/apps/audits/urls/api_urls.py @@ -1,7 +1,7 @@ # ~*~ coding: utf-8 ~*~ from __future__ import unicode_literals -from django.urls.conf import re_path +from django.urls.conf import re_path, path from rest_framework.routers import DefaultRouter from common import api as capi @@ -20,6 +20,7 @@ router.register(r'command-executions-hosts-relations', api.CommandExecutionHostR urlpatterns = [ + path('my-login-logs/', api.MyLoginLogAPIView.as_view(), name='my-login-log'), ] old_version_urlpatterns = [ diff --git a/apps/terminal/api/session.py b/apps/terminal/api/session.py index fcb7bcf53..6bc76bd81 100644 --- a/apps/terminal/api/session.py +++ b/apps/terminal/api/session.py @@ -3,6 +3,7 @@ import os import tarfile +from django.db.models import F, Max from django.shortcuts import get_object_or_404, reverse from django.utils.translation import ugettext as _ from django.utils.encoding import escape_uri_path @@ -11,8 +12,11 @@ from django.core.files.storage import default_storage from rest_framework import viewsets, views from rest_framework.response import Response from rest_framework.decorators import action +from rest_framework.permissions import IsAuthenticated +from rest_framework import generics from common.utils import data_to_json +from assets.models import Asset from common.const.http import GET from common.utils import get_logger, get_object_or_none from common.mixins.api import AsyncApiMixin @@ -26,14 +30,63 @@ from ..utils import find_session_replay_local, download_session_replay from ..models import Session from .. import serializers from terminal.utils import is_session_approver +from assets.serializers import AssetSerializer __all__ = [ - 'SessionViewSet', 'SessionReplayViewSet', 'SessionJoinValidateAPI' + 'SessionViewSet', 'SessionReplayViewSet', 'SessionJoinValidateAPI', + 'MySessionAPIView', 'MySessionAssetAPIView', ] logger = get_logger(__name__) +class MySessionAPIView(generics.ListAPIView): + permission_classes = (IsAuthenticated, ) + serializer_class = serializers.SessionSerializer + + def get_queryset(self): + with tmp_to_root_org(): + user = self.request.user + qs = Session.objects.filter(user_id=user.id) + return qs + + +class MySessionAssetAPIView(generics.ListAPIView): + queryset = Asset.objects.all() + permission_classes = (IsAuthenticated, ) + serializer_class = AssetSerializer + + def list(self, request, *args, **kwargs): + with tmp_to_root_org(): + user = self.request.user + + asset_ids = Session.objects.filter(user_id=user.id).exclude( + asset_id='' # xrdp bug 没有提交 asset_id,已修复,但要兼容旧数据 + ).values_list('asset_id').annotate( + max_date_start=Max(F('date_start')) + ).order_by('-max_date_start').values_list('asset_id', flat=True) + page = self.paginate_queryset(asset_ids) + if page is not None: + serializer = self._to_serializer(page) + return self.get_paginated_response(serializer.data) + + serializer = self._to_serializer(asset_ids) + return Response(serializer.data) + + def _to_serializer(self, asset_ids): + assets_qs = Asset.objects.filter(id__in=list(asset_ids)) + serializer_cls = self.get_serializer_class() + if hasattr(serializer_cls, 'setup_eager_loading'): + assets_qs = serializer_cls.setup_eager_loading(assets_qs) + + id_asset_map = {str(asset.id): asset for asset in assets_qs} + assets = [] + for i in asset_ids: + assets.append(id_asset_map[i]) + serializer = self.get_serializer(assets, many=True) + return serializer + + class SessionViewSet(OrgBulkModelViewSet): model = Session serializer_classes = { diff --git a/apps/terminal/urls/api_urls.py b/apps/terminal/urls/api_urls.py index b071e8134..f03ba083a 100644 --- a/apps/terminal/urls/api_urls.py +++ b/apps/terminal/urls/api_urls.py @@ -24,6 +24,8 @@ router.register(r'session-sharings', api.SessionSharingViewSet, 'session-sharing router.register(r'session-join-records', api.SessionJoinRecordsViewSet, 'session-sharing-record') urlpatterns = [ + path('my-login-assets/', api.MySessionAssetAPIView.as_view(), name='my-login-asset'), + path('my-sessions/', api.MySessionAPIView.as_view(), name='my-session'), path('terminal-registrations/', api.TerminalRegistrationApi.as_view(), name='terminal-registration'), path('registration/', api.TerminalRegistrationApi.as_view(), name='registration'), path('sessions/join/validate/', api.SessionJoinValidateAPI.as_view(), name='join-session-validate'),