mirror of https://github.com/jumpserver/jumpserver
				
				
				
			[feature] 添加 login-logs API
							parent
							
								
									1b1a686b96
								
							
						
					
					
						commit
						f4eca83a49
					
				| 
						 | 
				
			
			@ -1,10 +1,16 @@
 | 
			
		|||
# -*- coding: utf-8 -*-
 | 
			
		||||
#
 | 
			
		||||
from rest_framework.viewsets import GenericViewSet
 | 
			
		||||
from rest_framework.mixins import ListModelMixin
 | 
			
		||||
from django.db.models import Q
 | 
			
		||||
 | 
			
		||||
from common.permissions import IsOrgAdminOrAppUser, IsOrgAuditor
 | 
			
		||||
from common.mixins.api import CommonApiMixin
 | 
			
		||||
from common.permissions import IsOrgAdminOrAppUser, IsOrgAuditor, IsOrgAdmin
 | 
			
		||||
from common.drf.filters import DatetimeRangeFilter
 | 
			
		||||
from orgs.mixins.api import OrgModelViewSet
 | 
			
		||||
from .models import FTPLog
 | 
			
		||||
from .serializers import FTPLogSerializer
 | 
			
		||||
from orgs.utils import current_org
 | 
			
		||||
from .models import FTPLog, UserLoginLog
 | 
			
		||||
from .serializers import FTPLogSerializer, UserLoginLogSerializer
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class FTPLogViewSet(OrgModelViewSet):
 | 
			
		||||
| 
						 | 
				
			
			@ -12,3 +18,29 @@ class FTPLogViewSet(OrgModelViewSet):
 | 
			
		|||
    serializer_class = FTPLogSerializer
 | 
			
		||||
    permission_classes = (IsOrgAdminOrAppUser | IsOrgAuditor,)
 | 
			
		||||
    http_method_names = ['get', 'post', 'head', 'options']
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class UserLoginLogViewSet(CommonApiMixin,
 | 
			
		||||
                          ListModelMixin,
 | 
			
		||||
                          GenericViewSet):
 | 
			
		||||
    queryset = UserLoginLog.objects.all()
 | 
			
		||||
    permission_classes = [IsOrgAdmin | IsOrgAuditor]
 | 
			
		||||
    serializer_class = UserLoginLogSerializer
 | 
			
		||||
    extra_filter_backends = [DatetimeRangeFilter]
 | 
			
		||||
    date_range_filter_fields = [
 | 
			
		||||
        ('datetime', ('date_from', 'date_to'))
 | 
			
		||||
    ]
 | 
			
		||||
    filterset_fields = ['username']
 | 
			
		||||
    search_fields = ['ip', 'city', 'username']
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def get_org_members():
 | 
			
		||||
        users = current_org.get_org_members().values_list('username', flat=True)
 | 
			
		||||
        return users
 | 
			
		||||
 | 
			
		||||
    def get_queryset(self):
 | 
			
		||||
        queryset = super().get_queryset()
 | 
			
		||||
        if not current_org.is_default():
 | 
			
		||||
            users = self.get_org_members()
 | 
			
		||||
            queryset = queryset.filter(username__in=users)
 | 
			
		||||
        return queryset
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -14,10 +14,13 @@ class FTPLogSerializer(serializers.ModelSerializer):
 | 
			
		|||
        fields = '__all__'
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class LoginLogSerializer(serializers.ModelSerializer):
 | 
			
		||||
