diff --git a/apps/reports/api/assets/activity.py b/apps/reports/api/assets/activity.py index 7fbfb4cb3..0b262e48f 100644 --- a/apps/reports/api/assets/activity.py +++ b/apps/reports/api/assets/activity.py @@ -2,7 +2,7 @@ # from collections import defaultdict -from django.db.models import Count, Q +from django.db.models import Count from django.http.response import JsonResponse from rest_framework.views import APIView @@ -29,9 +29,9 @@ class AssetActivityApi(DateRangeMixin, APIView): def get_asset_login_metrics(self, queryset): data = defaultdict(set) - for t, asset in queryset.values_list('date_start', 'asset'): + for t, _id in queryset.values_list('date_start', 'id'): date_str = str(t.date()) - data[date_str].add(asset) + data[date_str].add(_id) metrics = [len(data.get(str(d), set())) for d in self.date_range_list] return metrics @@ -47,35 +47,32 @@ class AssetActivityApi(DateRangeMixin, APIView): stats = qs.aggregate( total=Count(1), - asset_online=Count(1, filter=Q(is_finished=False)), asset_count=Count('asset_id', distinct=True), user_count=Count('user_id', distinct=True), - is_success_count=Count(1, filter=Q(is_success=True)), ) asset_ids = {str(_id) for _id in qs.values_list('asset_id', flat=True).distinct()} assets = Asset.objects.filter(id__in=asset_ids) asset_login_by_protocol = group_stats( - qs, 'protocol_label', 'protocol' + qs, 'label', 'protocol' ) asset_login_by_from = group_stats( - qs, 'login_from_label', 'login_from', LoginFrom.as_dict() + qs, 'label', 'login_from', LoginFrom.as_dict() ) asset_by_type = group_stats( - assets, 'type', 'platform__type', all_type_dict, + assets, 'label', 'platform__type', all_type_dict, ) - dates_metrics_date = [date.strftime('%m-%d') for date in self.date_range_list] or ['0'] payload = { - **stats, + 'session_stats': stats, 'asset_login_by_type': asset_by_type, 'asset_login_by_from': asset_login_by_from, 'asset_login_by_protocol': asset_login_by_protocol, 'asset_login_log_metrics': { - 'dates_metrics_date': dates_metrics_date, + 'dates_metrics_date': self.dates_metrics_date, 'dates_metrics_total': self.get_asset_login_metrics(qs), } } diff --git a/apps/reports/api/assets/asset.py b/apps/reports/api/assets/asset.py index 212f8b6e0..e58a9f814 100644 --- a/apps/reports/api/assets/asset.py +++ b/apps/reports/api/assets/asset.py @@ -1,22 +1,23 @@ # -*- coding: utf-8 -*- # +from collections import defaultdict, OrderedDict from django.db.models import Count, Q from django.http import JsonResponse -from django.utils import timezone from rest_framework.views import APIView -from assets.const import AllTypes, Connectivity, Category +from assets.const import AllTypes, Connectivity from assets.models import Asset, Platform from common.permissions import IsValidLicense from common.utils import lazyproperty from rbac.permissions import RBACPermission from reports.api.assets.base import group_stats +from reports.mixins import DateRangeMixin __all__ = ['AssetStatisticApi'] -class AssetStatisticApi(APIView): +class AssetStatisticApi(DateRangeMixin, APIView): http_method_names = ['get'] # TODO: Define the required RBAC permissions for this API rbac_perms = { @@ -26,49 +27,60 @@ class AssetStatisticApi(APIView): @lazyproperty def base_qs(self): - return Asset.objects.only( - 'id', 'platform', 'zone', 'connectivity', 'is_active' - ) + return Asset.objects.all() + + def get_added_asset_metrics(self): + filtered_queryset = self.filter_by_date_range(self.base_qs, 'date_created') + + data = defaultdict(set) + for t, _id in filtered_queryset.values_list('date_created', 'id'): + date_str = str(t.date()) + data[date_str].add(_id) + + metrics = [len(data.get(str(d), set())) for d in self.date_range_list] + return metrics def get(self, request, *args, **kwargs): qs = self.base_qs all_type_dict = dict(AllTypes.choices()) - platform_by_type = group_stats( - Platform.objects.all(), 'type_label', 'type', all_type_dict, - ) - stats = qs.aggregate( total=Count(1), active=Count(1, filter=Q(is_active=True)), connected=Count(1, filter=Q(connectivity=Connectivity.OK)), + zone=Count(1, filter=Q(zone__isnull=False)), + directory_services=Count(1, filter=Q(directory_services__isnull=False)), ) + type_category_map = { + d['label']: str(d['category'].label) + for d in AllTypes.types() + } + by_type = group_stats( qs, 'type', 'platform__type', all_type_dict, ) - by_category = group_stats( - qs, 'category', 'platform__category', Category.as_dict() - ) + by_type_category = defaultdict(list) + for item in by_type: + category = type_category_map.get(item['label'], 'Other') + by_type_category[category].append(item) - by_zone = group_stats( - qs, 'zone_label', 'zone__name' - ) + sorted_category_assets = OrderedDict() + desired_order = [str(i['label']) for i in AllTypes.categories()] + for category in desired_order: + sorted_category_assets[category] = by_type_category.get(category, []) - week_start = timezone.now() + timezone.timedelta(days=7) - assets_added_this_week_qs = qs.filter(date_created__gte=week_start) - assets_added_this_week_by_type = group_stats( - assets_added_this_week_qs, 'type', 'platform__type', all_type_dict, - ) + stats.update({ + 'platform_count': Platform.objects.all().count(), + }) payload = { - **stats, - 'platform_by_type': platform_by_type, - 'assets_by_type': by_type, - 'assets_by_category': by_category, - 'assets_by_zone': by_zone, - 'assets_added_this_week_count': assets_added_this_week_qs.count(), - 'assets_added_this_week_by_type': assets_added_this_week_by_type, + 'asset_stats': stats, + 'assets_by_type_category': sorted_category_assets, + 'added_asset_metrics': { + 'dates_metrics_date': self.dates_metrics_date, + 'dates_metrics_total': self.get_added_asset_metrics(), + } } return JsonResponse(payload, status=200) diff --git a/apps/reports/api/users/change_password.py b/apps/reports/api/users/change_password.py index 1ac780d42..8ac5a4338 100644 --- a/apps/reports/api/users/change_password.py +++ b/apps/reports/api/users/change_password.py @@ -59,7 +59,6 @@ class UserChangeSecretApi(DateRangeMixin, APIView): def get(self, request, *args, **kwargs): data = {} - dates_metrics_date = [date.strftime('%m-%d') for date in self.date_range_list] or ['0'] qs = self.filter_by_date_range(self.change_password_queryset, 'datetime') @@ -80,7 +79,7 @@ class UserChangeSecretApi(DateRangeMixin, APIView): data['change_password_top10_change_bys'] = list(change_password_top10_change_bys) data['user_change_password_metrics'] = { - 'dates_metrics_date': dates_metrics_date, + 'dates_metrics_date': self.dates_metrics_date, 'dates_metrics_total': self.get_change_password_metrics(qs), } diff --git a/apps/reports/api/users/user.py b/apps/reports/api/users/user.py index ab3d973da..6ca02104d 100644 --- a/apps/reports/api/users/user.py +++ b/apps/reports/api/users/user.py @@ -89,18 +89,17 @@ class UserReportApi(DateRangeMixin, APIView): def get(self, request, *args, **kwargs): data = {} - dates_metrics_date = [date.strftime('%m-%d') for date in self.date_range_list] or ['0'] data['user_login_log_metrics'] = { - 'dates_metrics_date': dates_metrics_date, + 'dates_metrics_date': self.dates_metrics_date, 'dates_metrics_total': self.get_user_login_metrics(self.user_login_log_queryset), } data['user_login_failed_metrics'] = { - 'dates_metrics_date': dates_metrics_date, + 'dates_metrics_date': self.dates_metrics_date, 'dates_metrics_total': self.get_user_login_metrics(self.user_login_failed_queryset), } data['user_login_method_metrics'] = { - 'dates_metrics_date': dates_metrics_date, + 'dates_metrics_date': self.dates_metrics_date, 'dates_metrics_total': self.get_user_login_method_metrics(), } data['user_login_region_distribution'] = self.get_user_login_region_distribution() diff --git a/apps/reports/mixins.py b/apps/reports/mixins.py index b7564d282..d618a4ed0 100644 --- a/apps/reports/mixins.py +++ b/apps/reports/mixins.py @@ -40,3 +40,7 @@ class DateRangeMixin: def filter_by_date_range(self, queryset, field_name: str): start, end = self.date_range_bounds return queryset.filter(**{f'{field_name}__range': (start, end)}) + + @lazyproperty + def dates_metrics_date(self): + return [date.strftime('%m-%d') for date in self.date_range_list] or ['0']