mirror of https://github.com/jumpserver/jumpserver
				
				
				
			
						commit
						2d48c8028b
					
				| 
						 | 
				
			
			@ -76,14 +76,9 @@ class TreeService(Tree):
 | 
			
		|||
            ancestor_ids.pop(0)
 | 
			
		||||
        return ancestor_ids
 | 
			
		||||
 | 
			
		||||
    def ancestors(self, nid, with_self=False, deep=False, with_assets=True):
 | 
			
		||||
    def ancestors(self, nid, with_self=False, deep=False):
 | 
			
		||||
        ancestor_ids = self.ancestors_ids(nid, with_self=with_self)
 | 
			
		||||
        ancestors = [self.get_node(i, deep=deep) for i in ancestor_ids]
 | 
			
		||||
        if with_assets:
 | 
			
		||||
            return ancestors
 | 
			
		||||
        for n in ancestors:
 | 
			
		||||
            n.data['assets'] = set()
 | 
			
		||||
            n.data['all_assets'] = None
 | 
			
		||||
        return ancestors
 | 
			
		||||
 | 
			
		||||
    def get_node_full_tag(self, nid):
 | 
			
		||||
| 
						 | 
				
			
			@ -108,6 +103,7 @@ class TreeService(Tree):
 | 
			
		|||
        node = super().get_node(nid)
 | 
			
		||||
        if deep:
 | 
			
		||||
            node = self.copy_node(node)
 | 
			
		||||
            node.data = {}
 | 
			
		||||
        return node
 | 
			
		||||
 | 
			
		||||
    def parent(self, nid, deep=False):
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,295 @@
 | 
			
		|||
from django.core.cache import cache
 | 
			
		||||
from django.utils import timezone
 | 
			
		||||
from django.utils.timesince import timesince
 | 
			
		||||
from django.db.models import Count, Max
 | 
			
		||||
from django.http.response import JsonResponse
 | 
			
		||||
from rest_framework.views import APIView
 | 
			
		||||
from collections import Counter
 | 
			
		||||
 | 
			
		||||
from users.models import User
 | 
			
		||||
from assets.models import Asset
 | 
			
		||||
from terminal.models import Session
 | 
			
		||||
from orgs.utils import current_org
 | 
			
		||||
from common.permissions import IsOrgAdmin
 | 
			
		||||
from common.utils import lazyproperty
 | 
			
		||||
 | 
			
		||||
__all__ = ['IndexApi']
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class MonthLoginMetricMixin:
 | 
			
		||||
 | 
			
		||||
    @lazyproperty
 | 
			
		||||
    def session_month(self):
 | 
			
		||||
        month_ago = timezone.now() - timezone.timedelta(days=30)
 | 
			
		||||
        session_month = Session.objects.filter(date_start__gt=month_ago)
 | 
			
		||||
        return session_month
 | 
			
		||||
 | 
			
		||||
    @lazyproperty
 | 
			
		||||
    def session_month_dates(self):
 | 
			
		||||
        dates = self.session_month.dates('date_start', 'day')
 | 
			
		||||
        return dates
 | 
			
		||||
 | 
			
		||||
    def get_month_metrics_date(self):
 | 
			
		||||
        month_metrics_date = [d.strftime('%m-%d') for d in self.session_month_dates] or ['0']
 | 
			
		||||
        return month_metrics_date
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def get_cache_key(date, tp):
 | 
			
		||||
        date_str = date.strftime("%Y%m%d")
 | 
			
		||||
        key = "SESSION_MONTH_{}_{}".format(tp, date_str)
 | 
			
		||||
        return key
 | 
			
		||||
 | 
			
		||||
    def __get_data_from_cache(self, date, tp):
 | 
			
		||||
        if date == timezone.now().date():
 | 
			
		||||
            return None
 | 
			
		||||
        cache_key = self.get_cache_key(date, tp)
 | 
			
		||||
        count = cache.get(cache_key)
 | 
			
		||||
        return count
 | 
			
		||||
 | 
			
		||||
    def __set_data_to_cache(self, date, tp, count):
 | 
			
		||||
        cache_key = self.get_cache_key(date, tp)
 | 
			
		||||
        cache.set(cache_key, count, 3600*24*7)
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def get_date_start_2_end(d):
 | 
			
		||||
        time_min = timezone.datetime.min.time()
 | 
			
		||||
        time_max = timezone.datetime.max.time()
 | 
			
		||||
        tz = timezone.get_current_timezone()
 | 
			
		||||
        ds = timezone.datetime.combine(d, time_min).replace(tzinfo=tz)
 | 
			
		||||
        de = timezone.datetime.combine(d, time_max).replace(tzinfo=tz)
 | 
			
		||||
        return ds, de
 | 
			
		||||
 | 
			
		||||
    def get_date_login_count(self, date):
 | 
			
		||||
        tp = "LOGIN"
 | 
			
		||||
        count = self.__get_data_from_cache(date, tp)
 | 
			
		||||
        if count is not None:
 | 
			
		||||
            return count
 | 
			
		||||
        ds, de = self.get_date_start_2_end(date)
 | 
			
		||||
        count = Session.objects.filter(date_start__range=(ds, de)).count()
 | 
			
		||||
        self.__set_data_to_cache(date, tp, count)
 | 
			
		||||
        return count
 | 
			
		||||
 | 
			
		||||
    def get_month_metrics_total_count_login(self):
 | 
			
		||||
        data = []
 | 
			
		||||
        for d in self.session_month_dates:
 | 
			
		||||
            count = self.get_date_login_count(d)
 | 
			
		||||
            data.append(count)
 | 
			
		||||
        if len(data) == 0:
 | 
			
		||||
            data = [0]
 | 
			
		||||
        return data
 | 
			
		||||
 | 
			
		||||
    def get_date_user_count(self, date):
 | 
			
		||||
        tp = "USER"
 | 
			
		||||
        count = self.__get_data_from_cache(date, tp)
 | 
			
		||||
        if count is not None:
 | 
			
		||||
            return count
 | 
			
		||||
        ds, de = self.get_date_start_2_end(date)
 | 
			
		||||
        count = len(set(Session.objects.filter(date_start__range=(ds, de)).values_list('user', flat=True)))
 | 
			
		||||
        self.__set_data_to_cache(date, tp, count)
 | 
			
		||||
        return count
 | 
			
		||||
 | 
			
		||||
    def get_month_metrics_total_count_active_users(self):
 | 
			
		||||
        data = []
 | 
			
		||||
        for d in self.session_month_dates:
 | 
			
		||||
            count = self.get_date_user_count(d)
 | 
			
		||||
            data.append(count)
 | 
			
		||||
        return data
 | 
			
		||||
 | 
			
		||||
    def get_date_asset_count(self, date):
 | 
			
		||||
        tp = "ASSET"
 | 
			
		||||
        count = self.__get_data_from_cache(date, tp)
 | 
			
		||||
        if count is not None:
 | 
			
		||||
            return count
 | 
			
		||||
        ds, de = self.get_date_start_2_end(date)
 | 
			
		||||
        count = len(set(Session.objects.filter(date_start__range=(ds, de)).values_list('asset', flat=True)))
 | 
			
		||||
        self.__set_data_to_cache(date, tp, count)
 | 
			
		||||
        return count
 | 
			
		||||
 | 
			
		||||
    def get_month_metrics_total_count_active_assets(self):
 | 
			
		||||
        data = []
 | 
			
		||||
        for d in self.session_month_dates:
 | 
			
		||||
            count = self.get_date_asset_count(d)
 | 
			
		||||
            data.append(count)
 | 
			
		||||
        return data
 | 
			
		||||
 | 
			
		||||
    @lazyproperty
 | 
			
		||||
    def month_total_count_active_users(self):
 | 
			
		||||
        count = len(set(self.session_month.values_list('user', flat=True)))
 | 
			
		||||
        return count
 | 
			
		||||
 | 
			
		||||
    @lazyproperty
 | 
			
		||||
    def month_total_count_inactive_users(self):
 | 
			
		||||
        total = current_org.get_org_members().count()
 | 
			
		||||
        active = self.month_total_count_active_users
 | 
			
		||||
        count = total - active
 | 
			
		||||
        if count < 0:
 | 
			
		||||
            count = 0
 | 
			
		||||
        return count
 | 
			
		||||
 | 
			
		||||
    @lazyproperty
 | 
			
		||||
    def month_total_count_disabled_users(self):
 | 
			
		||||
        return current_org.get_org_members().filter(is_active=False).count()
 | 
			
		||||
 | 
			
		||||
    @lazyproperty
 | 
			
		||||
    def month_total_count_active_assets(self):
 | 
			
		||||
        return len(set(self.session_month.values_list('asset', flat=True)))
 | 
			
		||||
 | 
			
		||||
    @lazyproperty
 | 
			
		||||
    def month_total_count_inactive_assets(self):
 | 
			
		||||
        total = Asset.objects.all().count()
 | 
			
		||||
        active = self.month_total_count_active_assets
 | 
			
		||||
        count = total - active
 | 
			
		||||
        if count < 0:
 | 
			
		||||
            count = 0
 | 
			
		||||
        return count
 | 
			
		||||
 | 
			
		||||
    @lazyproperty
 | 
			
		||||
    def month_total_count_disabled_assets(self):
 | 
			
		||||
        return Asset.objects.filter(is_active=False).count()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class WeekSessionMetricMixin:
 | 
			
		||||
    session_week = None
 | 
			
		||||
 | 
			
		||||
    @lazyproperty
 | 
			
		||||
    def session_week(self):
 | 
			
		||||
        week_ago = timezone.now() - timezone.timedelta(weeks=1)
 | 
			
		||||
        session_week = Session.objects.filter(date_start__gt=week_ago)
 | 
			
		||||
        return session_week
 | 
			
		||||
 | 
			
		||||
    def get_week_login_times_top5_users(self):
 | 
			
		||||
        users = self.session_week.values_list('user', flat=True)
 | 
			
		||||
        users = [
 | 
			
		||||
            {'user': user, 'total': total}
 | 
			
		||||
            for user, total in Counter(users).most_common(5)
 | 
			
		||||
        ]
 | 
			
		||||
        return users
 | 
			
		||||
 | 
			
		||||
    def get_week_total_count_login_users(self):
 | 
			
		||||
        return len(set(self.session_week.values_list('user', flat=True)))
 | 
			
		||||
 | 
			
		||||
    def get_week_total_count_login_times(self):
 | 
			
		||||
        return self.session_week.count()
 | 
			
		||||
 | 
			
		||||
    def get_week_login_times_top10_assets(self):
 | 
			
		||||
        assets = self.session_week.values("asset")\
 | 
			
		||||
            .annotate(total=Count("asset"))\
 | 
			
		||||
            .annotate(last=Max("date_start")).order_by("-total")[:10]
 | 
			
		||||
        for asset in assets:
 | 
			
		||||
            asset['last'] = str(asset['last'])
 | 
			
		||||
        return list(assets)
 | 
			
		||||
 | 
			
		||||
    def get_week_login_times_top10_users(self):
 | 
			
		||||
        users = self.session_week.values("user") \
 | 
			
		||||
                     .annotate(total=Count("user")) \
 | 
			
		||||
                     .annotate(last=Max("date_start")).order_by("-total")[:10]
 | 
			
		||||
        for user in users:
 | 
			
		||||
            user['last'] = str(user['last'])
 | 
			
		||||
        return list(users)
 | 
			
		||||
 | 
			
		||||
    def get_week_login_record_top10_sessions(self):
 | 
			
		||||
        sessions = self.session_week.order_by('-date_start')[:10]
 | 
			
		||||
        for session in sessions:
 | 
			
		||||
            session.avatar_url = User.get_avatar_url("")
 | 
			
		||||
        sessions = [
 | 
			
		||||
            {
 | 
			
		||||
                'user': session.user,
 | 
			
		||||
                'asset': session.asset,
 | 
			
		||||
                'is_finished': session.is_finished,
 | 
			
		||||
                'date_start': str(session.date_start),
 | 
			
		||||
                'timesince': timesince(session.date_start)
 | 
			
		||||
            }
 | 
			
		||||
            for session in sessions
 | 
			
		||||
        ]
 | 
			
		||||
        return sessions
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class TotalCountMixin:
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def get_total_count_users():
 | 
			
		||||
        return current_org.get_org_members().count()
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def get_total_count_assets():
 | 
			
		||||
        return Asset.objects.all().count()
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def get_total_count_online_users():
 | 
			
		||||
        count = len(set(Session.objects.filter(is_finished=False).values_list('user', flat=True)))
 | 
			
		||||
        return count
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def get_total_count_online_assets():
 | 
			
		||||
        return Session.objects.filter(is_finished=False).count()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class IndexApi(TotalCountMixin, WeekSessionMetricMixin, MonthLoginMetricMixin, APIView):
 | 
			
		||||
    permission_classes = (IsOrgAdmin,)
 | 
			
		||||
    http_method_names = ['get']
 | 
			
		||||
 | 
			
		||||
    def get(self, request, *args, **kwargs):
 | 
			
		||||
        data = {}
 | 
			
		||||
 | 
			
		||||
        query_params = self.request.query_params
 | 
			
		||||
 | 
			
		||||
        _all = query_params.get('all')
 | 
			
		||||
 | 
			
		||||
        if _all or query_params.get('total_count'):
 | 
			
		||||
            data.update({
 | 
			
		||||
                'total_count_assets': self.get_total_count_assets(),
 | 
			
		||||
                'total_count_users': self.get_total_count_users(),
 | 
			
		||||
                'total_count_online_users': self.get_total_count_online_users(),
 | 
			
		||||
                'total_count_online_assets': self.get_total_count_online_assets(),
 | 
			
		||||
            })
 | 
			
		||||
 | 
			
		||||
        if _all or query_params.get('month_metrics'):
 | 
			
		||||
            data.update({
 | 
			
		||||
                'month_metrics_date': self.get_month_metrics_date(),
 | 
			
		||||
                'month_metrics_total_count_login': self.get_month_metrics_total_count_login(),
 | 
			
		||||
                'month_metrics_total_count_active_users': self.get_month_metrics_total_count_active_users(),
 | 
			
		||||
                'month_metrics_total_count_active_assets': self.get_month_metrics_total_count_active_assets(),
 | 
			
		||||
            })
 | 
			
		||||
 | 
			
		||||
        if _all or query_params.get('month_total_count_users'):
 | 
			
		||||
            data.update({
 | 
			
		||||
                'month_total_count_active_users': self.month_total_count_active_users,
 | 
			
		||||
                'month_total_count_inactive_users': self.month_total_count_inactive_users,
 | 
			
		||||
                'month_total_count_disabled_users': self.month_total_count_disabled_users,
 | 
			
		||||
            })
 | 
			
		||||
 | 
			
		||||
        if _all or query_params.get('month_total_count_assets'):
 | 
			
		||||
            data.update({
 | 
			
		||||
                'month_total_count_active_assets': self.month_total_count_active_assets,
 | 
			
		||||
                'month_total_count_inactive_assets': self.month_total_count_inactive_assets,
 | 
			
		||||
                'month_total_count_disabled_assets': self.month_total_count_disabled_assets,
 | 
			
		||||
            })
 | 
			
		||||
 | 
			
		||||
        if _all or query_params.get('week_total_count'):
 | 
			
		||||
            data.update({
 | 
			
		||||
                'week_total_count_login_users': self.get_week_total_count_login_users(),
 | 
			
		||||
                'week_total_count_login_times': self.get_week_total_count_login_times(),
 | 
			
		||||
            })
 | 
			
		||||
 | 
			
		||||
        if _all or query_params.get('week_login_times_top5_users'):
 | 
			
		||||
            data.update({
 | 
			
		||||
                'week_login_times_top5_users': self.get_week_login_times_top5_users(),
 | 
			
		||||
            })
 | 
			
		||||
 | 
			
		||||
        if _all or query_params.get('week_login_times_top10_assets'):
 | 
			
		||||
            data.update({
 | 
			
		||||
                'week_login_times_top10_assets': self.get_week_login_times_top10_assets(),
 | 
			
		||||
            })
 | 
			
		||||
 | 
			
		||||
        if _all or query_params.get('week_login_times_top10_users'):
 | 
			
		||||
            data.update({
 | 
			
		||||
                'week_login_times_top10_users': self.get_week_login_times_top10_users(),
 | 
			
		||||
            })
 | 
			
		||||
 | 
			
		||||
        if _all or query_params.get('week_login_record_top10_sessions'):
 | 
			
		||||
            data.update({
 | 
			
		||||
                'week_login_record_top10_sessions': self.get_week_login_record_top10_sessions()
 | 
			
		||||
            })
 | 
			
		||||
 | 
			
		||||
        return JsonResponse(data, status=200)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -7,9 +7,10 @@ from django.conf.urls.static import static
 | 
			
		|||