class UserLoginLogSerializer(serializers.ModelSerializer):
 | 
			
		||||
    class Meta:
 | 
			
		||||
        model = models.UserLoginLog
 | 
			
		||||
        fields = '__all__'
 | 
			
		||||
        fields = (
 | 
			
		||||
            'username', 'type', 'ip', 'city', 'user_agent',
 | 
			
		||||
            'mfa', 'reason', 'status', 'datetime'
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class OperateLogSerializer(serializers.ModelSerializer):
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -12,6 +12,7 @@ app_name = "audits"
 | 
			
		|||
 | 
			
		||||
router = DefaultRouter()
 | 
			
		||||
router.register(r'ftp-logs', api.FTPLogViewSet, 'ftp-log')
 | 
			
		||||
router.register(r'login-logs', api.UserLoginLogViewSet, 'login-log')
 | 
			
		||||
 | 
			
		||||
urlpatterns = [
 | 
			
		||||
]
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,7 +4,9 @@ import coreapi
 | 
			
		|||
from rest_framework import filters
 | 
			
		||||
from rest_framework.fields import DateTimeField
 | 
			
		||||
from rest_framework.serializers import ValidationError
 | 
			
		||||
from rest_framework.compat import coreapi, coreschema
 | 
			
		||||
from django.core.cache import cache
 | 
			
		||||
from django.core.exceptions import ImproperlyConfigured
 | 
			
		||||
import logging
 | 
			
		||||
 | 
			
		||||
from common import const
 | 
			
		||||
| 
						 | 
				
			
			@ -13,15 +15,48 @@ __all__ = ["DatetimeRangeFilter", "IDSpmFilter", "CustomFilter"]
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
class DatetimeRangeFilter(filters.BaseFilterBackend):
 | 
			
		||||
    def filter_queryset(self, request, queryset, view):
 | 
			
		||||
    def get_schema_fields(self, view):
 | 
			
		||||
        ret = []
 | 
			
		||||
        fields = self._get_date_range_filter_fields(view)
 | 
			
		||||
 | 
			
		||||
        for attr, date_range_keyword in fields.items():
 | 
			
		||||
            if len(date_range_keyword) != 2:
 | 
			
		||||
                continue
 | 
			
		||||
            for v in date_range_keyword:
 | 
			
		||||
                ret.append(
 | 
			
		||||
                    coreapi.Field(
 | 
			
		||||
                        name=v, location='query', required=False, type='string',
 | 
			
		||||
                        schema=coreschema.String(
 | 
			
		||||
                            title=v,
 | 
			
		||||
                            description='%s %s' % (attr, v)
 | 
			
		||||
                        )
 | 
			
		||||
                    )
 | 
			
		||||
                )
 | 
			
		||||
 | 
			
		||||
        return ret
 | 
			
		||||
 | 
			
		||||
    def _get_date_range_filter_fields(self, view):
 | 
			
		||||
        if not hasattr(view, 'date_range_filter_fields'):
 | 
			
		||||
            return queryset
 | 
			
		||||
            return {}
 | 
			
		||||
        try:
 | 
			
		||||
            fields = dict(view.date_range_filter_fields)
 | 
			
		||||
            return dict(view.date_range_filter_fields)
 | 
			
		||||
        except ValueError:
 | 
			
		||||
            msg = "View {} datetime_filter_fields set is error".format(view.name)
 | 
			
		||||
            msg = """
 | 
			
		||||
                View {} `date_range_filter_fields` set is improperly.
 | 
			
		||||
                For example:
 | 
			
		||||
                ```
 | 
			
		||||
                    class ExampleView:
 | 
			
		||||
                        date_range_filter_fields = [
 | 
			
		||||
                            ('db column', ('query param date from', 'query param date to'))
 | 
			
		||||
                        ]
 | 
			
		||||
                ```
 | 
			
		||||
            """.format(view.name)
 | 
			
		||||
            logging.error(msg)
 | 
			
		||||
            return queryset
 | 
			
		||||
            raise ImproperlyConfigured(msg)
 | 
			
		||||
 | 
			
		||||
    def filter_queryset(self, request, queryset, view):
 | 
			
		||||
        fields = self._get_date_range_filter_fields(view)
 | 
			
		||||
 | 
			
		||||
        kwargs = {}
 | 
			
		||||
        for attr, date_range_keyword in fields.items():
 | 
			
		||||
            if len(date_range_keyword) != 2:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -36,5 +36,3 @@ class DatetimeSearchMixin:
 | 
			
		|||
    def get(self, request, *args, **kwargs):
 | 
			
		||||
        self.get_date_range()
 | 
			
		||||
        return super().get(request, *args, **kwargs)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue