• 八千流's avatar
    超级管理员可创建超级审计员并可设置审计员为组织审计员 (#3141) · a2376d3a
    八千流 authored
    * [Update] 超级管理员可创建超级审计员并可设置审计员为组织审计员
    
    * [Update] 修改小问题
    
    * [Update] 修改普通用户角色可以是组织审计员
    
    * [Update] 更改组织审计员切换组织问题
    
    * [Update] 修改小问题
    
    * [Update] 普通用户是组织审计员的页面左侧栏显示
    
    * [Update] 修改删除权限问题和组织显示问题
    
    * [Update] 优化逻辑
    
    * [Update] 优化类名
    
    * [Update] 修改小问题
    
    * [Update] 优化逻辑
    
    * [Update] 优化切换到某一个组织逻辑
    
    * [Update] 修改用户详情页的 删除/更新 按钮是否可点击
    
    * [Update] 优化代码
    
    * [Update] 组织管理列表增加审计员显示
    
    * [Update] 优化代码细节
    
    * [Update] 优化权限类逻辑
    
    * [Update] 优化导航菜单控制
    
    * [Update] 优化页面控制逻辑
    
    * [Update] 修改变量名错误问题
    
    * [Update] 修改页面上的小问题
    
    * [Update] 审计员或组织审计员能够更新个人部分信息
    
    * [Update] 用户名为admin的用户不能被删除
    
    * [Update] 不同用户在不同组织下扮演不同角色的权限不同,为了避免切换组织时出现403,重定向到index
    
    * [Update] 一个用户在同一个组织既是管理员又是审计员,隐藏个人信息模块,仅当是审计员,在当前组织显示个人信息模块
    
    * [Update] 修改方法命名
    
    * [Update] 优化代码细节
    
    * [Update] 修改命令执行列表方法
    
    * [Update] 优化用户之间操作的权限逻辑;添加 UserModel 的 property 属性;修改 Organization 的 related name 名称;
    
    * [Update] 修改OrgProcessor Anonymous问题
    
    * [Update] 修改用户序列类校验组织和转换raw密码的逻辑
    a2376d3a
views.py 10.2 KB
import csv
import json
import uuid
import codecs


from django.conf import settings
from django.urls import reverse
from django.utils import timezone
from django.core.cache import cache
from django.http import HttpResponse, JsonResponse
from django.utils.decorators import method_decorator
from django.views import View
from django.views.decorators.csrf import csrf_exempt
from django.views.generic import ListView
from django.utils.translation import ugettext as _
from django.db.models import Q

from audits.utils import get_excel_response, write_content_to_excel
from common.mixins import DatetimeSearchMixin
from common.permissions import (
    PermissionsMixin, IsOrgAdmin, IsValidUser, IsOrgAuditor
)
from orgs.utils import current_org
from ops.views import CommandExecutionListView as UserCommandExecutionListView
from .models import FTPLog, OperateLog, PasswordChangeLog, UserLoginLog


def get_resource_type_list():
    from users.models import User, UserGroup
    from assets.models import (
        Asset, Node, AdminUser, SystemUser, Domain, Gateway, CommandFilter,
        CommandFilterRule,
    )
    from orgs.models import Organization
    from perms.models import AssetPermission

    models = [
        User, UserGroup, Asset, Node, AdminUser, SystemUser, Domain,
        Gateway, Organization, AssetPermission, CommandFilter, CommandFilterRule
    ]
    return [model._meta.verbose_name for model in models]


class FTPLogListView(PermissionsMixin, DatetimeSearchMixin, ListView):
    model = FTPLog
    template_name = 'audits/ftp_log_list.html'
    paginate_by = settings.DISPLAY_PER_PAGE
    user = asset = system_user = filename = ''
    date_from = date_to = None
    permission_classes = [IsOrgAdmin | IsOrgAuditor]

    def get_queryset(self):
        self.queryset = super().get_queryset()
        self.user = self.request.GET.get('user')
        self.asset = self.request.GET.get('asset')
        self.system_user = self.request.GET.get('system_user')
        self.filename = self.request.GET.get('filename', '')

        filter_kwargs = dict()
        filter_kwargs['date_start__gt'] = self.date_from
        filter_kwargs['date_start__lt'] = self.date_to
        if self.user:
            filter_kwargs['user'] = self.user
        if self.asset:
            filter_kwargs['asset'] = self.asset
        if self.system_user:
            filter_kwargs['system_user'] = self.system_user
        if self.filename:
            filter_kwargs['filename__contains'] = self.filename
        if filter_kwargs:
            self.queryset = self.queryset.filter(**filter_kwargs).order_by('-date_start')
        return self.queryset

    def get_context_data(self, **kwargs):
        context = {
            'user_list': FTPLog.objects.values_list('user', flat=True).distinct(),
            'asset_list': FTPLog.objects.values_list('asset', flat=True).distinct(),
            'system_user_list': FTPLog.objects.values_list('system_user', flat=True).distinct(),
            'date_from': self.date_from,
            'date_to': self.date_to,
            'user': self.user,
            'asset': self.asset,
            'system_user': self.system_user,
            'filename': self.filename,
            "app": _("Audits"),
            "action": _("FTP log"),
        }
        kwargs.update(context)
        return super().get_context_data(**kwargs)


class OperateLogListView(PermissionsMixin, DatetimeSearchMixin, ListView):
    model = OperateLog
    template_name = 'audits/operate_log_list.html'
    paginate_by = settings.DISPLAY_PER_PAGE
    user = action = resource_type = ''
    date_from = date_to = None
    actions_dict = dict(OperateLog.ACTION_CHOICES)
    permission_classes = [IsOrgAdmin | IsOrgAuditor]

    def get_queryset(self):
        self.queryset = super().get_queryset()
        self.user = self.request.GET.get('user')
        self.action = self.request.GET.get('action')
        self.resource_type = self.request.GET.get('resource_type')

        filter_kwargs = dict()
        filter_kwargs['datetime__gt'] = self.date_from
        filter_kwargs['datetime__lt'] = self.date_to
        if self.user:
            filter_kwargs['user'] = self.user
        if self.action:
            filter_kwargs['action'] = self.action
        if self.resource_type:
            filter_kwargs['resource_type'] = self.resource_type
        if filter_kwargs:
            self.queryset = self.queryset.filter(**filter_kwargs).order_by('-datetime')
        return self.queryset

    def get_context_data(self, **kwargs):
        context = {
            'user_list': current_org.get_org_members(),
            'actions': self.actions_dict,
            'resource_type_list': get_resource_type_list(),
            'date_from': self.date_from,
            'date_to': self.date_to,
            'user': self.user,
            'resource_type': self.resource_type,
            "app": _("Audits"),
            "action": _("Operate log"),
        }
        kwargs.update(context)
        return super().get_context_data(**kwargs)


class PasswordChangeLogList(PermissionsMixin, DatetimeSearchMixin, ListView):
    model = PasswordChangeLog
    template_name = 'audits/password_change_log_list.html'
    paginate_by = settings.DISPLAY_PER_PAGE
    user = ''
    date_from = date_to = None
    permission_classes = [IsOrgAdmin | IsOrgAuditor]

    def get_queryset(self):
        users = current_org.get_org_members()
        self.queryset = super().get_queryset().filter(
            user__in=[user.__str__() for user in users]
        )
        self.user = self.request.GET.get('user')

        filter_kwargs = dict()
        filter_kwargs['datetime__gt'] = self.date_from
        filter_kwargs['datetime__lt'] = self.date_to
        if self.user:
            filter_kwargs['user'] = self.user
        if filter_kwargs:
            self.queryset = self.queryset.filter(**filter_kwargs).order_by('-datetime')
        return self.queryset

    def get_context_data(self, **kwargs):
        context = {
            'user_list': current_org.get_org_members(),
            'date_from': self.date_from,
            'date_to': self.date_to,
            'user': self.user,
            "app": _("Audits"),
            "action": _("Password change log"),
        }
        kwargs.update(context)
        return super().get_context_data(**kwargs)


class LoginLogListView(PermissionsMixin, DatetimeSearchMixin, ListView):
    template_name = 'audits/login_log_list.html'
    model = UserLoginLog
    paginate_by = settings.DISPLAY_PER_PAGE
    user = keyword = ""
    date_to = date_from = None
    permission_classes = [IsOrgAdmin | IsOrgAuditor]

    @staticmethod
    def get_org_members():
        users = current_org.get_org_members().values_list('username', flat=True)
        return users

    def get_queryset(self):
        if current_org.is_default():
            queryset = super().get_queryset()
        else:
            users = self.get_org_members()
            queryset = super().get_queryset().filter(username__in=users)

        self.user = self.request.GET.get('user', '')
        self.keyword = self.request.GET.get("keyword", '')

        queryset = queryset.filter(
            datetime__gt=self.date_from, datetime__lt=self.date_to
        )
        if self.user:
            queryset = queryset.filter(username=self.user)
        if self.keyword:
            queryset = queryset.filter(
                Q(ip__contains=self.keyword) |
                Q(city__contains=self.keyword) |
                Q(username__contains=self.keyword)
            )
        return queryset

    def get_context_data(self, **kwargs):
        context = {
            'app': _('Audits'),
            'action': _('Login log'),
            'date_from': self.date_from,
            'date_to': self.date_to,
            'user': self.user,
            'keyword': self.keyword,
            'user_list': self.get_org_members(),
        }
        kwargs.update(context)
        return super().get_context_data(**kwargs)


class CommandExecutionListView(UserCommandExecutionListView):
    user_id = None

    def get_user_list(self):
        users = current_org.get_org_members(exclude=('Auditor',))
        return users

    def get_queryset(self):
        queryset = self._get_queryset()
        self.user_id = self.request.GET.get('user')
        org_users = self.get_user_list()
        if self.user_id:
            queryset = queryset.filter(user=self.user_id)
        else:
            queryset = queryset.filter(user__in=org_users)
        return queryset

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context.update({
            'app': _('Audits'),
            'action': _('Command execution log'),
            'date_from': self.date_from,
            'date_to': self.date_to,
            'user_list': self.get_user_list(),
            'keyword': self.keyword,
            'user_id': self.user_id,
        })
        return context


@method_decorator(csrf_exempt, name='dispatch')
class LoginLogExportView(PermissionsMixin, View):
    permission_classes = [IsValidUser]

    def get(self, request):
        fields = [
            field for field in UserLoginLog._meta.fields
        ]
        filename = 'login-logs-{}.csv'.format(
            timezone.localtime(timezone.now()).strftime('%Y-%m-%d_%H-%M-%S')
        )
        excel_response = get_excel_response(filename)
        header = [field.verbose_name for field in fields]
        login_logs = cache.get(request.GET.get('spm', ''), [])

        response = write_content_to_excel(excel_response, login_logs=login_logs,
                                          header=header, fields=fields)
        return response

    def post(self, request):
        try:
            date_form = json.loads(request.body).get('date_form', [])
            date_to = json.loads(request.body).get('date_to', [])
            user = json.loads(request.body).get('user', [])
            keyword = json.loads(request.body).get('keyword', [])

            login_logs = UserLoginLog.get_login_logs(
                date_form=date_form, date_to=date_to, user=user, keyword=keyword)
        except ValueError:
            return HttpResponse('Json object not valid', status=400)
        spm = uuid.uuid4().hex
        cache.set(spm, login_logs, 300)
        url = reverse('audits:login-log-export') + '?spm=%s' % spm
        return JsonResponse({'redirect': url})