from django.conf.urls.i18n import i18n_patterns
 | 
			
		||||
from django.views.i18n import JavaScriptCatalog
 | 
			
		||||
 | 
			
		||||
from . import views
 | 
			
		||||
from . import views, api
 | 
			
		||||
 | 
			
		||||
api_v1 = [
 | 
			
		||||
    path('index/', api.IndexApi.as_view()),
 | 
			
		||||
    path('users/', include('users.urls.api_urls', namespace='api-users')),
 | 
			
		||||
    path('assets/', include('assets.urls.api_urls', namespace='api-assets')),
 | 
			
		||||
    path('perms/', include('perms.urls.api_urls', namespace='api-perms')),
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,224 +1,12 @@
 | 
			
		|||
from django.core.cache import cache
 | 
			
		||||
from django.views.generic import TemplateView
 | 
			
		||||
from django.utils import timezone
 | 
			
		||||
from django.utils.translation import ugettext_lazy as _
 | 
			
		||||
from django.db.models import Count, Max
 | 
			
		||||
from django.shortcuts import redirect
 | 
			
		||||
 | 
			
		||||
from users.models import User
 | 
			
		||||
from assets.models import Asset
 | 
			
		||||
from terminal.models import Session
 | 
			
		||||
from orgs.utils import current_org
 | 
			
		||||
from common.permissions import PermissionsMixin, IsValidUser
 | 
			
		||||
from common.utils import timeit, lazyproperty
 | 
			
		||||
 | 
			
		||||
__all__ = ['IndexView']
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class MonthLoginMetricMixin:
 | 
			
		||||
    @lazyproperty
 | 
			
		||||
    def session_month(self):
 | 
			
		||||
        month_ago = timezone.now() - timezone.timedelta(days=30)
 | 
			
		||||
        session_month = Session.objects.filter(date_start__gt=month_ago)
 | 
			
		||||
        return session_month
 | 
			
		||||
 | 
			
		||||
    @lazyproperty
 | 
			
		||||
    def session_month_dates(self):
 | 
			
		||||
        dates = self.session_month.dates('date_start', 'day')
 | 
			
		||||
        return dates
 | 
			
		||||
 | 
			
		||||
    def get_month_day_metrics(self):
 | 
			
		||||
        month_str = [
 | 
			
		||||
            d.strftime('%m-%d') for d in self.session_month_dates
 | 
			
		||||
        ] or ['0']
 | 
			
		||||
        return month_str
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def get_cache_key(date, tp):
 | 
			
		||||
        date_str = date.strftime("%Y%m%d")
 | 
			
		||||
        key = "SESSION_MONTH_{}_{}_{}".format(current_org.id, tp, date_str)
 | 
			
		||||
        return key
 | 
			
		||||
 | 
			
		||||
    def __get_data_from_cache(self, date, tp):
 | 
			
		||||
        if date == timezone.now().date():
 | 
			
		||||
            return None
 | 
			
		||||
        cache_key = self.get_cache_key(date, tp)
 | 
			
		||||
        count = cache.get(cache_key)
 | 
			
		||||
        return count
 | 
			
		||||
 | 
			
		||||
    def __set_data_to_cache(self, date, tp, count):
 | 
			
		||||
        cache_key = self.get_cache_key(date, tp)
 | 
			
		||||
        cache.set(cache_key, count, 3600*24*7)
 | 
			
		||||
 | 
			
		||||
    @lazyproperty
 | 
			
		||||
    def user_disabled_total(self):
 | 
			
		||||
        return current_org.get_org_members().filter(is_active=False).count()
 | 
			
		||||
 | 
			
		||||
    @lazyproperty
 | 
			
		||||
    def asset_disabled_total(self):
 | 
			
		||||
        return Asset.objects.filter(is_active=False).count()
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def get_date_start_2_end(d):
 | 
			
		||||
        time_min = timezone.datetime.min.time()
 | 
			
		||||
        time_max = timezone.datetime.max.time()
 | 
			
		||||
        tz = timezone.get_current_timezone()
 | 
			
		||||
        ds = timezone.datetime.combine(d, time_min).replace(tzinfo=tz)
 | 
			
		||||
        de = timezone.datetime.combine(d, time_max).replace(tzinfo=tz)
 | 
			
		||||
        return ds, de
 | 
			
		||||
 | 
			
		||||
    def get_date_login_count(self, date):
 | 
			
		||||
        tp = "LOGIN"
 | 
			
		||||
        count = self.__get_data_from_cache(date, tp)
 | 
			
		||||
        if count is not None:
 | 
			
		||||
            return count
 | 
			
		||||
        ds, de = self.get_date_start_2_end(date)
 | 
			
		||||
        count = Session.objects.filter(date_start__range=(ds, de)).count()
 | 
			
		||||
        self.__set_data_to_cache(date, tp, count)
 | 
			
		||||
        return count
 | 
			
		||||
 | 
			
		||||
    def get_month_login_metrics(self):
 | 
			
		||||
        data = []
 | 
			
		||||
        for d in self.session_month_dates:
 | 
			
		||||
            count = self.get_date_login_count(d)
 | 
			
		||||
            data.append(count)
 | 
			
		||||
        if len(data) == 0:
 | 
			
		||||
            data = [0]
 | 
			
		||||
        return data
 | 
			
		||||
 | 
			
		||||
    def get_date_user_count(self, date):
 | 
			
		||||
        tp = "USER"
 | 
			
		||||
        count = self.__get_data_from_cache(date, tp)
 | 
			
		||||
        if count is not None:
 | 
			
		||||
            return count
 | 
			
		||||
        ds, de = self.get_date_start_2_end(date)
 | 
			
		||||
        count = Session.objects.filter(date_start__range=(ds, de))\
 | 
			
		||||
            .values('user').distinct().count()
 | 
			
		||||
        self.__set_data_to_cache(date, tp, count)
 | 
			
		||||
        return count
 | 
			
		||||
 | 
			
		||||
    def get_month_active_user_metrics(self):
 | 
			
		||||
        data = []
 | 
			
		||||
        for d in self.session_month_dates:
 | 
			
		||||
            count = self.get_date_user_count(d)
 | 
			
		||||
            data.append(count)
 | 
			
		||||
        return data
 | 
			
		||||
 | 
			
		||||
    def get_date_asset_count(self, date):
 | 
			
		||||
        tp = "ASSET"
 | 
			
		||||
        count = self.__get_data_from_cache(date, tp)
 | 
			
		||||
        if count is not None:
 | 
			
		||||
            return count
 | 
			
		||||
        ds, de = self.get_date_start_2_end(date)
 | 
			
		||||
        count = Session.objects.filter(date_start__range=(ds, de)) \
 | 
			
		||||
            .values('asset').distinct().count()
 | 
			
		||||
        self.__set_data_to_cache(date, tp, count)
 | 
			
		||||
        return count
 | 
			
		||||
 | 
			
		||||
    def get_month_active_asset_metrics(self):
 | 
			
		||||
        data = []
 | 
			
		||||
        for d in self.session_month_dates:
 | 
			
		||||
            count = self.get_date_asset_count(d)
 | 
			
		||||
            data.append(count)
 | 
			
		||||
        return data
 | 
			
		||||
 | 
			
		||||
    @lazyproperty
 | 
			
		||||
    def month_active_user_total(self):
 | 
			
		||||
        count = self.session_month.values('user').distinct().count()
 | 
			
		||||
        return count
 | 
			
		||||
 | 
			
		||||
    @lazyproperty
 | 
			
		||||
    def month_inactive_user_total(self):
 | 
			
		||||
        total = current_org.get_org_members().count()
 | 
			
		||||
        active = self.month_active_user_total
 | 
			
		||||
        count = total - active
 | 
			
		||||
        if count < 0:
 | 
			
		||||
            count = 0
 | 
			
		||||
        return count
 | 
			
		||||
 | 
			
		||||
    @lazyproperty
 | 
			
		||||
    def month_active_asset_total(self):
 | 
			
		||||
        return self.session_month.values('asset').distinct().count()
 | 
			
		||||
 | 
			
		||||
    @lazyproperty
 | 
			
		||||
    def month_inactive_asset_total(self):
 | 
			
		||||
        total = Asset.objects.all().count()
 | 
			
		||||
        active = self.month_active_asset_total
 | 
			
		||||
        count = total - active
 | 
			
		||||
        if count < 0:
 | 
			
		||||
            count = 0
 | 
			
		||||
        return count
 | 
			
		||||
 | 
			
		||||
    def get_context_data(self, **kwargs):
 | 
			
		||||
        context = super().get_context_data(**kwargs)
 | 
			
		||||
        context.update({
 | 
			
		||||
            'month_str': self.get_month_day_metrics(),
 | 
			
		||||
            'month_total_visit_count': self.get_month_login_metrics(),
 | 
			
		||||
            'month_user': self.get_month_active_user_metrics(),
 | 
			
		||||
            'mouth_asset': self.get_month_active_asset_metrics(),
 | 
			
		||||
            'month_user_active': self.month_active_user_total,
 | 
			
		||||
            'month_user_inactive': self.month_inactive_user_total,
 | 
			
		||||
            'month_user_disabled': self.user_disabled_total,
 | 
			
		||||
            'month_asset_active': self.month_active_asset_total,
 | 
			
		||||
            'month_asset_inactive': self.month_inactive_asset_total,
 | 
			
		||||
            'month_asset_disabled': self.asset_disabled_total,
 | 
			
		||||
        })
 | 
			
		||||
        return context
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class WeekSessionMetricMixin:
 | 
			
		||||
    session_week = None
 | 
			
		||||
 | 
			
		||||
    @lazyproperty
 | 
			
		||||
    def session_week(self):
 | 
			
		||||
        week_ago = timezone.now() - timezone.timedelta(weeks=1)
 | 
			
		||||
        session_week = Session.objects.filter(date_start__gt=week_ago)
 | 
			
		||||
        return session_week
 | 
			
		||||
 | 
			
		||||
    def get_top5_user_a_week(self):
 | 
			
		||||
        users = self.session_week.values('user') \
 | 
			
		||||
                    .annotate(total=Count('user')) \
 | 
			
		||||
                    .order_by('-total')[:5]
 | 
			
		||||
        return users
 | 
			
		||||
 | 
			
		||||
    def get_week_login_user_count(self):
 | 
			
		||||
        return self.session_week.values('user').distinct().count()
 | 
			
		||||
 | 
			
		||||
    def get_week_login_asset_count(self):
 | 
			
		||||
        return self.session_week.count()
 | 
			
		||||
 | 
			
		||||
    def get_week_top10_assets(self):
 | 
			
		||||
        assets = self.session_week.values("asset")\
 | 
			
		||||
            .annotate(total=Count("asset"))\
 | 
			
		||||
            .annotate(last=Max("date_start")).order_by("-total")[:10]
 | 
			
		||||
        return assets
 | 
			
		||||
 | 
			
		||||
    def get_week_top10_users(self):
 | 
			
		||||
        users = self.session_week.values("user") \
 | 
			
		||||
                     .annotate(total=Count("user")) \
 | 
			
		||||
                     .annotate(last=Max("date_start")).order_by("-total")[:10]
 | 
			
		||||
        return users
 | 
			
		||||
 | 
			
		||||
    def get_last10_sessions(self):
 | 
			
		||||
        sessions = self.session_week.order_by('-date_start')[:10]
 | 
			
		||||
        for session in sessions:
 | 
			
		||||
            session.avatar_url = User.get_avatar_url("")
 | 
			
		||||
        return sessions
 | 
			
		||||
 | 
			
		||||
    def get_context_data(self, **kwargs):
 | 
			
		||||
        context = super().get_context_data(**kwargs)
 | 
			
		||||
        context.update({
 | 
			
		||||
            'user_visit_count_weekly': self.get_week_login_user_count(),
 | 
			
		||||
            'asset_visit_count_weekly': self.get_week_login_asset_count(),
 | 
			
		||||
            'user_visit_count_top_five': self.get_top5_user_a_week(),
 | 
			
		||||
            'last_login_ten': self.get_last10_sessions(),
 | 
			
		||||
            'week_asset_hot_ten': self.get_week_top10_assets(),
 | 
			
		||||
            'week_user_hot_ten': self.get_week_top10_users(),
 | 
			
		||||
        })
 | 
			
		||||
        return context
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class IndexView(PermissionsMixin, MonthLoginMetricMixin, WeekSessionMetricMixin, TemplateView):
 | 
			
		||||
class IndexView(PermissionsMixin, TemplateView):
 | 
			
		||||
    template_name = 'index.html'
 | 
			
		||||
    permission_classes = [IsValidUser]
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -229,31 +17,9 @@ class IndexView(PermissionsMixin, MonthLoginMetricMixin, WeekSessionMetricMixin,
 | 
			
		|||
            return redirect('assets:user-asset-list')
 | 
			
		||||
        return super(IndexView, self).dispatch(request, *args, **kwargs)
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def get_user_count():
 | 
			
		||||
        return current_org.get_org_members().count()
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def get_asset_count():
 | 
			
		||||
        return Asset.objects.all().count()
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def get_online_user_count():
 | 
			
		||||
        count = Session.objects.filter(is_finished=False)\
 | 
			
		||||
            .values_list('user', flat=True).distinct().count()
 | 
			
		||||
        return count
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def get_online_session_count():
 | 
			
		||||
        return Session.objects.filter(is_finished=False).count()
 | 
			
		||||
 | 
			
		||||
    def get_context_data(self, **kwargs):
 | 
			
		||||
        context = super().get_context_data(**kwargs)
 | 
			
		||||
        context.update({
 | 
			
		||||
            'assets_count': self.get_asset_count(),
 | 
			
		||||
            'users_count': self.get_user_count(),
 | 
			
		||||
            'online_user_count': self.get_online_user_count(),
 | 
			
		||||
            'online_asset_count': self.get_online_session_count(),
 | 
			
		||||
            'app': _("Dashboard"),
 | 
			
		||||
        })
 | 
			
		||||
        return context
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
										
											Binary file not shown.
										
									
								
							| 
						 | 
				
			
			@ -8,7 +8,7 @@ msgid ""
 | 
			
		|||
msgstr ""
 | 
			
		||||
"Project-Id-Version: JumpServer 0.3.3\n"
 | 
			
		||||
"Report-Msgid-Bugs-To: \n"
 | 
			
		||||
"POT-Creation-Date: 2020-04-17 20:49+0800\n"
 | 
			
		||||
"POT-Creation-Date: 2020-05-08 15:42+0800\n"
 | 
			
		||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 | 
			
		||||
"Last-Translator: ibuler <ibuler@qq.com>\n"
 | 
			
		||||
"Language-Team: JumpServer team<ibuler@qq.com>\n"
 | 
			
		||||
| 
						 | 
				
			
			@ -42,7 +42,7 @@ msgstr "自定义"
 | 
			
		|||
#: perms/templates/perms/asset_permission_asset.html:53
 | 
			
		||||
#: perms/templates/perms/asset_permission_create_update.html:57
 | 
			
		||||
#: perms/templates/perms/asset_permission_list.html:35
 | 
			
		||||
#: perms/templates/perms/asset_permission_list.html:87
 | 
			
		||||
#: perms/templates/perms/asset_permission_list.html:87 templates/index.html:82
 | 
			
		||||
#: terminal/backends/command/models.py:19 terminal/models.py:187
 | 
			
		||||
#: terminal/templates/terminal/command_list.html:31
 | 
			
		||||
#: terminal/templates/terminal/command_list.html:106
 | 
			
		||||
| 
						 | 
				
			
			@ -58,7 +58,8 @@ msgstr "自定义"
 | 
			
		|||
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_list.html:54
 | 
			
		||||
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_subtask_list.html:13
 | 
			
		||||
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_list.html:14
 | 
			
		||||
#: xpack/plugins/cloud/models.py:266
 | 
			
		||||
#: xpack/plugins/cloud/models.py:269
 | 
			
		||||
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_create_update.html:37
 | 
			
		||||
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_instance.html:47
 | 
			
		||||
#: xpack/plugins/orgs/templates/orgs/org_list.html:17
 | 
			
		||||
#: xpack/plugins/vault/forms.py:13 xpack/plugins/vault/forms.py:15
 | 
			
		||||
| 
						 | 
				
			
			@ -169,8 +170,9 @@ msgstr "运行参数"
 | 
			
		|||
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:53
 | 
			
		||||
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_list.html:12
 | 
			
		||||
#: xpack/plugins/gathered_user/templates/gathered_user/task_list.html:16
 | 
			
		||||
#: xpack/plugins/orgs/templates/orgs/org_detail.html:47
 | 
			
		||||
#: xpack/plugins/orgs/templates/orgs/org_detail.html:51
 | 
			
		||||
#: xpack/plugins/orgs/templates/orgs/org_list.html:12
 | 
			
		||||
#: xpack/plugins/orgs/templates/orgs/org_users.html:46
 | 
			
		||||
msgid "Name"
 | 
			
		||||
msgstr "名称"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -194,7 +196,7 @@ msgstr "类型"
 | 
			
		|||
#: applications/templates/applications/database_app_detail.html:56
 | 
			
		||||
#: applications/templates/applications/database_app_list.html:25
 | 
			
		||||
#: applications/templates/applications/user_database_app_list.html:18
 | 
			
		||||
#: ops/models/adhoc.py:146 templates/index.html:90
 | 
			
		||||
#: ops/models/adhoc.py:146
 | 
			
		||||
#: users/templates/users/user_granted_database_app.html:36
 | 
			
		||||
msgid "Host"
 | 
			
		||||
msgstr "主机"
 | 
			
		||||
| 
						 | 
				
			
			@ -260,13 +262,13 @@ msgstr "数据库"
 | 
			
		|||
#: xpack/plugins/change_auth_plan/models.py:75
 | 
			
		||||
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:115
 | 
			
		||||
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_list.html:19
 | 
			
		||||
#: xpack/plugins/cloud/models.py:53 xpack/plugins/cloud/models.py:136
 | 
			
		||||
#: xpack/plugins/cloud/models.py:53 xpack/plugins/cloud/models.py:139
 | 
			
		||||
#: xpack/plugins/cloud/templates/cloud/account_detail.html:67
 | 
			
		||||
#: xpack/plugins/cloud/templates/cloud/account_list.html:15
 | 
			
		||||
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:102
 | 
			
		||||
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:128
 | 
			
		||||
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_list.html:18
 | 
			
		||||
#: xpack/plugins/gathered_user/models.py:26
 | 
			
		||||
#: xpack/plugins/orgs/templates/orgs/org_detail.html:59
 | 
			
		||||
#: xpack/plugins/orgs/templates/orgs/org_detail.html:63
 | 
			
		||||
#: xpack/plugins/orgs/templates/orgs/org_list.html:23
 | 
			
		||||
msgid "Comment"
 | 
			
		||||
msgstr "备注"
 | 
			
		||||
| 
						 | 
				
			
			@ -323,7 +325,7 @@ msgstr "参数"
 | 
			
		|||
#: users/templates/users/user_detail.html:97
 | 
			
		||||
#: xpack/plugins/change_auth_plan/models.py:79
 | 
			
		||||
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:111
 | 
			
		||||
#: xpack/plugins/cloud/models.py:56 xpack/plugins/cloud/models.py:142
 | 
			
		||||
#: xpack/plugins/cloud/models.py:56 xpack/plugins/cloud/models.py:145
 | 
			
		||||
#: xpack/plugins/gathered_user/models.py:30
 | 
			
		||||
msgid "Created by"
 | 
			
		||||
msgstr "创建者"
 | 
			
		||||
| 
						 | 
				
			
			@ -350,10 +352,10 @@ msgstr "创建者"
 | 
			
		|||
#: tickets/templates/tickets/ticket_detail.html:52 users/models/group.py:18
 | 
			
		||||
#: users/templates/users/user_group_detail.html:58
 | 
			
		||||
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:103
 | 
			
		||||
#: xpack/plugins/cloud/models.py:59 xpack/plugins/cloud/models.py:145
 | 
			
		||||
#: xpack/plugins/cloud/models.py:59 xpack/plugins/cloud/models.py:148
 | 
			
		||||
#: xpack/plugins/cloud/templates/cloud/account_detail.html:63
 | 
			
		||||
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:98
 | 
			
		||||
#: xpack/plugins/orgs/templates/orgs/org_detail.html:55
 | 
			
		||||
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:108
 | 
			
		||||
#: xpack/plugins/orgs/templates/orgs/org_detail.html:59
 | 
			
		||||
msgid "Date created"
 | 
			
		||||
msgstr "创建日期"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -405,7 +407,7 @@ msgstr "远程应用"
 | 
			
		|||
#: users/templates/users/user_pubkey_update.html:80
 | 
			
		||||
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_create_update.html:65
 | 
			
		||||
#: xpack/plugins/cloud/templates/cloud/account_create_update.html:29
 | 
			
		||||
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_create_update.html:49
 | 
			
		||||
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_create_update.html:52
 | 
			
		||||
#: xpack/plugins/gathered_user/templates/gathered_user/task_create_update.html:40
 | 
			
		||||
#: xpack/plugins/interface/templates/interface/interface.html:72
 | 
			
		||||
#: xpack/plugins/orgs/templates/orgs/org_create_update.html:29
 | 
			
		||||
| 
						 | 
				
			
			@ -536,7 +538,7 @@ msgstr "详情"
 | 
			
		|||
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:26
 | 
			
		||||
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_list.html:60
 | 
			
		||||
#: xpack/plugins/gathered_user/templates/gathered_user/task_list.html:46
 | 
			
		||||
#: xpack/plugins/orgs/templates/orgs/org_detail.html:20
 | 
			
		||||
#: xpack/plugins/orgs/templates/orgs/org_detail.html:24
 | 
			
		||||
#: xpack/plugins/orgs/templates/orgs/org_list.html:93
 | 
			
		||||
msgid "Update"
 | 
			
		||||
msgstr "更新"
 | 
			
		||||
| 
						 | 
				
			
			@ -588,7 +590,7 @@ msgstr "更新"
 | 
			
		|||
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:30
 | 
			
		||||
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_list.html:61
 | 
			
		||||
#: xpack/plugins/gathered_user/templates/gathered_user/task_list.html:47
 | 
			
		||||
#: xpack/plugins/orgs/templates/orgs/org_detail.html:24
 | 
			
		||||
#: xpack/plugins/orgs/templates/orgs/org_detail.html:28
 | 
			
		||||
#: xpack/plugins/orgs/templates/orgs/org_list.html:95
 | 
			
		||||
msgid "Delete"
 | 
			
		||||
msgstr "删除"
 | 
			
		||||
| 
						 | 
				
			
			@ -648,6 +650,7 @@ msgstr "创建数据库应用"
 | 
			
		|||
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_list.html:19
 | 
			
		||||
#: xpack/plugins/gathered_user/templates/gathered_user/task_list.html:20
 | 
			
		||||
#: xpack/plugins/orgs/templates/orgs/org_list.html:24
 | 
			
		||||
#: xpack/plugins/orgs/templates/orgs/org_users.html:47
 | 
			
		||||
msgid "Action"
 | 
			
		||||
msgstr "动作"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -871,6 +874,7 @@ msgstr "用户名"
 | 
			
		|||
#: ops/templates/ops/task_detail.html:95
 | 
			
		||||
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:82
 | 
			
		||||
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:72
 | 
			
		||||
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:82
 | 
			
		||||
msgid "Yes"
 | 
			
		||||
msgstr "是"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -878,6 +882,7 @@ msgstr "是"
 | 
			
		|||
#: ops/templates/ops/task_detail.html:97
 | 
			
		||||
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:84
 | 
			
		||||
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:74
 | 
			
		||||
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:84
 | 
			
		||||
msgid "No"
 | 
			
		||||
msgstr "否"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1318,7 +1323,7 @@ msgstr "默认资产组"
 | 
			
		|||
#: perms/templates/perms/database_app_permission_list.html:15
 | 
			
		||||
#: perms/templates/perms/remote_app_permission_create_update.html:41
 | 
			
		||||
#: perms/templates/perms/remote_app_permission_list.html:15
 | 
			
		||||
#: templates/index.html:86 terminal/backends/command/models.py:18
 | 
			
		||||
#: templates/index.html:78 terminal/backends/command/models.py:18
 | 
			
		||||
#: terminal/models.py:185 terminal/templates/terminal/command_list.html:30
 | 
			
		||||
#: terminal/templates/terminal/command_list.html:105
 | 
			
		||||
#: terminal/templates/terminal/session_detail.html:48
 | 
			
		||||
| 
						 | 
				
			
			@ -1338,7 +1343,6 @@ msgstr "默认资产组"
 | 
			
		|||
#: users/templates/users/user_remote_app_permission.html:37
 | 
			
		||||
#: users/templates/users/user_remote_app_permission.html:58
 | 
			
		||||
#: users/views/profile/base.py:46 xpack/plugins/orgs/forms.py:27
 | 
			
		||||
#: xpack/plugins/orgs/templates/orgs/org_detail.html:108
 | 
			
		||||
#: xpack/plugins/orgs/templates/orgs/org_list.html:15
 | 
			
		||||
msgid "User"
 | 
			
		||||
msgstr "用户"
 | 
			
		||||
| 
						 | 
				
			
			@ -1407,7 +1411,7 @@ msgstr "资产管理"
 | 
			
		|||
#: assets/models/user.py:111 assets/templates/assets/system_user_users.html:76
 | 
			
		||||
#: templates/_nav.html:17 users/views/group.py:28 users/views/group.py:45
 | 
			
		||||
#: users/views/group.py:63 users/views/group.py:82 users/views/group.py:99
 | 
			
		||||
#: users/views/login.py:164 users/views/profile/password.py:40
 | 
			
		||||
#: users/views/login.py:163 users/views/profile/password.py:40
 | 
			
		||||
#: users/views/profile/pubkey.py:36 users/views/user.py:50
 | 
			
		||||
#: users/views/user.py:67 users/views/user.py:111 users/views/user.py:178
 | 
			
		||||
#: users/views/user.py:206 users/views/user.py:220 users/views/user.py:234
 | 
			
		||||
| 
						 | 
				
			
			@ -1728,7 +1732,7 @@ msgstr "资产列表"
 | 
			
		|||
#: ops/templates/ops/command_execution_create.html:112
 | 
			
		||||
#: settings/templates/settings/_ldap_list_users_modal.html:41
 | 
			
		||||
#: users/templates/users/_granted_assets.html:7
 | 
			
		||||
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_create_update.html:62
 | 
			
		||||
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_create_update.html:65
 | 
			
		||||
msgid "Loading"
 | 
			
		||||
msgstr "加载中"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1888,7 +1892,7 @@ msgstr "自动生成密钥"
 | 
			
		|||
#: perms/templates/perms/remote_app_permission_create_update.html:51
 | 
			
		||||
#: terminal/templates/terminal/terminal_update.html:38
 | 
			
		||||
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_create_update.html:61
 | 
			
		||||
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_create_update.html:44
 | 
			
		||||
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_create_update.html:47
 | 
			
		||||
#: xpack/plugins/gathered_user/templates/gathered_user/task_create_update.html:35
 | 
			
		||||
msgid "Other"
 | 
			
		||||
msgstr "其它"
 | 
			
		||||
| 
						 | 
				
			
			@ -1957,7 +1961,7 @@ msgstr "选择节点"
 | 
			
		|||
#: users/templates/users/user_list.html:184
 | 
			
		||||
#: users/templates/users/user_password_verify.html:20
 | 
			
		||||
#: xpack/plugins/cloud/templates/cloud/account_create_update.html:30
 | 
			
		||||
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_create_update.html:50
 | 
			
		||||
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_create_update.html:53
 | 
			
		||||
#: xpack/plugins/gathered_user/templates/gathered_user/task_create_update.html:41
 | 
			
		||||
#: xpack/plugins/interface/templates/interface/interface.html:103
 | 
			
		||||
#: xpack/plugins/orgs/templates/orgs/org_create_update.html:30
 | 
			
		||||
| 
						 | 
				
			
			@ -1997,7 +2001,7 @@ msgstr "资产用户"
 | 
			
		|||
#: users/templates/users/user_detail.html:126
 | 
			
		||||
#: users/templates/users/user_profile.html:150
 | 
			
		||||
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:126
 | 
			
		||||
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:129
 | 
			
		||||
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:139
 | 
			
		||||
#: xpack/plugins/license/templates/license/license_detail.html:80
 | 
			
		||||
msgid "Quick modify"
 | 
			
		||||
msgstr "快速修改"
 | 
			
		||||
| 
						 | 
				
			
			@ -2530,7 +2534,7 @@ msgstr "启用"
 | 
			
		|||
msgid "-"
 | 
			
		||||
msgstr ""
 | 
			
		||||
 | 
			
		||||
#: audits/models.py:78 xpack/plugins/cloud/models.py:201
 | 
			
		||||
#: audits/models.py:78 xpack/plugins/cloud/models.py:204
 | 
			
		||||
msgid "Failed"
 | 
			
		||||
msgstr "失败"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -2563,7 +2567,7 @@ msgstr "多因子认证"
 | 
			
		|||
#: audits/models.py:87 audits/templates/audits/login_log_list.html:63
 | 
			
		||||
#: xpack/plugins/change_auth_plan/models.py:286
 | 
			
		||||
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_subtask_list.html:15
 | 
			
		||||
#: xpack/plugins/cloud/models.py:214
 | 
			
		||||
#: xpack/plugins/cloud/models.py:217
 | 
			
		||||
msgid "Reason"
 | 
			
		||||
msgstr "原因"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -2571,7 +2575,7 @@ msgstr "原因"
 | 
			
		|||
#: tickets/templates/tickets/ticket_detail.html:34
 | 
			
		||||
#: tickets/templates/tickets/ticket_list.html:36
 | 
			
		||||
#: tickets/templates/tickets/ticket_list.html:104
 | 
			
		||||
#: xpack/plugins/cloud/models.py:211 xpack/plugins/cloud/models.py:269
 | 
			
		||||
#: xpack/plugins/cloud/models.py:214 xpack/plugins/cloud/models.py:272
 | 
			
		||||
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_history.html:50
 | 
			
		||||
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_instance.html:48
 | 
			
		||||
msgid "Status"
 | 
			
		||||
| 
						 | 
				
			
			@ -2603,6 +2607,7 @@ msgstr "开始日期"
 | 
			
		|||
#: perms/templates/perms/asset_permission_user.html:74
 | 
			
		||||
#: perms/templates/perms/database_app_permission_user.html:74
 | 
			
		||||
#: perms/templates/perms/remote_app_permission_user.html:83
 | 
			
		||||
#: xpack/plugins/orgs/templates/orgs/org_users.html:67
 | 
			
		||||
msgid "Select user"
 | 
			
		||||
msgstr "选择用户"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -3007,7 +3012,7 @@ msgstr "字段必须唯一"
 | 
			
		|||
msgid "<h1>Flow service unavailable, check it</h1>"
 | 
			
		||||
msgstr ""
 | 
			
		||||
 | 
			
		||||
#: jumpserver/views/index.py:257 templates/_nav.html:7
 | 
			
		||||
#: jumpserver/views/index.py:23 templates/_nav.html:7
 | 
			
		||||
msgid "Dashboard"
 | 
			
		||||
msgstr "仪表盘"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -3044,13 +3049,13 @@ msgstr "没有该主机 {} 权限"
 | 
			
		|||
 | 
			
		||||
#: ops/mixin.py:29 ops/mixin.py:92 ops/mixin.py:162
 | 
			
		||||
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:98
 | 
			
		||||
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:88
 | 
			
		||||
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:98
 | 
			
		||||
msgid "Cycle perform"
 | 
			
		||||
msgstr "周期执行"
 | 
			
		||||
 | 
			
		||||
#: ops/mixin.py:33 ops/mixin.py:90 ops/mixin.py:111 ops/mixin.py:150
 | 
			
		||||
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:90
 | 
			
		||||
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:80
 | 
			
		||||
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:90
 | 
			
		||||
msgid "Regularly perform"
 | 
			
		||||
msgstr "定期执行"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -3058,8 +3063,8 @@ msgstr "定期执行"
 | 
			
		|||
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_create_update.html:54
 | 
			
		||||
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:79
 | 
			
		||||
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_list.html:17
 | 
			
		||||
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_create_update.html:37
 | 
			
		||||
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:69
 | 
			
		||||
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_create_update.html:40
 | 
			
		||||
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:79
 | 
			
		||||
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_list.html:16
 | 
			
		||||
#: xpack/plugins/gathered_user/templates/gathered_user/task_create_update.html:28
 | 
			
		||||
msgid "Periodic perform"
 | 
			
		||||
| 
						 | 
				
			
			@ -3120,7 +3125,7 @@ msgstr "Become"
 | 
			
		|||
 | 
			
		||||
#: ops/models/adhoc.py:150 users/templates/users/user_group_detail.html:54
 | 
			
		||||
#: xpack/plugins/cloud/templates/cloud/account_detail.html:59
 | 
			
		||||
#: xpack/plugins/orgs/templates/orgs/org_detail.html:51
 | 
			
		||||
#: xpack/plugins/orgs/templates/orgs/org_detail.html:55
 | 
			
		||||
msgid "Create by"
 | 
			
		||||
msgstr "创建者"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -3180,7 +3185,7 @@ msgstr "{} 任务结束"
 | 
			
		|||
 | 
			
		||||
#: ops/models/command.py:24
 | 
			
		||||
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_list.html:56
 | 
			
		||||
#: xpack/plugins/cloud/models.py:209
 | 
			
		||||
#: xpack/plugins/cloud/models.py:212
 | 
			
		||||
msgid "Result"
 | 
			
		||||
msgstr "结果"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -3398,7 +3403,7 @@ msgstr "内容"
 | 
			
		|||
#: ops/templates/ops/task_list.html:73
 | 
			
		||||
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:135
 | 
			
		||||
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_list.html:54
 | 
			
		||||
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:138
 | 
			
		||||
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:148
 | 
			
		||||
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_list.html:58
 | 
			
		||||
#: xpack/plugins/gathered_user/templates/gathered_user/task_list.html:44
 | 
			
		||||
msgid "Run"
 | 
			
		||||
| 
						 | 
				
			
			@ -3573,8 +3578,9 @@ msgstr "添加资产"
 | 
			
		|||
#: perms/templates/perms/remote_app_permission_user.html:120
 | 
			
		||||
#: users/templates/users/user_group_detail.html:87
 | 
			
		||||
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_asset_list.html:76
 | 
			
		||||
#: xpack/plugins/orgs/templates/orgs/org_detail.html:88
 | 
			
		||||
#: xpack/plugins/orgs/templates/orgs/org_detail.html:125
 | 
			
		||||
#: xpack/plugins/orgs/templates/orgs/org_detail.html:89
 | 
			
		||||
#: xpack/plugins/orgs/templates/orgs/org_detail.html:123
 | 
			
		||||
#: xpack/plugins/orgs/templates/orgs/org_users.html:73
 | 
			
		||||
msgid "Add"
 | 
			
		||||
msgstr "添加"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -3673,6 +3679,7 @@ msgstr "刷新成功"
 | 
			
		|||
#: perms/templates/perms/asset_permission_user.html:31
 | 
			
		||||
#: perms/templates/perms/database_app_permission_user.html:31
 | 
			
		||||
#: perms/templates/perms/remote_app_permission_user.html:30
 | 
			
		||||
#: xpack/plugins/orgs/templates/orgs/org_users.html:24
 | 
			
		||||
msgid "User list of "
 | 
			
		||||
msgstr "用户列表"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -4624,8 +4631,8 @@ msgid "Total users"
 | 
			
		|||
msgstr "用户总数"
 | 
			
		||||
 | 
			
		||||
#: templates/index.html:23
 | 
			
		||||
msgid "Total hosts"
 | 
			
		||||
msgstr "主机总数"
 | 
			
		||||
msgid "Total assets"
 | 
			
		||||
msgstr "资产总数"
 | 
			
		||||
 | 
			
		||||
#: templates/index.html:36
 | 
			
		||||
msgid "Online users"
 | 
			
		||||
| 
						 | 
				
			
			@ -4647,120 +4654,124 @@ msgstr " 位用户登录 "
 | 
			
		|||
msgid " times asset."
 | 
			
		||||
msgstr " 次资产."
 | 
			
		||||
 | 
			
		||||
#: templates/index.html:66
 | 
			
		||||
msgid " times/week"
 | 
			
		||||
msgstr " 次/周"
 | 
			
		||||
 | 
			
		||||
#: templates/index.html:77
 | 
			
		||||
#: templates/index.html:69
 | 
			
		||||
msgid "Active user asset ratio"
 | 
			
		||||
msgstr "活跃用户资产占比"
 | 
			
		||||
 | 
			
		||||
#: templates/index.html:80
 | 
			
		||||
#: templates/index.html:72
 | 
			
		||||
msgid ""
 | 
			
		||||
"The following graphs describe the percentage of active users per month and "
 | 
			
		||||
"assets per user host per month, respectively."
 | 
			
		||||
msgstr "以下图形分别描述一个月活跃用户和资产占所有用户主机的百分比"
 | 
			
		||||
 | 
			
		||||
#: templates/index.html:105 templates/index.html:120
 | 
			
		||||
#: templates/index.html:97 templates/index.html:112
 | 
			
		||||
msgid "Top 10 assets in a week"
 | 
			
		||||
msgstr "一周Top10资产"
 | 
			
		||||
 | 
			
		||||
#: templates/index.html:121
 | 
			
		||||
#: templates/index.html:113
 | 
			
		||||
msgid "Login frequency and last login record."
 | 
			
		||||
msgstr "登录次数及最近一次登录记录."
 | 
			
		||||
 | 
			
		||||
#: templates/index.html:132 templates/index.html:218
 | 
			
		||||
msgid " times"
 | 
			
		||||
msgstr " 次"
 | 
			
		||||
 | 
			
		||||
#: templates/index.html:135 templates/index.html:221
 | 
			
		||||
msgid "The time last logged in"
 | 
			
		||||
msgstr "最近一次登录日期"
 | 
			
		||||
 | 
			
		||||
#: templates/index.html:136 templates/index.html:222
 | 
			
		||||
msgid "At"
 | 
			
		||||
msgstr "于"
 | 
			
		||||
 | 
			
		||||
#: templates/index.html:142 templates/index.html:180 templates/index.html:228
 | 
			
		||||
msgid "(No)"
 | 
			
		||||
msgstr "(暂无)"
 | 
			
		||||
 | 
			
		||||
#: templates/index.html:150
 | 
			
		||||
#: templates/index.html:122
 | 
			
		||||
msgid "Last 10 login"
 | 
			
		||||
msgstr "最近十次登录"
 | 
			
		||||
 | 
			
		||||
#: templates/index.html:156
 | 
			
		||||
#: templates/index.html:128
 | 
			
		||||
msgid "Login record"
 | 
			
		||||
msgstr "登录记录"
 | 
			
		||||
 | 
			
		||||
#: templates/index.html:157
 | 
			
		||||
#: templates/index.html:129
 | 
			
		||||
msgid "Last 10 login records."
 | 
			
		||||
msgstr "最近十次登录记录."
 | 
			
		||||
 | 
			
		||||
#: templates/index.html:170 templates/index.html:172
 | 
			
		||||
msgid "Before"
 | 
			
		||||
msgstr "前"
 | 
			
		||||
 | 
			
		||||
#: templates/index.html:174
 | 
			
		||||
msgid "Login in "
 | 
			
		||||
msgstr "登录了"
 | 
			
		||||
 | 
			
		||||
#: templates/index.html:191 templates/index.html:206
 | 
			
		||||
#: templates/index.html:143 templates/index.html:158
 | 
			
		||||
msgid "Top 10 users in a week"
 | 
			
		||||
msgstr "一周Top10用户"
 | 
			
		||||
 | 
			
		||||
#: templates/index.html:207
 | 
			
		||||
#: templates/index.html:159
 | 
			
		||||
msgid "User login frequency and last login record."
 | 
			
		||||
msgstr "用户登录次数及最近一次登录记录"
 | 
			
		||||
 | 
			
		||||
#: templates/index.html:264
 | 
			
		||||
#: templates/index.html:184
 | 
			
		||||
msgid "Monthly data overview"
 | 
			
		||||
msgstr "月数据总览"
 | 
			
		||||
 | 
			
		||||
#: templates/index.html:265
 | 
			
		||||
#: templates/index.html:185
 | 
			
		||||
msgid "History summary in one month"
 | 
			
		||||
msgstr "一个月内历史汇总"
 | 
			
		||||
 | 
			
		||||
#: templates/index.html:273 templates/index.html:297
 | 
			
		||||
#: templates/index.html:193 templates/index.html:217
 | 
			
		||||
msgid "Login count"
 | 
			
		||||
msgstr "登录次数"
 | 
			
		||||
 | 
			
		||||
#: templates/index.html:273 templates/index.html:304
 | 
			
		||||
#: templates/index.html:193 templates/index.html:224
 | 
			
		||||
msgid "Active users"
 | 
			
		||||
msgstr "活跃用户"
 | 
			
		||||
 | 
			
		||||
#: templates/index.html:273 templates/index.html:311
 | 
			
		||||
#: templates/index.html:193 templates/index.html:231
 | 
			
		||||
msgid "Active assets"
 | 
			
		||||
msgstr "活跃资产"
 | 
			
		||||
 | 
			
		||||
#: templates/index.html:338 templates/index.html:388
 | 
			
		||||
#: templates/index.html:262 templates/index.html:313
 | 
			
		||||
msgid "Monthly active users"
 | 
			
		||||
msgstr "月活跃用户"
 | 
			
		||||
 | 
			
		||||
#: templates/index.html:338 templates/index.html:389
 | 
			
		||||
#: templates/index.html:262 templates/index.html:314
 | 
			
		||||
msgid "Disable user"
 | 
			
		||||
msgstr "禁用用户"
 | 
			
		||||
 | 
			
		||||
#: templates/index.html:338 templates/index.html:390
 | 
			
		||||
#: templates/index.html:262 templates/index.html:315
 | 
			
		||||
msgid "Month not logged in user"
 | 
			
		||||
msgstr "月未登录用户"
 | 
			
		||||
 | 
			
		||||
#: templates/index.html:364 templates/index.html:440
 | 
			
		||||
#: templates/index.html:288 templates/index.html:368
 | 
			
		||||
msgid "Access to the source"
 | 
			
		||||
msgstr "访问来源"
 | 
			
		||||
 | 
			
		||||
#: templates/index.html:414 templates/index.html:464
 | 
			
		||||
msgid "Month is logged into the host"
 | 
			
		||||
msgstr "月被登录主机"
 | 
			
		||||
#: templates/index.html:342
 | 
			
		||||
msgid "Month is logged into the asset"
 | 
			
		||||
msgstr "月被登录资产"
 | 
			
		||||
 | 
			
		||||
#: templates/index.html:414 templates/index.html:465
 | 
			
		||||
#: templates/index.html:342 templates/index.html:393
 | 
			
		||||
msgid "Disable host"
 | 
			
		||||
msgstr "禁用主机"
 | 
			
		||||
 | 
			
		||||
#: templates/index.html:414 templates/index.html:466
 | 
			
		||||
#: templates/index.html:342 templates/index.html:394
 | 
			
		||||
msgid "Month not logged on host"
 | 
			
		||||
msgstr "月未登录主机"
 | 
			
		||||
 | 
			
		||||
#: templates/index.html:392
 | 
			
		||||
msgid "Month is logged into the host"
 | 
			
		||||
msgstr "月被登录主机"
 | 
			
		||||
 | 
			
		||||
#: templates/index.html:466
 | 
			
		||||
msgid " times/week"
 | 
			
		||||
msgstr " 次/周"
 | 
			
		||||
 | 
			
		||||
#: templates/index.html:491 templates/index.html:527
 | 
			
		||||
msgid " times"
 | 
			
		||||
msgstr " 次"
 | 
			
		||||
 | 
			
		||||
#: templates/index.html:494 templates/index.html:530
 | 
			
		||||
msgid "The time last logged in"
 | 
			
		||||
msgstr "最近一次登录日期"
 | 
			
		||||
 | 
			
		||||
#: templates/index.html:495 templates/index.html:531
 | 
			
		||||
msgid "At"
 | 
			
		||||
msgstr "于"
 | 
			
		||||
 | 
			
		||||
#: templates/index.html:510 templates/index.html:545 templates/index.html:580
 | 
			
		||||
msgid "(No)"
 | 
			
		||||
msgstr "(暂无)"
 | 
			
		||||
 | 
			
		||||
#: templates/index.html:561
 | 
			
		||||
msgid "Before"
 | 
			
		||||
msgstr "前"
 | 
			
		||||
 | 
			
		||||
#: templates/index.html:562
 | 
			
		||||
msgid "Login in "
 | 
			
		||||
msgstr "登录了"
 | 
			
		||||
 | 
			
		||||
#: templates/rest_framework/base.html:128
 | 
			
		||||
msgid "Filters"
 | 
			
		||||
msgstr "过滤"
 | 
			
		||||
| 
						 | 
				
			
			@ -4880,9 +4891,9 @@ msgid ""
 | 
			
		|||
"            "
 | 
			
		||||
msgstr ""
 | 
			
		||||
 | 
			
		||||
#: terminal/forms/storage.py:136 xpack/plugins/cloud/models.py:263
 | 
			
		||||
#: terminal/forms/storage.py:136 xpack/plugins/cloud/models.py:266
 | 
			
		||||
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_create_update.html:29
 | 
			
		||||
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:106
 | 
			
		||||
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:112
 | 
			
		||||
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_instance.html:46
 | 
			
		||||
msgid "Region"
 | 
			
		||||
msgstr "地域"
 | 
			
		||||
| 
						 | 
				
			
			@ -5401,7 +5412,7 @@ msgstr "复制用户公钥到这里"
 | 
			
		|||
msgid "Join user groups"
 | 
			
		||||
msgstr "添加到用户组"
 | 
			
		||||
 | 
			
		||||
#: users/forms/user.py:103 users/views/login.py:124
 | 
			
		||||
#: users/forms/user.py:103 users/views/login.py:123
 | 
			
		||||
#: users/views/profile/password.py:57
 | 
			
		||||
msgid "* Your password does not meet the requirements"
 | 
			
		||||
msgstr "* 您的密码不符合要求"
 | 
			
		||||
| 
						 | 
				
			
			@ -5427,6 +5438,7 @@ msgid "Administrator"
 | 
			
		|||
msgstr "管理员"
 | 
			
		||||
 | 
			
		||||
#: users/models/user.py:145 xpack/plugins/orgs/forms.py:29
 | 
			
		||||
#: xpack/plugins/orgs/templates/orgs/org_detail.html:109
 | 
			
		||||
#: xpack/plugins/orgs/templates/orgs/org_list.html:14
 | 
			
		||||
msgid "Auditor"
 | 
			
		||||
msgstr "审计员"
 | 
			
		||||
| 
						 | 
				
			
			@ -5781,7 +5793,6 @@ msgid "User group detail"
 | 
			
		|||
msgstr "用户组详情"
 | 
			
		||||
 | 
			
		||||
#: users/templates/users/user_group_detail.html:81
 | 
			
		||||
#: xpack/plugins/orgs/templates/orgs/org_detail.html:116
 | 
			
		||||
msgid "Add user"
 | 
			
		||||
msgstr "添加用户"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -5921,7 +5932,7 @@ msgid "Update user"
 | 
			
		|||
msgstr "更新用户"
 | 
			
		||||
 | 
			
		||||
#: users/templates/users/user_update.html:22 users/views/login.py:49
 | 
			
		||||
#: users/views/login.py:117
 | 
			
		||||
#: users/views/login.py:116
 | 
			
		||||
msgid "User auth from {}, go there change password"
 | 
			
		||||
msgstr "用户认证源来自 {}, 请去相应系统修改密码"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -6143,28 +6154,28 @@ msgstr "用户组授权资产"
 | 
			
		|||
msgid "Email address invalid, please input again"
 | 
			
		||||
msgstr "邮箱地址错误,重新输入"
 | 
			
		||||
 | 
			
		||||
#: users/views/login.py:63
 | 
			
		||||
#: users/views/login.py:62
 | 
			
		||||
msgid "Send reset password message"
 | 
			
		||||
msgstr "发送重置密码邮件"
 | 
			
		||||
 | 
			
		||||
#: users/views/login.py:64
 | 
			
		||||
#: users/views/login.py:63
 | 
			
		||||
msgid "Send reset password mail success, login your mail box and follow it "
 | 
			
		||||
msgstr ""
 | 
			
		||||
"发送重置邮件成功, 请登录邮箱查看, 按照提示操作 (如果没收到,请等待3-5分钟)"
 | 
			
		||||
 | 
			
		||||
#: users/views/login.py:77
 | 
			
		||||
#: users/views/login.py:76
 | 
			
		||||
msgid "Reset password success"
 | 
			
		||||
msgstr "重置密码成功"
 | 
			
		||||
 | 
			
		||||
#: users/views/login.py:78
 | 
			
		||||
#: users/views/login.py:77
 | 
			
		||||
msgid "Reset password success, return to login page"
 | 
			
		||||
msgstr "重置密码成功,返回到登录页面"
 | 
			
		||||
 | 
			
		||||
#: users/views/login.py:102 users/views/login.py:112
 | 
			
		||||
#: users/views/login.py:101 users/views/login.py:111
 | 
			
		||||
msgid "Token invalid or expired"
 | 
			
		||||
msgstr "Token错误或失效"
 | 
			
		||||
 | 
			
		||||
#: users/views/login.py:164
 | 
			
		||||
#: users/views/login.py:163
 | 
			
		||||
msgid "First login"
 | 
			
		||||
msgstr "首次登录"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -6420,6 +6431,10 @@ msgstr "选择节点"
 | 
			
		|||
msgid "Select admins"
 | 
			
		||||
msgstr "选择管理员"
 | 
			
		||||
 | 
			
		||||
#: xpack/plugins/cloud/forms.py:85
 | 
			
		||||
msgid "Tips: The asset information is always covered"
 | 
			
		||||
msgstr "提示:资产信息总是被覆盖"
 | 
			
		||||
 | 
			
		||||
#: xpack/plugins/cloud/meta.py:9 xpack/plugins/cloud/views.py:27
 | 
			
		||||
#: xpack/plugins/cloud/views.py:44 xpack/plugins/cloud/views.py:62
 | 
			
		||||
#: xpack/plugins/cloud/views.py:78 xpack/plugins/cloud/views.py:92
 | 
			
		||||
| 
						 | 
				
			
			@ -6464,48 +6479,52 @@ msgstr "地域"
 | 
			
		|||
msgid "Instances"
 | 
			
		||||
msgstr "实例"
 | 
			
		||||
 | 
			
		||||
#: xpack/plugins/cloud/models.py:139
 | 
			
		||||
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:94
 | 
			
		||||
#: xpack/plugins/cloud/models.py:136
 | 
			
		||||
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:69
 | 
			
		||||
msgid "Covered always"
 | 
			
		||||
msgstr "总是覆盖"
 | 
			
		||||
 | 
			
		||||
#: xpack/plugins/cloud/models.py:142
 | 
			
		||||
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:104
 | 
			
		||||
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_list.html:17
 | 
			
		||||
msgid "Date last sync"
 | 
			
		||||
msgstr "最后同步日期"
 | 
			
		||||
 | 
			
		||||
#: xpack/plugins/cloud/models.py:150 xpack/plugins/cloud/models.py:207
 | 
			
		||||
#: xpack/plugins/cloud/models.py:153 xpack/plugins/cloud/models.py:210
 | 
			
		||||
msgid "Sync instance task"
 | 
			
		||||
msgstr "同步实例任务"
 | 
			
		||||
 | 
			
		||||
#: xpack/plugins/cloud/models.py:202
 | 
			
		||||
#: xpack/plugins/cloud/models.py:205
 | 
			
		||||
msgid "Succeed"
 | 
			
		||||
msgstr "成功"
 | 
			
		||||
 | 
			
		||||
#: xpack/plugins/cloud/models.py:217 xpack/plugins/cloud/models.py:272
 | 
			
		||||
#: xpack/plugins/cloud/models.py:220 xpack/plugins/cloud/models.py:275
 | 
			
		||||
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_history.html:51
 | 
			
		||||
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_instance.html:49
 | 
			
		||||
msgid "Date sync"
 | 
			
		||||
msgstr "同步日期"
 | 
			
		||||
 | 
			
		||||
#: xpack/plugins/cloud/models.py:245
 | 
			
		||||
#: xpack/plugins/cloud/models.py:248
 | 
			
		||||
msgid "Unsync"
 | 
			
		||||
msgstr "未同步"
 | 
			
		||||
 | 
			
		||||
#: xpack/plugins/cloud/models.py:246 xpack/plugins/cloud/models.py:247
 | 
			
		||||
#: xpack/plugins/cloud/models.py:249 xpack/plugins/cloud/models.py:250
 | 
			
		||||
msgid "Synced"
 | 
			
		||||
msgstr "已同步"
 | 
			
		||||
 | 
			
		||||
#: xpack/plugins/cloud/models.py:248
 | 
			
		||||
#: xpack/plugins/cloud/models.py:251
 | 
			
		||||
msgid "Released"
 | 
			
		||||
msgstr "已释放"
 | 
			
		||||
 | 
			
		||||
#: xpack/plugins/cloud/models.py:253
 | 
			
		||||
#: xpack/plugins/cloud/models.py:256
 | 
			
		||||
msgid "Sync task"
 | 
			
		||||
msgstr "同步任务"
 | 
			
		||||
 | 
			
		||||
#: xpack/plugins/cloud/models.py:257
 | 
			
		||||
#: xpack/plugins/cloud/models.py:260
 | 
			
		||||
msgid "Sync instance task history"
 | 
			
		||||
msgstr "同步实例任务历史"
 | 
			
		||||
 | 
			
		||||
#: xpack/plugins/cloud/models.py:260
 | 
			
		||||
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:114
 | 
			
		||||
#: xpack/plugins/cloud/models.py:263
 | 
			
		||||
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_instance.html:45
 | 
			
		||||
msgid "Instance"
 | 
			
		||||
msgstr "实例"
 | 
			
		||||
| 
						 | 
				
			
			@ -6584,7 +6603,7 @@ msgstr "创建账户"
 | 
			
		|||
msgid "Node & AdminUser"
 | 
			
		||||
msgstr "节点 & 管理用户"
 | 
			
		||||
 | 
			
		||||
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_create_update.html:63
 | 
			
		||||
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_create_update.html:66
 | 
			
		||||
msgid "Load failed"
 | 
			
		||||
msgstr "加载失败"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -6609,11 +6628,11 @@ msgstr "同步历史列表"
 | 
			
		|||
msgid "Sync instance list"
 | 
			
		||||
msgstr "同步实例列表"
 | 
			
		||||
 | 
			
		||||
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:135
 | 
			
		||||
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:145
 | 
			
		||||
msgid "Run task manually"
 | 
			
		||||
msgstr "手动执行任务"
 | 
			
		||||
 | 
			
		||||
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:178
 | 
			
		||||
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:188
 | 
			
		||||
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_list.html:102
 | 
			
		||||
msgid "Sync success"
 | 
			
		||||
msgstr "同步成功"
 | 
			
		||||
| 
						 | 
				
			
			@ -6650,7 +6669,7 @@ msgstr "执行次数"
 | 
			
		|||
msgid "Instance count"
 | 
			
		||||
msgstr "实例个数"
 | 
			
		||||
 | 
			
		||||
#: xpack/plugins/cloud/utils.py:37
 | 
			
		||||
#: xpack/plugins/cloud/utils.py:38
 | 
			
		||||
msgid "Account unavailable"
 | 
			
		||||
msgstr "账户无效"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -6887,42 +6906,60 @@ msgid "Select auditor"
 | 
			
		|||
msgstr "选择审计员"
 | 
			
		||||
 | 
			
		||||
#: xpack/plugins/orgs/forms.py:28
 | 
			
		||||
#: xpack/plugins/orgs/templates/orgs/org_detail.html:71
 | 
			
		||||
#: xpack/plugins/orgs/templates/orgs/org_detail.html:75
 | 
			
		||||
#: xpack/plugins/orgs/templates/orgs/org_list.html:13
 | 
			
		||||
msgid "Admin"
 | 
			
		||||
msgstr "管理员"
 | 
			
		||||
 | 
			
		||||
#: xpack/plugins/orgs/meta.py:8 xpack/plugins/orgs/views.py:26
 | 
			
		||||
#: xpack/plugins/orgs/views.py:43 xpack/plugins/orgs/views.py:61
 | 
			
		||||
#: xpack/plugins/orgs/views.py:79
 | 
			
		||||
#: xpack/plugins/orgs/meta.py:8 xpack/plugins/orgs/views.py:27
 | 
			
		||||
#: xpack/plugins/orgs/views.py:44 xpack/plugins/orgs/views.py:62
 | 
			
		||||
#: xpack/plugins/orgs/views.py:85 xpack/plugins/orgs/views.py:116
 | 
			
		||||
msgid "Organizations"
 | 
			
		||||
msgstr "组织管理"
 | 
			
		||||
 | 
			
		||||
#: xpack/plugins/orgs/templates/orgs/org_detail.html:17
 | 
			
		||||
#: xpack/plugins/orgs/views.py:80
 | 
			
		||||
#: xpack/plugins/orgs/templates/orgs/org_users.html:13
 | 
			
		||||
#: xpack/plugins/orgs/views.py:86
 | 
			
		||||
msgid "Org detail"
 | 
			
		||||
msgstr "组织详情"
 | 
			
		||||
 | 
			
		||||
#: xpack/plugins/orgs/templates/orgs/org_detail.html:79
 | 
			
		||||
#: xpack/plugins/orgs/templates/orgs/org_detail.html:20
 | 
			
		||||
#: xpack/plugins/orgs/templates/orgs/org_users.html:16
 | 
			
		||||
msgid "Org users"
 | 
			
		||||
msgstr "组织用户"
 | 
			
		||||
 | 
			
		||||
#: xpack/plugins/orgs/templates/orgs/org_detail.html:83
 | 
			
		||||
msgid "Add admin"
 | 
			
		||||
msgstr "添加管理员"
 | 
			
		||||
 | 
			
		||||
#: xpack/plugins/orgs/templates/orgs/org_detail.html:117
 | 
			
		||||
msgid "Add auditor"
 | 
			
		||||
msgstr "添加审计员"
 | 
			
		||||
 | 
			
		||||
#: xpack/plugins/orgs/templates/orgs/org_list.html:5
 | 
			
		||||
msgid "Create organization "
 | 
			
		||||
msgstr "创建组织"
 | 
			
		||||
 | 
			
		||||
#: xpack/plugins/orgs/views.py:27
 | 
			
		||||
#: xpack/plugins/orgs/templates/orgs/org_users.html:59
 | 
			
		||||
msgid "Add user to organization"
 | 
			
		||||
msgstr "添加用户"
 | 
			
		||||
 | 
			
		||||
#: xpack/plugins/orgs/views.py:28
 | 
			
		||||
msgid "Org list"
 | 
			
		||||
msgstr "组织列表"
 | 
			
		||||
 | 
			
		||||
#: xpack/plugins/orgs/views.py:44
 | 
			
		||||
#: xpack/plugins/orgs/views.py:45
 | 
			
		||||
msgid "Create org"
 | 
			
		||||
msgstr "创建组织"
 | 
			
		||||
 | 
			
		||||
#: xpack/plugins/orgs/views.py:62
 | 
			
		||||
#: xpack/plugins/orgs/views.py:63
 | 
			
		||||
msgid "Update org"
 | 
			
		||||
msgstr "更新组织"
 | 
			
		||||
 | 
			
		||||
#: xpack/plugins/orgs/views.py:117
 | 
			
		||||
msgid "Org user list"
 | 
			
		||||
msgstr "组织用户列表"
 | 
			
		||||
 | 
			
		||||
#: xpack/plugins/vault/meta.py:11 xpack/plugins/vault/views.py:23
 | 
			
		||||
#: xpack/plugins/vault/views.py:38
 | 
			
		||||
msgid "Vault"
 | 
			
		||||
| 
						 | 
				
			
			@ -6944,11 +6981,8 @@ msgstr "密码匣子"
 | 
			
		|||
msgid "vault create"
 | 
			
		||||
msgstr "创建"
 | 
			
		||||
 | 
			
		||||
#~ msgid "Tips: The asset information is always covered"
 | 
			
		||||
#~ msgstr "提示:资产信息总是被覆盖"
 | 
			
		||||
 | 
			
		||||
#~ msgid "Covered always"
 | 
			
		||||
#~ msgstr "总是覆盖"
 | 
			
		||||
#~ msgid "Total hosts"
 | 
			
		||||
#~ msgstr "主机总数"
 | 
			
		||||
 | 
			
		||||
#~ msgid "* For security, do not change {}'s password"
 | 
			
		||||
#~ msgstr "* 为了安全,不能修改 {} 的密码"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,14 +1,16 @@
 | 
			
		|||
# -*- coding: utf-8 -*-
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
from rest_framework import status
 | 
			
		||||
from django.shortcuts import get_object_or_404
 | 
			
		||||
from rest_framework import status, generics
 | 
			
		||||
from rest_framework.views import Response
 | 
			
		||||
from rest_framework_bulk import BulkModelViewSet
 | 
			
		||||
 | 
			
		||||
from common.permissions import IsSuperUserOrAppUser
 | 
			
		||||
from .models import Organization
 | 
			
		||||
from .serializers import OrgSerializer, OrgReadSerializer, \
 | 
			
		||||
    OrgMembershipUserSerializer, OrgMembershipAdminSerializer
 | 
			
		||||
    OrgMembershipUserSerializer, OrgMembershipAdminSerializer, \
 | 
			
		||||
    OrgAllUserSerializer
 | 
			
		||||
from users.models import User, UserGroup
 | 
			
		||||
from assets.models import Asset, Domain, AdminUser, SystemUser, Label
 | 
			
		||||
from perms.models import AssetPermission
 | 
			
		||||
| 
						 | 
				
			
			@ -67,3 +69,15 @@ class OrgMembershipUsersViewSet(OrgMembershipModelViewSetMixin, BulkModelViewSet
 | 
			
		|||
    membership_class = Organization.users.through
 | 
			
		||||
    permission_classes = (IsSuperUserOrAppUser, )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class OrgAllUserListApi(generics.ListAPIView):
 | 
			
		||||
    permission_classes = (IsSuperUserOrAppUser,)
 | 
			
		||||
    serializer_class = OrgAllUserSerializer
 | 
			
		||||
    filter_fields = ("username", "name")
 | 
			
		||||
    search_fields = filter_fields
 | 
			
		||||
 | 
			
		||||
    def get_queryset(self):
 | 
			
		||||
        pk = self.kwargs.get("pk")
 | 
			
		||||
        org = get_object_or_404(Organization, pk=pk)
 | 
			
		||||
        users = org.get_org_users().only(*self.serializer_class.Meta.only_fields)
 | 
			
		||||
        return users
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -80,3 +80,15 @@ class OrgMembershipUserSerializer(OrgMembershipSerializerMixin, ModelSerializer)
 | 
			
		|||
        model = Organization.users.through
 | 
			
		||||
        list_serializer_class = AdaptedBulkListSerializer
 | 
			
		||||
        fields = '__all__'
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class OrgAllUserSerializer(serializers.Serializer):
 | 
			
		||||
    user = serializers.UUIDField(read_only=True, source='id')
 | 
			
		||||
    user_display = serializers.SerializerMethodField()
 | 
			
		||||
 | 
			
		||||
    class Meta:
 | 
			
		||||
        only_fields = ['id', 'username', 'name']
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def get_user_display(obj):
 | 
			
		||||
        return str(obj)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,7 +1,7 @@
 | 
			
		|||
# -*- coding: utf-8 -*-
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
from django.urls import re_path
 | 
			
		||||
from django.urls import re_path, path
 | 
			
		||||
from rest_framework.routers import DefaultRouter
 | 
			
		||||
 | 
			
		||||
from common import api as capi
 | 
			
		||||
| 
						 | 
				
			
			@ -24,6 +24,7 @@ old_version_urlpatterns = [
 | 
			
		|||
]
 | 
			
		||||
 | 
			
		||||
urlpatterns = [
 | 
			
		||||
    path('<uuid:pk>/users/all/', api.OrgAllUserListApi.as_view(), name='org-all-users'),
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
urlpatterns += router.urls + old_version_urlpatterns
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,14 +1,7 @@
 | 
			
		|||
from __future__ import unicode_literals
 | 
			
		||||
 | 
			
		||||
from django.conf import settings
 | 
			
		||||
from django.apps import AppConfig
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class PermsConfig(AppConfig):
 | 
			
		||||
    name = 'perms'
 | 
			
		||||
 | 
			
		||||
    def ready(self):
 | 
			
		||||
        from . import signals_handler
 | 
			
		||||
        if not settings.XPACK_ENABLED:
 | 
			
		||||
            settings.ASSETS_PERM_CACHE_ENABLE = False
 | 
			
		||||
        return super().ready()
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -301,7 +301,6 @@ class AssetPermissionUtil(AssetPermissionUtilCacheMixin):
 | 
			
		|||
                continue
 | 
			
		||||
            ancestors = self.full_tree.ancestors(
 | 
			
		||||
                child.identifier, with_self=False, deep=True,
 | 
			
		||||
                with_assets=False,
 | 
			
		||||
            )
 | 
			
		||||
            if not ancestors:
 | 
			
		||||
                continue
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,7 +11,7 @@
 | 
			
		|||
                    <h5>{% trans 'Total users' %}</h5>
 | 
			
		||||
                </div>
 | 
			
		||||
                <div class="ibox-content">
 | 
			
		||||
                    <h1 class="no-margins"><a href="{% url 'users:user-list' %}">{{ users_count }}</a></h1>
 | 
			
		||||
                    <h1 class="no-margins"><a href="{% url 'users:user-list' %}"><span id="total_count_users"></span></a></h1>
 | 
			
		||||
                    <small>All users</small>
 | 
			
		||||
                </div>
 | 
			
		||||
            </div>
 | 
			
		||||
| 
						 | 
				
			
			@ -19,12 +19,12 @@
 | 
			
		|||
        <div class="col-sm-3">
 | 
			
		||||
            <div class="ibox float-e-margins">
 | 
			
		||||
                <div class="ibox-title">
 | 
			
		||||
                    <span class="label label-info pull-right">Hosts</span>
 | 
			
		||||
                    <h5>{% trans 'Total hosts' %}</h5>
 | 
			
		||||
                    <span class="label label-info pull-right">Assets</span>
 | 
			
		||||
                    <h5>{% trans 'Total assets' %}</h5>
 | 
			
		||||
                </div>
 | 
			
		||||
                <div class="ibox-content">
 | 
			
		||||
                    <h1 class="no-margins"><a href="{% url 'assets:asset-list' %}">{{ assets_count }}</a></h1>
 | 
			
		||||
                    <small>All hosts</small>
 | 
			
		||||
                    <h1 class="no-margins"><a href="{% url 'assets:asset-list' %}"><span id="total_count_assets"></span></a></h1>
 | 
			
		||||
                    <small>All assets</small>
 | 
			
		||||
                </div>
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
| 
						 | 
				
			
			@ -36,7 +36,7 @@
 | 
			
		|||
                    <h5>{% trans 'Online users' %}</h5>
 | 
			
		||||
                </div>
 | 
			
		||||
                <div class="ibox-content">
 | 
			
		||||
                    <h1 class="no-margins"><a href="{% url 'terminal:session-online-list' %}"> <span id="online_users"></span>{{ online_user_count }}</a></h1>
 | 
			
		||||
                    <h1 class="no-margins"><a href="{% url 'terminal:session-online-list' %}"> <span id="total_count_online_users"></span></a></h1>
 | 
			
		||||
                    <small>Online users</small>
 | 
			
		||||
                </div>
 | 
			
		||||
            </div>
 | 
			
		||||
| 
						 | 
				
			
			@ -50,7 +50,7 @@
 | 
			
		|||
 | 
			
		||||
                </div>
 | 
			
		||||
                <div class="ibox-content">
 | 
			
		||||
                        <h1 class="no-margins"><a href="{% url 'terminal:session-online-list' %}"> <span id="online_hosts"></span>{{ online_asset_count }}</a></h1>
 | 
			
		||||
                        <h1 class="no-margins"><a href="{% url 'terminal:session-online-list' %}"> <span id="total_count_online_assets"></span></a></h1>
 | 
			
		||||
                    <small>Online sessions</small>
 | 
			
		||||
                </div>
 | 
			
		||||
            </div>
 | 
			
		||||
| 
						 | 
				
			
			@ -58,19 +58,11 @@
 | 
			
		|||
    </div>
 | 
			
		||||
    <div class="row">
 | 
			
		||||
        <div class="col-sm-2 border-bottom white-bg dashboard-header" style="margin-left:15px;height: 346px">
 | 
			
		||||
            <small>{% trans 'In the past week, a total of ' %}<span class="text-info">{{ user_visit_count_weekly }}</span>{% trans ' users have logged in ' %}<span class="text-success">{{ asset_visit_count_weekly }}</span>{% trans ' times asset.' %}</small>
 | 
			
		||||
            <ul class="list-group clear-list m-t">
 | 
			
		||||
                {% for data in user_visit_count_top_five %}
 | 
			
		||||
                    <li class="list-group-item fist-item">
 | 
			
		||||
                        <span class="pull-right">
 | 
			
		||||
                            {{ data.total }}{% trans ' times/week' %}
 | 
			
		||||
                        </span>
 | 
			
		||||
                        <span class="label ">{{ forloop.counter }}</span> {{ data.user }}
 | 
			
		||||
                    </li>
 | 
			
		||||
                {% endfor %}
 | 
			
		||||
            <small>{% trans 'In the past week, a total of ' %}<span class="text-info" id="week_total_count_login_users"></span>{% trans ' users have logged in ' %}<span class="text-success" id="week_total_count_login_times"></span>{% trans ' times asset.' %}</small>
 | 
			
		||||
            <ul class="list-group clear-list m-t" id="week_login_times_top5_users">
 | 
			
		||||
            </ul>
 | 
			
		||||
        </div>
 | 
			
		||||
        <div class="col-sm-7" id="top10" style="margin-left: -15px;height: 346px;padding: 15px 0 15px 0;"></div>
 | 
			
		||||
        <div class="col-sm-7" id="month_metrics_echarts" style="margin-left: -15px;height: 346px;padding: 15px 0 15px 0;"></div>
 | 
			
		||||
        <div class="col-sm-3 white-bg" id="top1" style="margin-left: -15px;height: 346px">
 | 
			
		||||
            <div class="statistic-box">
 | 
			
		||||
                <h4>
 | 
			
		||||
| 
						 | 
				
			
			@ -81,13 +73,13 @@
 | 
			
		|||
                </p>
 | 
			
		||||
                <div class="row text-center">
 | 
			
		||||
                    <div class="col-sm-6">
 | 
			
		||||
                        <div id="activeUser"  style="width: 140px; height: 140px;">
 | 
			
		||||
                        <div id="month_total_count_users_pie"  style="width: 140px; height: 140px;">
 | 
			
		||||
                        </div>
 | 
			
		||||
                        <h5>{% trans 'User' %}</h5>
 | 
			
		||||
                    </div>
 | 
			
		||||
                    <div class="col-sm-6">
 | 
			
		||||
                        <div id="activeAsset" style="width: 140px; height: 140px;"></div>
 | 
			
		||||
                        <h5>{% trans 'Host' %}</h5>
 | 
			
		||||
                        <div id="month_total_count_assets_pie" style="width: 140px; height: 140px;"></div>
 | 
			
		||||
                        <h5>{% trans 'Asset' %}</h5>
 | 
			
		||||
                    </div>
 | 
			
		||||
                </div>
 | 
			
		||||
                <div class="m-t">
 | 
			
		||||
| 
						 | 
				
			
			@ -120,27 +112,7 @@
 | 
			
		|||
                    <h3><i class="fa fa-inbox"></i>{% trans 'Top 10 assets in a week'%}</h3>
 | 
			
		||||
                    <small><i class="fa fa-map-marker"></i>{% trans 'Login frequency and last login record.' %}</small>
 | 
			
		||||
                </div>
 | 
			
		||||
                <div class="ibox-content inspinia-timeline">
 | 
			
		||||
                    {% if week_asset_hot_ten %}
 | 
			
		||||
                        {% for data in week_asset_hot_ten %}
 | 
			
		||||
                            <div class="timeline-item">
 | 
			
		||||
                                <div class="row">
 | 
			
		||||
                                    <div class="col-xs-5 date ellipsis">
 | 
			
		||||
                                        <i class="fa fa-info-circle"></i>
 | 
			
		||||
                                        <strong data-toggle="tooltip" title="{{ data.asset }}">{{ data.asset }}</strong>
 | 
			
		||||
                                        <br/>
 | 
			
		||||
                                        <small class="text-navy">{{ data.total }}{% trans ' times' %}</small>
 | 
			
		||||
                                    </div>
 | 
			
		||||
                                    <div class="col-xs-7 content no-top-border">
 | 
			
		||||
                                        <p class="m-b-xs">{% trans 'The time last logged in' %}</p>
 | 
			
		||||
                                        <p>{% trans 'At' %} {{ data.last|date:"Y-m-d H:i:s" }}</p>
 | 
			
		||||
                                    </div>
 | 
			
		||||
                                </div>
 | 
			
		||||
                            </div>
 | 
			
		||||
                        {% endfor %}
 | 
			
		||||
                    {% else %}
 | 
			
		||||
                        <p class="text-center">{% trans '(No)' %}</p>
 | 
			
		||||
                    {% endif %}
 | 
			
		||||
                <div class="ibox-content inspinia-timeline" id="week_login_times_top10_assets">
 | 
			
		||||
                </div>
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
| 
						 | 
				
			
			@ -158,27 +130,7 @@
 | 
			
		|||
                </div>
 | 
			
		||||
                <div class="ibox-content">
 | 
			
		||||
                    <div>
 | 
			
		||||
                        <div class="feed-activity-list">
 | 
			
		||||
                            {% if last_login_ten %}
 | 
			
		||||
                                {% for login in last_login_ten %}
 | 
			
		||||
                                    <div class="feed-element">
 | 
			
		||||
                                        <a href="#" class="pull-left">
 | 
			
		||||
                                            <img alt="image" class="img-circle" src="{% static 'img/avatar/user.png' %}">
 | 
			
		||||
                                        </a>
 | 
			
		||||
                                        <div class="media-body ">
 | 
			
		||||
                                            {% ifequal login.is_finished 0 %}
 | 
			
		||||
                                                <small class="pull-right text-navy">{{ login.date_start|timesince }} {% trans 'Before' %}</small>
 | 
			
		||||
                                            {% else %}
 | 
			
		||||
                                                <small class="pull-right">{{ login.date_start|timesince }} {% trans 'Before' %}</small>
 | 
			
		||||
                                            {% endifequal %}
 | 
			
		||||
                                            <strong>{{ login.user }}</strong> {% trans 'Login in ' %}{{ login.asset }} <br>
 | 
			
		||||
                                            <small class="text-muted">{{ login.date_start }}</small>
 | 
			
		||||
                                        </div>
 | 
			
		||||
                                    </div>
 | 
			
		||||
                                {% endfor %}
 | 
			
		||||
                            {% else %}
 | 
			
		||||
                                <p class="text-center">{% trans '(No)' %}</p>
 | 
			
		||||
                            {% endif %}
 | 
			
		||||
                        <div class="feed-activity-list" id="week_login_record_top10_sessions">
 | 
			
		||||
                        </div>
 | 
			
		||||
                    </div>
 | 
			
		||||
                </div>
 | 
			
		||||
| 
						 | 
				
			
			@ -206,27 +158,7 @@
 | 
			
		|||
                    <h3><i class="fa fa-user"></i>{% trans 'Top 10 users in a week' %}</h3>
 | 
			
		||||
                    <small><i class="fa fa-map-marker"></i>{% trans 'User login frequency and last login record.' %}</small>
 | 
			
		||||
                </div>
 | 
			
		||||
                <div class="ibox-content inspinia-timeline">
 | 
			
		||||
                    {% if week_user_hot_ten %}
 | 
			
		||||
                        {% for data in week_user_hot_ten %}
 | 
			
		||||
                            <div class="timeline-item">
 | 
			
		||||
                                <div class="row">
 | 
			
		||||
                                    <div class="col-xs-5 date ellipsis">
 | 
			
		||||
                                        <i class="fa fa-info-circle"></i>
 | 
			
		||||
                                        <strong data-toggle="tooltip" title="{{ data.user }}">{{ data.user }}</strong>
 | 
			
		||||
                                        <br/>
 | 
			
		||||
                                        <small class="text-navy">{{ data.total }}{% trans ' times' %}</small>
 | 
			
		||||
                                    </div>
 | 
			
		||||
                                    <div class="col-xs-7 content no-top-border">
 | 
			
		||||
                                        <p class="m-b-xs">{% trans 'The time last logged in' %}</p>
 | 
			
		||||
                                        <p>{% trans 'At' %} {{ data.last|date:"Y-m-d H:i:s" }}</p>
 | 
			
		||||
                                    </div>
 | 
			
		||||
                                </div>
 | 
			
		||||
                            </div>
 | 
			
		||||
                        {% endfor %}
 | 
			
		||||
                    {% else %}
 | 
			
		||||
                        <p class="text-center">{% trans '(No)' %}</p>
 | 
			
		||||
                    {% endif %}
 | 
			
		||||
                <div class="ibox-content inspinia-timeline" id="week_login_times_top10_users">
 | 
			
		||||
                </div>
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
| 
						 | 
				
			
			@ -238,27 +170,15 @@
 | 
			
		|||
{% block custom_foot_js %}
 | 
			
		||||
<script src="{% static 'js/plugins/echarts/echarts.js' %}"></script>
 | 
			
		||||
<script>
 | 
			
		||||
$(document).ready(function(){
 | 
			
		||||
    $('#show').click(function(){
 | 
			
		||||
        $('#show').css('display', 'none');
 | 
			
		||||
        $('#more').css('display', 'block');
 | 
			
		||||
    });
 | 
			
		||||
    $("[data-toggle='tooltip']").tooltip();
 | 
			
		||||
});
 | 
			
		||||
    require.config({
 | 
			
		||||
        paths: {
 | 
			
		||||
            'echarts': '/static/js/plugins/echarts/chart/',
 | 
			
		||||
            'echarts/chart/line': '/static/js/plugins/echarts/chart/line',
 | 
			
		||||
            'echarts/chart/pie': '/static/js/plugins/echarts/chart/pie'
 | 
			
		||||
        }
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
function requireMonthMetricsECharts(data){
 | 
			
		||||
    require(
 | 
			
		||||
        [
 | 
			
		||||
            'echarts',
 | 
			
		||||
            'echarts/chart/line'
 | 
			
		||||
        ],
 | 
			
		||||
        function (ec) {
 | 
			
		||||
            var top10Chart = ec.init(document.getElementById('top10'));
 | 
			
		||||
            var monthMetricsECharts = ec.init(document.getElementById('month_metrics_echarts'));
 | 
			
		||||
            var option = {
 | 
			
		||||
                title : {
 | 
			
		||||
                    text: "{% trans 'Monthly data overview' %}",
 | 
			
		||||
| 
						 | 
				
			
			@ -284,7 +204,7 @@ $(document).ready(function(){
 | 
			
		|||
                    {
 | 
			
		||||
                        type : 'category',
 | 
			
		||||
                        boundaryGap : false,
 | 
			
		||||
                        data : {{ month_str|safe}}
 | 
			
		||||
                        data : data['month_metrics_date'],
 | 
			
		||||
                    }
 | 
			
		||||
                ],
 | 
			
		||||
                yAxis : [
 | 
			
		||||
| 
						 | 
				
			
			@ -298,38 +218,42 @@ $(document).ready(function(){
 | 
			
		|||
                        type:'line',
 | 
			
		||||
                        smooth: true,
 | 
			
		||||
                        itemStyle: {normal: {areaStyle: {type: 'default'}}},
 | 
			
		||||
                        data: {{ month_total_visit_count|safe}}
 | 
			
		||||
                        data: data['month_metrics_total_count_login']
 | 
			
		||||
                    },
 | 
			
		||||
                    {
 | 
			
		||||
                        name: "{% trans 'Active users' %}",
 | 
			
		||||
                        type: 'line',
 | 
			
		||||
                        smooth: true,
 | 
			
		||||
                        itemStyle: {normal: {areaStyle: {type: 'default'}}},
 | 
			
		||||
                        data: {{ month_user|safe }}
 | 
			
		||||
                        data: data['month_metrics_total_count_active_users']
 | 
			
		||||
                    },
 | 
			
		||||
                    {
 | 
			
		||||
                        name:"{% trans 'Active assets' %}",
 | 
			
		||||
                        type:'line',
 | 
			
		||||
                        smooth:true,
 | 
			
		||||
                        itemStyle: {normal: {areaStyle: {type: 'default'}}},
 | 
			
		||||
                        data: {{ mouth_asset|safe }}
 | 
			
		||||
                        data: data['month_metrics_total_count_active_assets']
 | 
			
		||||
                    }
 | 
			
		||||
                ]
 | 
			
		||||
            };
 | 
			
		||||
            top10Chart.setOption(option);
 | 
			
		||||
            monthMetricsECharts.setOption(option);
 | 
			
		||||
        }
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function requireMonthTotalCountUsersPie(data){
 | 
			
		||||
    require(
 | 
			
		||||
        [
 | 
			
		||||
            'echarts',
 | 
			
		||||
            'echarts/chart/pie'
 | 
			
		||||
        ],
 | 
			
		||||
        function (ec) {
 | 
			
		||||
            var auChart = ec.init(document.getElementById('activeUser'));
 | 
			
		||||
            var monthTotalCountUsersPie = ec.init(document.getElementById('month_total_count_users_pie'));
 | 
			
		||||
            var option = {
 | 
			
		||||
                tooltip : {
 | 
			
		||||
                    trigger: 'item',
 | 
			
		||||
                    formatter: "{b} <br> {c} ({d}%)"
 | 
			
		||||
                    formatter: "{b} <br> {c} <br> ({d}%)"
 | 
			
		||||
                },
 | 
			
		||||
                legend: {
 | 
			
		||||
                    show: false,
 | 
			
		||||
| 
						 | 
				
			
			@ -364,6 +288,7 @@ $(document).ready(function(){
 | 
			
		|||
                        name:"{% trans 'Access to the source' %}",
 | 
			
		||||
                        type:'pie',
 | 
			
		||||
                        radius : ['50%', '70%'],
 | 
			
		||||
                        avoidLabelOverlap: false,
 | 
			
		||||
                        itemStyle : {
 | 
			
		||||
                            normal : {
 | 
			
		||||
                                label : {
 | 
			
		||||
| 
						 | 
				
			
			@ -385,33 +310,36 @@ $(document).ready(function(){
 | 
			
		|||
                            }
 | 
			
		||||
                        },
 | 
			
		||||
                        data:[
 | 
			
		||||
                            {value:{{ month_user_active }}, name:"{% trans 'Monthly active users' %}"},
 | 
			
		||||
                            {value:{{ month_user_disabled }}, name:"{% trans 'Disable user' %}"},
 | 
			
		||||
                            {value:{{ month_user_inactive }}, name:"{% trans 'Month not logged in user' %}"}
 | 
			
		||||
                            {value:data['month_total_count_active_users'], name:"{% trans 'Monthly active users' %}"},
 | 
			
		||||
                            {value:data['month_total_count_disabled_users'], name:"{% trans 'Disable user' %}"},
 | 
			
		||||
                            {value:data['month_total_count_inactive_users'], name:"{% trans 'Month not logged in user' %}"}
 | 
			
		||||
                        ]
 | 
			
		||||
                    }
 | 
			
		||||
                ]
 | 
			
		||||
            };
 | 
			
		||||
            auChart.setOption(option);
 | 
			
		||||
            monthTotalCountUsersPie.setOption(option);
 | 
			
		||||
        }
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function requireMonthTotalCountAssetsPie(data){
 | 
			
		||||
    require(
 | 
			
		||||
        [
 | 
			
		||||
            'echarts',
 | 
			
		||||
            'echarts/chart/pie'
 | 
			
		||||
        ],
 | 
			
		||||
        function (ec) {
 | 
			
		||||
            var aaChart = ec.init(document.getElementById('activeAsset'));
 | 
			
		||||
            var monthTotalCountAssetsPie = ec.init(document.getElementById('month_total_count_assets_pie'));
 | 
			
		||||
            var option = {
 | 
			
		||||
                tooltip : {
 | 
			
		||||
                    trigger: 'item',
 | 
			
		||||
                    formatter: "{b} <br> {c} ({d}%)"
 | 
			
		||||
                    formatter: "{b} <br> {c} <br> ({d}%)"
 | 
			
		||||
                },
 | 
			
		||||
                legend: {
 | 
			
		||||
                    show: false,
 | 
			
		||||
                    orient : 'vertical',
 | 
			
		||||
                    x : 'left',
 | 
			
		||||
                    data:["{% trans 'Month is logged into the host' %}", "{% trans 'Disable host' %}", "{% trans 'Month not logged on host' %}"]
 | 
			
		||||
                    data:["{% trans 'Month is logged into the asset' %}", "{% trans 'Disable host' %}", "{% trans 'Month not logged on host' %}"]
 | 
			
		||||
                },
 | 
			
		||||
                toolbox: {
 | 
			
		||||
                    show : false,
 | 
			
		||||
| 
						 | 
				
			
			@ -461,16 +389,230 @@ $(document).ready(function(){
 | 
			
		|||
                            }
 | 
			
		||||
                        },
 | 
			
		||||
                        data:[
 | 
			
		||||
                            {value:{{ month_asset_active }}, name:"{% trans 'Month is logged into the host' %}"},
 | 
			
		||||
                            {value:{{ month_asset_disabled }}, name:"{% trans 'Disable host' %}"},
 | 
			
		||||
                            {value:{{ month_asset_inactive }}, name:"{% trans 'Month not logged on host' %}"}
 | 
			
		||||
                            {value:data['month_total_count_active_assets'], name:"{% trans 'Month is logged into the host' %}"},
 | 
			
		||||
                            {value:data['month_total_count_disabled_assets'], name:"{% trans 'Disable host' %}"},
 | 
			
		||||
                            {value:data['month_total_count_inactive_assets'], name:"{% trans 'Month not logged on host' %}"}
 | 
			
		||||
                        ]
 | 
			
		||||
                    }
 | 
			
		||||
                ]
 | 
			
		||||
            };
 | 
			
		||||
            aaChart.setOption(option);
 | 
			
		||||
            monthTotalCountAssetsPie.setOption(option);
 | 
			
		||||
        }
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var indexUrl = "/api/v1/index/";
 | 
			
		||||
 | 
			
		||||
function renderRequestApi(query, success, error){
 | 
			
		||||
    var url = indexUrl + "?" + query;
 | 
			
		||||
    if (!error){
 | 
			
		||||
        error = function (){console.log("Request url error: " + url)}
 | 
			
		||||
    }
 | 
			
		||||
    requestApi({
 | 
			
		||||
        url: url,
 | 
			
		||||
        method: "GET",
 | 
			
		||||
        success: success,
 | 
			
		||||
        error: error,
 | 
			
		||||
        flash_message: false,
 | 
			
		||||
    })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function renderTotalCount(){
 | 
			
		||||
     var success = function (data) {
 | 
			
		||||
         $('#total_count_assets').html(data['total_count_assets']);
 | 
			
		||||
         $('#total_count_users').html(data['total_count_users']);
 | 
			
		||||
         $('#total_count_online_users').html(data['total_count_online_users']);
 | 
			
		||||
         $('#total_count_online_assets').html(data['total_count_online_assets']);
 | 
			
		||||
     };
 | 
			
		||||
    renderRequestApi('total_count=1', success);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function renderMonthMetricsECharts(){
 | 
			
		||||
    var success = function (data) {
 | 
			
		||||
        requireMonthMetricsECharts(data)
 | 
			
		||||
    };
 | 
			
		||||
    renderRequestApi('month_metrics=1', success)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function renderMonthTotalCountUsersPie(){
 | 
			
		||||
    var success = function (data) {
 | 
			
		||||
        requireMonthTotalCountUsersPie(data)
 | 
			
		||||
    };
 | 
			
		||||
    renderRequestApi('month_total_count_users=1', success)
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function renderMonthTotalCountAssetsPie(){
 | 
			
		||||
    var success = function (data) {
 | 
			
		||||
        requireMonthTotalCountAssetsPie(data)
 | 
			
		||||
    };
 | 
			
		||||
    renderRequestApi('month_total_count_assets=1', success)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function renderWeekTotalCount(){
 | 
			
		||||
    var success = function (data) {
 | 
			
		||||
        $('#week_total_count_login_users').html(data['week_total_count_login_users']);
 | 
			
		||||
        $('#week_total_count_login_times').html(data['week_total_count_login_times'])
 | 
			
		||||
    };
 | 
			
		||||
    renderRequestApi('week_total_count=1', success)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function renderWeekLoginTimesTop5Users(){
 | 
			
		||||
    var success = function (data){
 | 
			
		||||
        var html = "";
 | 
			
		||||
        var html_cell = "" +
 | 
			
		||||
            "<li class=\"list-group-item fist-item\">" +
 | 
			
		||||
            "<span class=\"pull-right\">" +
 | 
			
		||||
            "{TOTAL} {% trans ' times/week' %}" +
 | 
			
		||||
            "</span>" +
 | 
			
		||||
            "<span class=\"label \">{INDEX}</span> {USER}" +
 | 
			
		||||
            "</li>";
 | 
			
		||||
 | 
			
		||||
        $.each(data['week_login_times_top5_users'], function(index, value){
 | 
			
		||||
            html += html_cell.replace('{TOTAL}', value['total'])
 | 
			
		||||
                .replace('{USER}', value['user'])
 | 
			
		||||
                .replace('{INDEX}', index+1)
 | 
			
		||||
        });
 | 
			
		||||
        $('#week_login_times_top5_users').html(html)
 | 
			
		||||
    };
 | 
			
		||||
    renderRequestApi('week_login_times_top5_users=1', success)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function renderWeekLoginTimesTop10Assets(){
 | 
			
		||||
    var success = function (data){
 | 
			
		||||
        var html = "";
 | 
			
		||||
        var html_cell = "" +
 | 
			
		||||
            "<div class=\"timeline-item\">" +
 | 
			
		||||
            "<div class=\"row\">" +
 | 
			
		||||
            "<div class=\"col-xs-5 date ellipsis\">" +
 | 
			
		||||
            "<i class=\"fa fa-info-circle\"></i>" +
 | 
			
		||||
            "<strong data-toggle=\"tooltip\" title=\"{ASSET}\">{ASSET}</strong>" +
 | 
			
		||||
            "<br/>" +
 | 
			
		||||
            "<small class=\"text-navy\">{TOTAL}{% trans ' times' %}</small>" +
 | 
			
		||||
            "</div>" +
 | 
			
		||||
            "<div class=\"col-xs-7 content no-top-border\">" +
 | 
			
		||||
            "<p class=\"m-b-xs\">{% trans 'The time last logged in' %}</p>" +
 | 
			
		||||
            "<p>{% trans 'At' %} {DATE_LAST}</p>" +
 | 
			
		||||
            "</div>" +
 | 
			
		||||
            "</div>" +
 | 
			
		||||
            "</div>";
 | 
			
		||||
 | 
			
		||||
        var assets = data['week_login_times_top10_assets'];
 | 
			
		||||
        if (assets.length !== 0){
 | 
			
		||||
            $.each(assets, function(index, value){
 | 
			
		||||
                html += html_cell
 | 
			
		||||
                    .replaceAll('{ASSET}', value['asset'])
 | 
			
		||||
                    .replace('{TOTAL}', value['total'])
 | 
			
		||||
                    .replace('{DATE_LAST}', toSafeLocalDateStr(value['last']))
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
        else{
 | 
			
		||||
            html += "<p class=\"text-center\">{% trans '(No)' %}</p>"
 | 
			
		||||
        }
 | 
			
		||||
        $('#week_login_times_top10_assets').html(html)
 | 
			
		||||
    };
 | 
			
		||||
    renderRequestApi('week_login_times_top10_assets=1', success)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function renderWeekLoginTimesTop10Users(){
 | 
			
		||||
    var success = function (data){
 | 
			
		||||
        var html = "";
 | 
			
		||||
        var html_cell = "" +
 | 
			
		||||
            "<div class=\"timeline-item\">" +
 | 
			
		||||
            "<div class=\"row\">" +
 | 
			
		||||
            "<div class=\"col-xs-5 date ellipsis\">" +
 | 
			
		||||
            "<i class=\"fa fa-info-circle\"></i>" +
 | 
			
		||||
            "<strong data-toggle=\"tooltip\" title=\"{USER}\">{USER}</strong>" +
 | 
			
		||||
            "<br/>" +
 | 
			
		||||
            "<small class=\"text-navy\">{TOTAL}{% trans ' times' %}</small>" +
 | 
			
		||||
            "</div>" +
 | 
			
		||||
            "<div class=\"col-xs-7 content no-top-border\">" +
 | 
			
		||||
            "<p class=\"m-b-xs\">{% trans 'The time last logged in' %}</p>" +
 | 
			
		||||
            "<p>{% trans 'At' %} {DATE_LAST}</p>" +
 | 
			
		||||
            "</div>" +
 | 
			
		||||
            "</div>" +
 | 
			
		||||
            "</div>";
 | 
			
		||||
 | 
			
		||||
        var users = data['week_login_times_top10_users'];
 | 
			
		||||
        if (users.length !== 0){
 | 
			
		||||
            $.each(users, function(index, value){
 | 
			
		||||
                html += html_cell.replaceAll('{USER}', value['user'])
 | 
			
		||||
                    .replace('{TOTAL}', value['total'])
 | 
			
		||||
                    .replace('{DATE_LAST}', toSafeLocalDateStr(value['last']))
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
        else{
 | 
			
		||||
            html += "<p class=\"text-center\">{% trans '(No)' %}</p>"
 | 
			
		||||
        }
 | 
			
		||||
        $('#week_login_times_top10_users').html(html)
 | 
			
		||||
    };
 | 
			
		||||
    renderRequestApi('week_login_times_top10_users=1', success)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function renderWeekLoginRecordTop10Sessions(){
 | 
			
		||||
    var success = function (data){
 | 
			
		||||
        var html = "";
 | 
			
		||||
        var html_cell = "" +
 | 
			
		||||
            "<div class=\"feed-element\">" +
 | 
			
		||||
            "<a href=\"#\" class=\"pull-left\">" +
 | 
			
		||||
            "<img alt=\"image\" class=\"img-circle\" src=\"{% static 'img/avatar/user.png' %}\">" +
 | 
			
		||||
            "</a>" +
 | 
			
		||||
            "<div class=\"media-body \">" +
 | 
			
		||||
            "<small class=\"pull-right {TEXT_NAVY}\">{TIMESINCE} {% trans 'Before' %}</small>" +
 | 
			
		||||
            "<strong>{USER}</strong> {% trans 'Login in ' %}{ASSET} <br>" +
 | 
			
		||||
            "<small class=\"text-muted\">{DATE_START}</small>" +
 | 
			
		||||
            "</div>" +
 | 
			
		||||
            "</div>";
 | 
			
		||||
 | 
			
		||||
        var users = data['week_login_record_top10_sessions'];
 | 
			
		||||
        if (users.length !== 0){
 | 
			
		||||
            $.each(users, function(index, value){
 | 
			
		||||
                console.log(value['is_finished'])
 | 
			
		||||
                html += html_cell.replaceAll('{USER}', value['user'])
 | 
			
		||||
                    .replace('{ASSET}', value['asset'])
 | 
			
		||||
                    .replace('{DATE_START}', toSafeLocalDateStr(value['date_start']))
 | 
			
		||||
                    .replace('{TEXT_NAVY}', value['is_finished']?'':'text-navy')
 | 
			
		||||
                    .replace('{TIMESINCE}', value['timesince'])
 | 
			
		||||
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
        else{
 | 
			
		||||
            html += "<p class=\"text-center\">{% trans '(No)' %}</p>"
 | 
			
		||||
        }
 | 
			
		||||
        $('#week_login_record_top10_sessions').html(html)
 | 
			
		||||
 | 
			
		||||
    };
 | 
			
		||||
    renderRequestApi('week_login_record_top10_sessions=1', success)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function renderData(){
 | 
			
		||||
    renderTotalCount();
 | 
			
		||||
    renderMonthMetricsECharts();
 | 
			
		||||
    renderMonthTotalCountUsersPie();
 | 
			
		||||
    renderMonthTotalCountAssetsPie();
 | 
			
		||||
    renderWeekTotalCount();
 | 
			
		||||
    renderWeekLoginTimesTop5Users();
 | 
			
		||||
    renderWeekLoginTimesTop10Assets();
 | 
			
		||||
    renderWeekLoginRecordTop10Sessions();
 | 
			
		||||
    renderWeekLoginTimesTop10Users();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
require.config({
 | 
			
		||||
    paths: {
 | 
			
		||||
        'echarts': '/static/js/plugins/echarts/chart/',
 | 
			
		||||
        'echarts/chart/line': '/static/js/plugins/echarts/chart/line',
 | 
			
		||||
        'echarts/chart/pie': '/static/js/plugins/echarts/chart/pie'
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
$(document).ready(function(){
 | 
			
		||||
    $('#show').click(function(){
 | 
			
		||||
        $('#show').css('display', 'none');
 | 
			
		||||
        $('#more').css('display', 'block');
 | 
			
		||||
    });
 | 
			
		||||
    $("[data-toggle='tooltip']").tooltip();
 | 
			
		||||
    renderData()
 | 
			
		||||
});
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
{% endblock %}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,9 +1,13 @@
 | 
			
		|||
# -*- coding: utf-8 -*-
 | 
			
		||||
#
 | 
			
		||||
from .. import utils
 | 
			
		||||
from users.models import User
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class UserQuerysetMixin:
 | 
			
		||||
    def get_queryset(self):
 | 
			
		||||
        queryset = utils.get_current_org_members()
 | 
			
		||||
        if self.request.query_params.get('all'):
 | 
			
		||||
            queryset = User.objects.exclude(role=User.ROLE_APP)
 | 
			
		||||
        else:
 | 
			
		||||
            queryset = utils.get_current_org_members()
 | 
			
		||||
        return queryset
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue