Merge pull request #3954 from xuxinwen/feature-audits-apis

[Feature] 添加 login-logs API
pull/3960/head
老广 2020-04-30 03:52:57 -05:00 committed by GitHub
commit 962763dc7b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 81 additions and 12 deletions

View File

@ -1,10 +1,16 @@
# -*- coding: utf-8 -*- # -*- 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 orgs.mixins.api import OrgModelViewSet
from .models import FTPLog from orgs.utils import current_org
from .serializers import FTPLogSerializer from .models import FTPLog, UserLoginLog
from .serializers import FTPLogSerializer, UserLoginLogSerializer
class FTPLogViewSet(OrgModelViewSet): class FTPLogViewSet(OrgModelViewSet):
@ -12,3 +18,29 @@ class FTPLogViewSet(OrgModelViewSet):
serializer_class = FTPLogSerializer serializer_class = FTPLogSerializer
permission_classes = (IsOrgAdminOrAppUser | IsOrgAuditor,) permission_classes = (IsOrgAdminOrAppUser | IsOrgAuditor,)
http_method_names = ['get', 'post', 'head', 'options'] 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

View File

@ -14,10 +14,13 @@ class FTPLogSerializer(serializers.ModelSerializer):
fields = '__all__' fields = '__all__'
class LoginLogSerializer(serializers.ModelSerializer): class UserLoginLogSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = models.UserLoginLog model = models.UserLoginLog
fields = '__all__' fields = (
'username', 'type', 'ip', 'city', 'user_agent',
'mfa', 'reason', 'status', 'datetime'
)
class OperateLogSerializer(serializers.ModelSerializer): class OperateLogSerializer(serializers.ModelSerializer):

View File

@ -12,6 +12,7 @@ app_name = "audits"
router = DefaultRouter() router = DefaultRouter()
router.register(r'ftp-logs', api.FTPLogViewSet, 'ftp-log') router.register(r'ftp-logs', api.FTPLogViewSet, 'ftp-log')
router.register(r'login-logs', api.UserLoginLogViewSet, 'login-log')
urlpatterns = [ urlpatterns = [
] ]

View File

@ -4,7 +4,9 @@ import coreapi
from rest_framework import filters from rest_framework import filters
from rest_framework.fields import DateTimeField from rest_framework.fields import DateTimeField
from rest_framework.serializers import ValidationError from rest_framework.serializers import ValidationError
from rest_framework.compat import coreapi, coreschema
from django.core.cache import cache from django.core.cache import cache
from django.core.exceptions import ImproperlyConfigured
import logging import logging
from common import const from common import const
@ -13,15 +15,48 @@ __all__ = ["DatetimeRangeFilter", "IDSpmFilter", 'IDInFilter', "CustomFilter"]
class DatetimeRangeFilter(filters.BaseFilterBackend): 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'): if not hasattr(view, 'date_range_filter_fields'):
return queryset return {}
try: try:
fields = dict(view.date_range_filter_fields) return dict(view.date_range_filter_fields)
except ValueError: 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) logging.error(msg)
return queryset raise ImproperlyConfigured(msg)
def filter_queryset(self, request, queryset, view):
fields = self._get_date_range_filter_fields(view)
kwargs = {} kwargs = {}
for attr, date_range_keyword in fields.items(): for attr, date_range_keyword in fields.items():
if len(date_range_keyword) != 2: if len(date_range_keyword) != 2:

View File

@ -36,5 +36,3 @@ class DatetimeSearchMixin:
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):
self.get_date_range() self.get_date_range()
return super().get(request, *args, **kwargs) return super().get(request, *args, **kwargs)