Merge pull request #3975 from jumpserver/dev_master

Dev master
pull/3978/head
BaiJiangJie 2020-05-08 16:42:32 +08:00 committed by GitHub
commit 2d48c8028b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 757 additions and 500 deletions

View File

@ -76,14 +76,9 @@ class TreeService(Tree):
ancestor_ids.pop(0) ancestor_ids.pop(0)
return ancestor_ids 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) ancestor_ids = self.ancestors_ids(nid, with_self=with_self)
ancestors = [self.get_node(i, deep=deep) for i in ancestor_ids] 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 return ancestors
def get_node_full_tag(self, nid): def get_node_full_tag(self, nid):
@ -108,6 +103,7 @@ class TreeService(Tree):
node = super().get_node(nid) node = super().get_node(nid)
if deep: if deep:
node = self.copy_node(node) node = self.copy_node(node)
node.data = {}
return node return node
def parent(self, nid, deep=False): def parent(self, nid, deep=False):

295
apps/jumpserver/api.py Normal file
View File

@ -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)

View File

@ -7,9 +7,10 @@ from django.conf.urls.static import static
from django.conf.urls.i18n import i18n_patterns from django.conf.urls.i18n import i18n_patterns
from django.views.i18n import JavaScriptCatalog from django.views.i18n import JavaScriptCatalog
from . import views from . import views, api
api_v1 = [ api_v1 = [
path('index/', api.IndexApi.as_view()),
path('users/', include('users.urls.api_urls', namespace='api-users')), path('users/', include('users.urls.api_urls', namespace='api-users')),
path('assets/', include('assets.urls.api_urls', namespace='api-assets')), path('assets/', include('assets.urls.api_urls', namespace='api-assets')),
path('perms/', include('perms.urls.api_urls', namespace='api-perms')), path('perms/', include('perms.urls.api_urls', namespace='api-perms')),

View File

@ -1,224 +1,12 @@
from django.core.cache import cache
from django.views.generic import TemplateView from django.views.generic import TemplateView
from django.utils import timezone
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from django.db.models import Count, Max
from django.shortcuts import redirect 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.permissions import PermissionsMixin, IsValidUser
from common.utils import timeit, lazyproperty
__all__ = ['IndexView'] __all__ = ['IndexView']
class MonthLoginMetricMixin: class IndexView(PermissionsMixin, TemplateView):
@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):
template_name = 'index.html' template_name = 'index.html'
permission_classes = [IsValidUser] permission_classes = [IsValidUser]
@ -229,31 +17,9 @@ class IndexView(PermissionsMixin, MonthLoginMetricMixin, WeekSessionMetricMixin,
return redirect('assets:user-asset-list') return redirect('assets:user-asset-list')
return super(IndexView, self).dispatch(request, *args, **kwargs) 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): def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs) context = super().get_context_data(**kwargs)
context.update({ 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"), 'app': _("Dashboard"),
}) })
return context return context

Binary file not shown.

View File

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: JumpServer 0.3.3\n" "Project-Id-Version: JumpServer 0.3.3\n"
"Report-Msgid-Bugs-To: \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" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: ibuler <ibuler@qq.com>\n" "Last-Translator: ibuler <ibuler@qq.com>\n"
"Language-Team: JumpServer team<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_asset.html:53
#: perms/templates/perms/asset_permission_create_update.html:57 #: perms/templates/perms/asset_permission_create_update.html:57
#: perms/templates/perms/asset_permission_list.html:35 #: 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/backends/command/models.py:19 terminal/models.py:187
#: terminal/templates/terminal/command_list.html:31 #: terminal/templates/terminal/command_list.html:31
#: terminal/templates/terminal/command_list.html:106 #: 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_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_execution_subtask_list.html:13
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_list.html:14 #: 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/cloud/templates/cloud/sync_instance_task_instance.html:47
#: xpack/plugins/orgs/templates/orgs/org_list.html:17 #: xpack/plugins/orgs/templates/orgs/org_list.html:17
#: xpack/plugins/vault/forms.py:13 xpack/plugins/vault/forms.py:15 #: 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_detail.html:53
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_list.html:12 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_list.html:12
#: xpack/plugins/gathered_user/templates/gathered_user/task_list.html:16 #: 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_list.html:12
#: xpack/plugins/orgs/templates/orgs/org_users.html:46
msgid "Name" msgid "Name"
msgstr "名称" msgstr "名称"
@ -194,7 +196,7 @@ msgstr "类型"
#: applications/templates/applications/database_app_detail.html:56 #: applications/templates/applications/database_app_detail.html:56
#: applications/templates/applications/database_app_list.html:25 #: applications/templates/applications/database_app_list.html:25
#: applications/templates/applications/user_database_app_list.html:18 #: 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 #: users/templates/users/user_granted_database_app.html:36
msgid "Host" msgid "Host"
msgstr "主机" msgstr "主机"
@ -260,13 +262,13 @@ msgstr "数据库"
#: xpack/plugins/change_auth_plan/models.py:75 #: 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_detail.html:115
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_list.html:19 #: 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_detail.html:67
#: xpack/plugins/cloud/templates/cloud/account_list.html:15 #: 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/cloud/templates/cloud/sync_instance_task_list.html:18
#: xpack/plugins/gathered_user/models.py:26 #: 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 #: xpack/plugins/orgs/templates/orgs/org_list.html:23
msgid "Comment" msgid "Comment"
msgstr "备注" msgstr "备注"
@ -323,7 +325,7 @@ msgstr "参数"
#: users/templates/users/user_detail.html:97 #: users/templates/users/user_detail.html:97
#: xpack/plugins/change_auth_plan/models.py:79 #: xpack/plugins/change_auth_plan/models.py:79
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:111 #: 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 #: xpack/plugins/gathered_user/models.py:30
msgid "Created by" msgid "Created by"
msgstr "创建者" msgstr "创建者"
@ -350,10 +352,10 @@ msgstr "创建者"
#: tickets/templates/tickets/ticket_detail.html:52 users/models/group.py:18 #: tickets/templates/tickets/ticket_detail.html:52 users/models/group.py:18
#: users/templates/users/user_group_detail.html:58 #: users/templates/users/user_group_detail.html:58
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:103 #: 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/account_detail.html:63
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:98 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:108
#: xpack/plugins/orgs/templates/orgs/org_detail.html:55 #: xpack/plugins/orgs/templates/orgs/org_detail.html:59
msgid "Date created" msgid "Date created"
msgstr "创建日期" msgstr "创建日期"
@ -405,7 +407,7 @@ msgstr "远程应用"
#: users/templates/users/user_pubkey_update.html:80 #: users/templates/users/user_pubkey_update.html:80
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_create_update.html:65 #: 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/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/gathered_user/templates/gathered_user/task_create_update.html:40
#: xpack/plugins/interface/templates/interface/interface.html:72 #: xpack/plugins/interface/templates/interface/interface.html:72
#: xpack/plugins/orgs/templates/orgs/org_create_update.html:29 #: 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_detail.html:26
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_list.html:60 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_list.html:60
#: xpack/plugins/gathered_user/templates/gathered_user/task_list.html:46 #: 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 #: xpack/plugins/orgs/templates/orgs/org_list.html:93
msgid "Update" msgid "Update"
msgstr "更新" 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_detail.html:30
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_list.html:61 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_list.html:61
#: xpack/plugins/gathered_user/templates/gathered_user/task_list.html:47 #: 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 #: xpack/plugins/orgs/templates/orgs/org_list.html:95
msgid "Delete" msgid "Delete"
msgstr "删除" msgstr "删除"
@ -648,6 +650,7 @@ msgstr "创建数据库应用"
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_list.html:19 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_list.html:19
#: xpack/plugins/gathered_user/templates/gathered_user/task_list.html:20 #: 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_list.html:24
#: xpack/plugins/orgs/templates/orgs/org_users.html:47
msgid "Action" msgid "Action"
msgstr "动作" msgstr "动作"
@ -871,6 +874,7 @@ msgstr "用户名"
#: ops/templates/ops/task_detail.html:95 #: ops/templates/ops/task_detail.html:95
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:82 #: 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:72
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:82
msgid "Yes" msgid "Yes"
msgstr "是" msgstr "是"
@ -878,6 +882,7 @@ msgstr "是"
#: ops/templates/ops/task_detail.html:97 #: ops/templates/ops/task_detail.html:97
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:84 #: 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:74
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:84
msgid "No" msgid "No"
msgstr "否" msgstr "否"
@ -1318,7 +1323,7 @@ msgstr "默认资产组"
#: perms/templates/perms/database_app_permission_list.html:15 #: 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_create_update.html:41
#: perms/templates/perms/remote_app_permission_list.html:15 #: 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/models.py:185 terminal/templates/terminal/command_list.html:30
#: terminal/templates/terminal/command_list.html:105 #: terminal/templates/terminal/command_list.html:105
#: terminal/templates/terminal/session_detail.html:48 #: 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:37
#: users/templates/users/user_remote_app_permission.html:58 #: users/templates/users/user_remote_app_permission.html:58
#: users/views/profile/base.py:46 xpack/plugins/orgs/forms.py:27 #: 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 #: xpack/plugins/orgs/templates/orgs/org_list.html:15
msgid "User" msgid "User"
msgstr "用户" msgstr "用户"
@ -1407,7 +1411,7 @@ msgstr "资产管理"
#: assets/models/user.py:111 assets/templates/assets/system_user_users.html:76 #: 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 #: 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/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/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: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 #: 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 #: ops/templates/ops/command_execution_create.html:112
#: settings/templates/settings/_ldap_list_users_modal.html:41 #: settings/templates/settings/_ldap_list_users_modal.html:41
#: users/templates/users/_granted_assets.html:7 #: 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" msgid "Loading"
msgstr "加载中" msgstr "加载中"
@ -1888,7 +1892,7 @@ msgstr "自动生成密钥"
#: perms/templates/perms/remote_app_permission_create_update.html:51 #: perms/templates/perms/remote_app_permission_create_update.html:51
#: terminal/templates/terminal/terminal_update.html:38 #: terminal/templates/terminal/terminal_update.html:38
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_create_update.html:61 #: 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 #: xpack/plugins/gathered_user/templates/gathered_user/task_create_update.html:35
msgid "Other" msgid "Other"
msgstr "其它" msgstr "其它"
@ -1957,7 +1961,7 @@ msgstr "选择节点"
#: users/templates/users/user_list.html:184 #: users/templates/users/user_list.html:184
#: users/templates/users/user_password_verify.html:20 #: users/templates/users/user_password_verify.html:20
#: xpack/plugins/cloud/templates/cloud/account_create_update.html:30 #: 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/gathered_user/templates/gathered_user/task_create_update.html:41
#: xpack/plugins/interface/templates/interface/interface.html:103 #: xpack/plugins/interface/templates/interface/interface.html:103
#: xpack/plugins/orgs/templates/orgs/org_create_update.html:30 #: 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_detail.html:126
#: users/templates/users/user_profile.html:150 #: users/templates/users/user_profile.html:150
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:126 #: 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 #: xpack/plugins/license/templates/license/license_detail.html:80
msgid "Quick modify" msgid "Quick modify"
msgstr "快速修改" msgstr "快速修改"
@ -2530,7 +2534,7 @@ msgstr "启用"
msgid "-" msgid "-"
msgstr "" msgstr ""
#: audits/models.py:78 xpack/plugins/cloud/models.py:201 #: audits/models.py:78 xpack/plugins/cloud/models.py:204
msgid "Failed" msgid "Failed"
msgstr "失败" msgstr "失败"
@ -2563,7 +2567,7 @@ msgstr "多因子认证"
#: audits/models.py:87 audits/templates/audits/login_log_list.html:63 #: 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/models.py:286
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_subtask_list.html:15 #: 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" msgid "Reason"
msgstr "原因" msgstr "原因"
@ -2571,7 +2575,7 @@ msgstr "原因"
#: tickets/templates/tickets/ticket_detail.html:34 #: tickets/templates/tickets/ticket_detail.html:34
#: tickets/templates/tickets/ticket_list.html:36 #: tickets/templates/tickets/ticket_list.html:36
#: tickets/templates/tickets/ticket_list.html:104 #: 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_history.html:50
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_instance.html:48 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_instance.html:48
msgid "Status" msgid "Status"
@ -2603,6 +2607,7 @@ msgstr "开始日期"
#: perms/templates/perms/asset_permission_user.html:74 #: perms/templates/perms/asset_permission_user.html:74
#: perms/templates/perms/database_app_permission_user.html:74 #: perms/templates/perms/database_app_permission_user.html:74
#: perms/templates/perms/remote_app_permission_user.html:83 #: perms/templates/perms/remote_app_permission_user.html:83
#: xpack/plugins/orgs/templates/orgs/org_users.html:67
msgid "Select user" msgid "Select user"
msgstr "选择用户" msgstr "选择用户"
@ -3007,7 +3012,7 @@ msgstr "字段必须唯一"
msgid "<h1>Flow service unavailable, check it</h1>" msgid "<h1>Flow service unavailable, check it</h1>"
msgstr "" msgstr ""
#: jumpserver/views/index.py:257 templates/_nav.html:7 #: jumpserver/views/index.py:23 templates/_nav.html:7
msgid "Dashboard" msgid "Dashboard"
msgstr "仪表盘" msgstr "仪表盘"
@ -3044,13 +3049,13 @@ msgstr "没有该主机 {} 权限"
#: ops/mixin.py:29 ops/mixin.py:92 ops/mixin.py:162 #: 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/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" msgid "Cycle perform"
msgstr "周期执行" msgstr "周期执行"
#: ops/mixin.py:33 ops/mixin.py:90 ops/mixin.py:111 ops/mixin.py:150 #: 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/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" msgid "Regularly perform"
msgstr "定期执行" 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_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_detail.html:79
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_list.html:17 #: 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_create_update.html:40
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:69 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:79
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_list.html:16 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_list.html:16
#: xpack/plugins/gathered_user/templates/gathered_user/task_create_update.html:28 #: xpack/plugins/gathered_user/templates/gathered_user/task_create_update.html:28
msgid "Periodic perform" msgid "Periodic perform"
@ -3120,7 +3125,7 @@ msgstr "Become"
#: ops/models/adhoc.py:150 users/templates/users/user_group_detail.html:54 #: ops/models/adhoc.py:150 users/templates/users/user_group_detail.html:54
#: xpack/plugins/cloud/templates/cloud/account_detail.html:59 #: 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" msgid "Create by"
msgstr "创建者" msgstr "创建者"
@ -3180,7 +3185,7 @@ msgstr "{} 任务结束"
#: ops/models/command.py:24 #: ops/models/command.py:24
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_list.html:56 #: 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" msgid "Result"
msgstr "结果" msgstr "结果"
@ -3398,7 +3403,7 @@ msgstr "内容"
#: ops/templates/ops/task_list.html:73 #: 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_detail.html:135
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_list.html:54 #: 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/cloud/templates/cloud/sync_instance_task_list.html:58
#: xpack/plugins/gathered_user/templates/gathered_user/task_list.html:44 #: xpack/plugins/gathered_user/templates/gathered_user/task_list.html:44
msgid "Run" msgid "Run"
@ -3573,8 +3578,9 @@ msgstr "添加资产"
#: perms/templates/perms/remote_app_permission_user.html:120 #: perms/templates/perms/remote_app_permission_user.html:120
#: users/templates/users/user_group_detail.html:87 #: users/templates/users/user_group_detail.html:87
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_asset_list.html:76 #: 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:89
#: xpack/plugins/orgs/templates/orgs/org_detail.html:125 #: xpack/plugins/orgs/templates/orgs/org_detail.html:123
#: xpack/plugins/orgs/templates/orgs/org_users.html:73
msgid "Add" msgid "Add"
msgstr "添加" msgstr "添加"
@ -3673,6 +3679,7 @@ msgstr "刷新成功"
#: perms/templates/perms/asset_permission_user.html:31 #: perms/templates/perms/asset_permission_user.html:31
#: perms/templates/perms/database_app_permission_user.html:31 #: perms/templates/perms/database_app_permission_user.html:31
#: perms/templates/perms/remote_app_permission_user.html:30 #: perms/templates/perms/remote_app_permission_user.html:30
#: xpack/plugins/orgs/templates/orgs/org_users.html:24
msgid "User list of " msgid "User list of "
msgstr "用户列表" msgstr "用户列表"
@ -4624,8 +4631,8 @@ msgid "Total users"
msgstr "用户总数" msgstr "用户总数"
#: templates/index.html:23 #: templates/index.html:23
msgid "Total hosts" msgid "Total assets"
msgstr "主机总数" msgstr "资产总数"
#: templates/index.html:36 #: templates/index.html:36
msgid "Online users" msgid "Online users"
@ -4647,120 +4654,124 @@ msgstr " 位用户登录 "
msgid " times asset." msgid " times asset."
msgstr " 次资产." msgstr " 次资产."
#: templates/index.html:66 #: templates/index.html:69
msgid " times/week"
msgstr " 次/周"
#: templates/index.html:77
msgid "Active user asset ratio" msgid "Active user asset ratio"
msgstr "活跃用户资产占比" msgstr "活跃用户资产占比"
#: templates/index.html:80 #: templates/index.html:72
msgid "" msgid ""
"The following graphs describe the percentage of active users per month and " "The following graphs describe the percentage of active users per month and "
"assets per user host per month, respectively." "assets per user host per month, respectively."
msgstr "以下图形分别描述一个月活跃用户和资产占所有用户主机的百分比" msgstr "以下图形分别描述一个月活跃用户和资产占所有用户主机的百分比"
#: templates/index.html:105 templates/index.html:120 #: templates/index.html:97 templates/index.html:112
msgid "Top 10 assets in a week" msgid "Top 10 assets in a week"
msgstr "一周Top10资产" msgstr "一周Top10资产"
#: templates/index.html:121 #: templates/index.html:113
msgid "Login frequency and last login record." msgid "Login frequency and last login record."
msgstr "登录次数及最近一次登录记录." msgstr "登录次数及最近一次登录记录."
#: templates/index.html:132 templates/index.html:218 #: templates/index.html:122
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
msgid "Last 10 login" msgid "Last 10 login"
msgstr "最近十次登录" msgstr "最近十次登录"
#: templates/index.html:156 #: templates/index.html:128
msgid "Login record" msgid "Login record"
msgstr "登录记录" msgstr "登录记录"
#: templates/index.html:157 #: templates/index.html:129
msgid "Last 10 login records." msgid "Last 10 login records."
msgstr "最近十次登录记录." msgstr "最近十次登录记录."
#: templates/index.html:170 templates/index.html:172 #: templates/index.html:143 templates/index.html:158
msgid "Before"
msgstr "前"
#: templates/index.html:174
msgid "Login in "
msgstr "登录了"
#: templates/index.html:191 templates/index.html:206
msgid "Top 10 users in a week" msgid "Top 10 users in a week"
msgstr "一周Top10用户" msgstr "一周Top10用户"
#: templates/index.html:207 #: templates/index.html:159
msgid "User login frequency and last login record." msgid "User login frequency and last login record."
msgstr "用户登录次数及最近一次登录记录" msgstr "用户登录次数及最近一次登录记录"
#: templates/index.html:264 #: templates/index.html:184
msgid "Monthly data overview" msgid "Monthly data overview"
msgstr "月数据总览" msgstr "月数据总览"
#: templates/index.html:265 #: templates/index.html:185
msgid "History summary in one month" msgid "History summary in one month"
msgstr "一个月内历史汇总" msgstr "一个月内历史汇总"
#: templates/index.html:273 templates/index.html:297 #: templates/index.html:193 templates/index.html:217
msgid "Login count" msgid "Login count"
msgstr "登录次数" msgstr "登录次数"
#: templates/index.html:273 templates/index.html:304 #: templates/index.html:193 templates/index.html:224
msgid "Active users" msgid "Active users"
msgstr "活跃用户" msgstr "活跃用户"
#: templates/index.html:273 templates/index.html:311 #: templates/index.html:193 templates/index.html:231
msgid "Active assets" msgid "Active assets"
msgstr "活跃资产" msgstr "活跃资产"
#: templates/index.html:338 templates/index.html:388 #: templates/index.html:262 templates/index.html:313
msgid "Monthly active users" msgid "Monthly active users"
msgstr "月活跃用户" msgstr "月活跃用户"
#: templates/index.html:338 templates/index.html:389 #: templates/index.html:262 templates/index.html:314
msgid "Disable user" msgid "Disable user"
msgstr "禁用用户" msgstr "禁用用户"
#: templates/index.html:338 templates/index.html:390 #: templates/index.html:262 templates/index.html:315
msgid "Month not logged in user" msgid "Month not logged in user"
msgstr "月未登录用户" msgstr "月未登录用户"
#: templates/index.html:364 templates/index.html:440 #: templates/index.html:288 templates/index.html:368
msgid "Access to the source" msgid "Access to the source"
msgstr "访问来源" msgstr "访问来源"
#: templates/index.html:414 templates/index.html:464 #: templates/index.html:342
msgid "Month is logged into the host" msgid "Month is logged into the asset"
msgstr "月被登录主机" msgstr "月被登录资产"
#: templates/index.html:414 templates/index.html:465 #: templates/index.html:342 templates/index.html:393
msgid "Disable host" msgid "Disable host"
msgstr "禁用主机" msgstr "禁用主机"
#: templates/index.html:414 templates/index.html:466 #: templates/index.html:342 templates/index.html:394
msgid "Month not logged on host" msgid "Month not logged on host"
msgstr "月未登录主机" 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 #: templates/rest_framework/base.html:128
msgid "Filters" msgid "Filters"
msgstr "过滤" msgstr "过滤"
@ -4880,9 +4891,9 @@ msgid ""
" " " "
msgstr "" 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_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 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_instance.html:46
msgid "Region" msgid "Region"
msgstr "地域" msgstr "地域"
@ -5401,7 +5412,7 @@ msgstr "复制用户公钥到这里"
msgid "Join user groups" msgid "Join user groups"
msgstr "添加到用户组" 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 #: users/views/profile/password.py:57
msgid "* Your password does not meet the requirements" msgid "* Your password does not meet the requirements"
msgstr "* 您的密码不符合要求" msgstr "* 您的密码不符合要求"
@ -5427,6 +5438,7 @@ msgid "Administrator"
msgstr "管理员" msgstr "管理员"
#: users/models/user.py:145 xpack/plugins/orgs/forms.py:29 #: 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 #: xpack/plugins/orgs/templates/orgs/org_list.html:14
msgid "Auditor" msgid "Auditor"
msgstr "审计员" msgstr "审计员"
@ -5781,7 +5793,6 @@ msgid "User group detail"
msgstr "用户组详情" msgstr "用户组详情"
#: users/templates/users/user_group_detail.html:81 #: users/templates/users/user_group_detail.html:81
#: xpack/plugins/orgs/templates/orgs/org_detail.html:116
msgid "Add user" msgid "Add user"
msgstr "添加用户" msgstr "添加用户"
@ -5921,7 +5932,7 @@ msgid "Update user"
msgstr "更新用户" msgstr "更新用户"
#: users/templates/users/user_update.html:22 users/views/login.py:49 #: 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" msgid "User auth from {}, go there change password"
msgstr "用户认证源来自 {}, 请去相应系统修改密码" msgstr "用户认证源来自 {}, 请去相应系统修改密码"
@ -6143,28 +6154,28 @@ msgstr "用户组授权资产"
msgid "Email address invalid, please input again" msgid "Email address invalid, please input again"
msgstr "邮箱地址错误,重新输入" msgstr "邮箱地址错误,重新输入"
#: users/views/login.py:63 #: users/views/login.py:62
msgid "Send reset password message" msgid "Send reset password message"
msgstr "发送重置密码邮件" msgstr "发送重置密码邮件"
#: users/views/login.py:64 #: users/views/login.py:63
msgid "Send reset password mail success, login your mail box and follow it " msgid "Send reset password mail success, login your mail box and follow it "
msgstr "" msgstr ""
"发送重置邮件成功, 请登录邮箱查看, 按照提示操作 (如果没收到,请等待3-5分钟)" "发送重置邮件成功, 请登录邮箱查看, 按照提示操作 (如果没收到,请等待3-5分钟)"
#: users/views/login.py:77 #: users/views/login.py:76
msgid "Reset password success" msgid "Reset password success"
msgstr "重置密码成功" msgstr "重置密码成功"
#: users/views/login.py:78 #: users/views/login.py:77
msgid "Reset password success, return to login page" msgid "Reset password success, return to login page"
msgstr "重置密码成功,返回到登录页面" 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" msgid "Token invalid or expired"
msgstr "Token错误或失效" msgstr "Token错误或失效"
#: users/views/login.py:164 #: users/views/login.py:163
msgid "First login" msgid "First login"
msgstr "首次登录" msgstr "首次登录"
@ -6420,6 +6431,10 @@ msgstr "选择节点"
msgid "Select admins" msgid "Select admins"
msgstr "选择管理员" 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/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:44 xpack/plugins/cloud/views.py:62
#: xpack/plugins/cloud/views.py:78 xpack/plugins/cloud/views.py:92 #: xpack/plugins/cloud/views.py:78 xpack/plugins/cloud/views.py:92
@ -6464,48 +6479,52 @@ msgstr "地域"
msgid "Instances" msgid "Instances"
msgstr "实例" msgstr "实例"
#: xpack/plugins/cloud/models.py:139 #: xpack/plugins/cloud/models.py:136
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:94 #: 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 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_list.html:17
msgid "Date last sync" msgid "Date last sync"
msgstr "最后同步日期" 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" msgid "Sync instance task"
msgstr "同步实例任务" msgstr "同步实例任务"
#: xpack/plugins/cloud/models.py:202 #: xpack/plugins/cloud/models.py:205
msgid "Succeed" msgid "Succeed"
msgstr "成功" 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_history.html:51
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_instance.html:49 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_instance.html:49
msgid "Date sync" msgid "Date sync"
msgstr "同步日期" msgstr "同步日期"
#: xpack/plugins/cloud/models.py:245 #: xpack/plugins/cloud/models.py:248
msgid "Unsync" msgid "Unsync"
msgstr "未同步" 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" msgid "Synced"
msgstr "已同步" msgstr "已同步"
#: xpack/plugins/cloud/models.py:248 #: xpack/plugins/cloud/models.py:251
msgid "Released" msgid "Released"
msgstr "已释放" msgstr "已释放"
#: xpack/plugins/cloud/models.py:253 #: xpack/plugins/cloud/models.py:256
msgid "Sync task" msgid "Sync task"
msgstr "同步任务" msgstr "同步任务"
#: xpack/plugins/cloud/models.py:257 #: xpack/plugins/cloud/models.py:260
msgid "Sync instance task history" msgid "Sync instance task history"
msgstr "同步实例任务历史" msgstr "同步实例任务历史"
#: xpack/plugins/cloud/models.py:260 #: xpack/plugins/cloud/models.py:263
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:114
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_instance.html:45 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_instance.html:45
msgid "Instance" msgid "Instance"
msgstr "实例" msgstr "实例"
@ -6584,7 +6603,7 @@ msgstr "创建账户"
msgid "Node & AdminUser" msgid "Node & AdminUser"
msgstr "节点 & 管理用户" 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" msgid "Load failed"
msgstr "加载失败" msgstr "加载失败"
@ -6609,11 +6628,11 @@ msgstr "同步历史列表"
msgid "Sync instance list" msgid "Sync instance list"
msgstr "同步实例列表" 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" msgid "Run task manually"
msgstr "手动执行任务" 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 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_list.html:102
msgid "Sync success" msgid "Sync success"
msgstr "同步成功" msgstr "同步成功"
@ -6650,7 +6669,7 @@ msgstr "执行次数"
msgid "Instance count" msgid "Instance count"
msgstr "实例个数" msgstr "实例个数"
#: xpack/plugins/cloud/utils.py:37 #: xpack/plugins/cloud/utils.py:38
msgid "Account unavailable" msgid "Account unavailable"
msgstr "账户无效" msgstr "账户无效"
@ -6887,42 +6906,60 @@ msgid "Select auditor"
msgstr "选择审计员" msgstr "选择审计员"
#: xpack/plugins/orgs/forms.py:28 #: 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 #: xpack/plugins/orgs/templates/orgs/org_list.html:13
msgid "Admin" msgid "Admin"
msgstr "管理员" msgstr "管理员"
#: xpack/plugins/orgs/meta.py:8 xpack/plugins/orgs/views.py:26 #: xpack/plugins/orgs/meta.py:8 xpack/plugins/orgs/views.py:27
#: xpack/plugins/orgs/views.py:43 xpack/plugins/orgs/views.py:61 #: xpack/plugins/orgs/views.py:44 xpack/plugins/orgs/views.py:62
#: xpack/plugins/orgs/views.py:79 #: xpack/plugins/orgs/views.py:85 xpack/plugins/orgs/views.py:116
msgid "Organizations" msgid "Organizations"
msgstr "组织管理" msgstr "组织管理"
#: xpack/plugins/orgs/templates/orgs/org_detail.html:17 #: 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" msgid "Org detail"
msgstr "组织详情" 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" msgid "Add admin"
msgstr "添加管理员" msgstr "添加管理员"
#: xpack/plugins/orgs/templates/orgs/org_detail.html:117
msgid "Add auditor"
msgstr "添加审计员"
#: xpack/plugins/orgs/templates/orgs/org_list.html:5 #: xpack/plugins/orgs/templates/orgs/org_list.html:5
msgid "Create organization " msgid "Create organization "
msgstr "创建组织" 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" msgid "Org list"
msgstr "组织列表" msgstr "组织列表"
#: xpack/plugins/orgs/views.py:44 #: xpack/plugins/orgs/views.py:45
msgid "Create org" msgid "Create org"
msgstr "创建组织" msgstr "创建组织"
#: xpack/plugins/orgs/views.py:62 #: xpack/plugins/orgs/views.py:63
msgid "Update org" msgid "Update org"
msgstr "更新组织" 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/meta.py:11 xpack/plugins/vault/views.py:23
#: xpack/plugins/vault/views.py:38 #: xpack/plugins/vault/views.py:38
msgid "Vault" msgid "Vault"
@ -6944,11 +6981,8 @@ msgstr "密码匣子"
msgid "vault create" msgid "vault create"
msgstr "创建" msgstr "创建"
#~ msgid "Tips: The asset information is always covered" #~ msgid "Total hosts"
#~ msgstr "提示:资产信息总是被覆盖" #~ msgstr "主机总数"
#~ msgid "Covered always"
#~ msgstr "总是覆盖"
#~ msgid "* For security, do not change {}'s password" #~ msgid "* For security, do not change {}'s password"
#~ msgstr "* 为了安全,不能修改 {} 的密码" #~ msgstr "* 为了安全,不能修改 {} 的密码"

View File

@ -1,14 +1,16 @@
# -*- coding: utf-8 -*- # -*- 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.views import Response
from rest_framework_bulk import BulkModelViewSet from rest_framework_bulk import BulkModelViewSet
from common.permissions import IsSuperUserOrAppUser from common.permissions import IsSuperUserOrAppUser
from .models import Organization from .models import Organization
from .serializers import OrgSerializer, OrgReadSerializer, \ from .serializers import OrgSerializer, OrgReadSerializer, \
OrgMembershipUserSerializer, OrgMembershipAdminSerializer OrgMembershipUserSerializer, OrgMembershipAdminSerializer, \
OrgAllUserSerializer
from users.models import User, UserGroup from users.models import User, UserGroup
from assets.models import Asset, Domain, AdminUser, SystemUser, Label from assets.models import Asset, Domain, AdminUser, SystemUser, Label
from perms.models import AssetPermission from perms.models import AssetPermission
@ -67,3 +69,15 @@ class OrgMembershipUsersViewSet(OrgMembershipModelViewSetMixin, BulkModelViewSet
membership_class = Organization.users.through membership_class = Organization.users.through
permission_classes = (IsSuperUserOrAppUser, ) 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

View File

@ -80,3 +80,15 @@ class OrgMembershipUserSerializer(OrgMembershipSerializerMixin, ModelSerializer)
model = Organization.users.through model = Organization.users.through
list_serializer_class = AdaptedBulkListSerializer list_serializer_class = AdaptedBulkListSerializer
fields = '__all__' 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)

View File

@ -1,7 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# #
from django.urls import re_path from django.urls import re_path, path
from rest_framework.routers import DefaultRouter from rest_framework.routers import DefaultRouter
from common import api as capi from common import api as capi
@ -24,6 +24,7 @@ old_version_urlpatterns = [
] ]
urlpatterns = [ urlpatterns = [
path('<uuid:pk>/users/all/', api.OrgAllUserListApi.as_view(), name='org-all-users'),
] ]
urlpatterns += router.urls + old_version_urlpatterns urlpatterns += router.urls + old_version_urlpatterns

View File

@ -1,14 +1,7 @@
from __future__ import unicode_literals from __future__ import unicode_literals
from django.conf import settings
from django.apps import AppConfig from django.apps import AppConfig
class PermsConfig(AppConfig): class PermsConfig(AppConfig):
name = 'perms' name = 'perms'
def ready(self):
from . import signals_handler
if not settings.XPACK_ENABLED:
settings.ASSETS_PERM_CACHE_ENABLE = False
return super().ready()

View File

@ -301,7 +301,6 @@ class AssetPermissionUtil(AssetPermissionUtilCacheMixin):
continue continue
ancestors = self.full_tree.ancestors( ancestors = self.full_tree.ancestors(
child.identifier, with_self=False, deep=True, child.identifier, with_self=False, deep=True,
with_assets=False,
) )
if not ancestors: if not ancestors:
continue continue

View File

@ -11,7 +11,7 @@
<h5>{% trans 'Total users' %}</h5> <h5>{% trans 'Total users' %}</h5>
</div> </div>
<div class="ibox-content"> <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> <small>All users</small>
</div> </div>
</div> </div>
@ -19,12 +19,12 @@
<div class="col-sm-3"> <div class="col-sm-3">
<div class="ibox float-e-margins"> <div class="ibox float-e-margins">
<div class="ibox-title"> <div class="ibox-title">
<span class="label label-info pull-right">Hosts</span> <span class="label label-info pull-right">Assets</span>
<h5>{% trans 'Total hosts' %}</h5> <h5>{% trans 'Total assets' %}</h5>
</div> </div>
<div class="ibox-content"> <div class="ibox-content">
<h1 class="no-margins"><a href="{% url 'assets:asset-list' %}">{{ assets_count }}</a></h1> <h1 class="no-margins"><a href="{% url 'assets:asset-list' %}"><span id="total_count_assets"></span></a></h1>
<small>All hosts</small> <small>All assets</small>
</div> </div>
</div> </div>
</div> </div>
@ -36,7 +36,7 @@
<h5>{% trans 'Online users' %}</h5> <h5>{% trans 'Online users' %}</h5>
</div> </div>
<div class="ibox-content"> <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> <small>Online users</small>
</div> </div>
</div> </div>
@ -50,7 +50,7 @@
</div> </div>
<div class="ibox-content"> <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> <small>Online sessions</small>
</div> </div>
</div> </div>
@ -58,19 +58,11 @@
</div> </div>
<div class="row"> <div class="row">
<div class="col-sm-2 border-bottom white-bg dashboard-header" style="margin-left:15px;height: 346px"> <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> <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"> <ul class="list-group clear-list m-t" id="week_login_times_top5_users">
{% 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 %}
</ul> </ul>
</div> </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="col-sm-3 white-bg" id="top1" style="margin-left: -15px;height: 346px">
<div class="statistic-box"> <div class="statistic-box">
<h4> <h4>
@ -81,13 +73,13 @@
</p> </p>
<div class="row text-center"> <div class="row text-center">
<div class="col-sm-6"> <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> </div>
<h5>{% trans 'User' %}</h5> <h5>{% trans 'User' %}</h5>
</div> </div>
<div class="col-sm-6"> <div class="col-sm-6">
<div id="activeAsset" style="width: 140px; height: 140px;"></div> <div id="month_total_count_assets_pie" style="width: 140px; height: 140px;"></div>
<h5>{% trans 'Host' %}</h5> <h5>{% trans 'Asset' %}</h5>
</div> </div>
</div> </div>
<div class="m-t"> <div class="m-t">
@ -120,27 +112,7 @@
<h3><i class="fa fa-inbox"></i>{% trans 'Top 10 assets in a week'%}</h3> <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> <small><i class="fa fa-map-marker"></i>{% trans 'Login frequency and last login record.' %}</small>
</div> </div>
<div class="ibox-content inspinia-timeline"> <div class="ibox-content inspinia-timeline" id="week_login_times_top10_assets">
{% 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> </div>
</div> </div>
</div> </div>
@ -158,27 +130,7 @@
</div> </div>
<div class="ibox-content"> <div class="ibox-content">
<div> <div>
<div class="feed-activity-list"> <div class="feed-activity-list" id="week_login_record_top10_sessions">
{% 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> </div>
</div> </div>
</div> </div>
@ -206,27 +158,7 @@
<h3><i class="fa fa-user"></i>{% trans 'Top 10 users in a week' %}</h3> <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> <small><i class="fa fa-map-marker"></i>{% trans 'User login frequency and last login record.' %}</small>
</div> </div>
<div class="ibox-content inspinia-timeline"> <div class="ibox-content inspinia-timeline" id="week_login_times_top10_users">
{% 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> </div>
</div> </div>
</div> </div>
@ -238,27 +170,15 @@
{% block custom_foot_js %} {% block custom_foot_js %}
<script src="{% static 'js/plugins/echarts/echarts.js' %}"></script> <script src="{% static 'js/plugins/echarts/echarts.js' %}"></script>
<script> <script>
$(document).ready(function(){
$('#show').click(function(){ function requireMonthMetricsECharts(data){
$('#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'
}
});
require( require(
[ [
'echarts', 'echarts',
'echarts/chart/line' 'echarts/chart/line'
], ],
function (ec) { function (ec) {
var top10Chart = ec.init(document.getElementById('top10')); var monthMetricsECharts = ec.init(document.getElementById('month_metrics_echarts'));
var option = { var option = {
title : { title : {
text: "{% trans 'Monthly data overview' %}", text: "{% trans 'Monthly data overview' %}",
@ -284,7 +204,7 @@ $(document).ready(function(){
{ {
type : 'category', type : 'category',
boundaryGap : false, boundaryGap : false,
data : {{ month_str|safe}} data : data['month_metrics_date'],
} }
], ],
yAxis : [ yAxis : [
@ -298,38 +218,42 @@ $(document).ready(function(){
type:'line', type:'line',
smooth: true, smooth: true,
itemStyle: {normal: {areaStyle: {type: 'default'}}}, itemStyle: {normal: {areaStyle: {type: 'default'}}},
data: {{ month_total_visit_count|safe}} data: data['month_metrics_total_count_login']
}, },
{ {
name: "{% trans 'Active users' %}", name: "{% trans 'Active users' %}",
type: 'line', type: 'line',
smooth: true, smooth: true,
itemStyle: {normal: {areaStyle: {type: 'default'}}}, itemStyle: {normal: {areaStyle: {type: 'default'}}},
data: {{ month_user|safe }} data: data['month_metrics_total_count_active_users']
}, },
{ {
name:"{% trans 'Active assets' %}", name:"{% trans 'Active assets' %}",
type:'line', type:'line',
smooth:true, smooth:true,
itemStyle: {normal: {areaStyle: {type: 'default'}}}, 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( require(
[ [
'echarts', 'echarts',
'echarts/chart/pie' 'echarts/chart/pie'
], ],
function (ec) { function (ec) {
var auChart = ec.init(document.getElementById('activeUser')); var monthTotalCountUsersPie = ec.init(document.getElementById('month_total_count_users_pie'));
var option = { var option = {
tooltip : { tooltip : {
trigger: 'item', trigger: 'item',
formatter: "{b} <br> {c} ({d}%)" formatter: "{b} <br> {c} <br> ({d}%)"
}, },
legend: { legend: {
show: false, show: false,
@ -364,6 +288,7 @@ $(document).ready(function(){
name:"{% trans 'Access to the source' %}", name:"{% trans 'Access to the source' %}",
type:'pie', type:'pie',
radius : ['50%', '70%'], radius : ['50%', '70%'],
avoidLabelOverlap: false,
itemStyle : { itemStyle : {
normal : { normal : {
label : { label : {
@ -385,33 +310,36 @@ $(document).ready(function(){
} }
}, },
data:[ data:[
{value:{{ month_user_active }}, name:"{% trans 'Monthly active users' %}"}, {value:data['month_total_count_active_users'], name:"{% trans 'Monthly active users' %}"},
{value:{{ month_user_disabled }}, name:"{% trans 'Disable user' %}"}, {value:data['month_total_count_disabled_users'], name:"{% trans 'Disable user' %}"},
{value:{{ month_user_inactive }}, name:"{% trans 'Month not logged in 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( require(
[ [
'echarts', 'echarts',
'echarts/chart/pie' 'echarts/chart/pie'
], ],
function (ec) { function (ec) {
var aaChart = ec.init(document.getElementById('activeAsset')); var monthTotalCountAssetsPie = ec.init(document.getElementById('month_total_count_assets_pie'));
var option = { var option = {
tooltip : { tooltip : {
trigger: 'item', trigger: 'item',
formatter: "{b} <br> {c} ({d}%)" formatter: "{b} <br> {c} <br> ({d}%)"
}, },
legend: { legend: {
show: false, show: false,
orient : 'vertical', orient : 'vertical',
x : 'left', 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: { toolbox: {
show : false, show : false,
@ -461,16 +389,230 @@ $(document).ready(function(){
} }
}, },
data:[ data:[
{value:{{ month_asset_active }}, name:"{% trans 'Month is logged into the host' %}"}, {value:data['month_total_count_active_assets'], name:"{% trans 'Month is logged into the host' %}"},
{value:{{ month_asset_disabled }}, name:"{% trans 'Disable host' %}"}, {value:data['month_total_count_disabled_assets'], name:"{% trans 'Disable host' %}"},
{value:{{ month_asset_inactive }}, name:"{% trans 'Month not logged on 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> </script>
{% endblock %} {% endblock %}

View File

@ -1,9 +1,13 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# #
from .. import utils from .. import utils
from users.models import User
class UserQuerysetMixin: class UserQuerysetMixin:
def get_queryset(self): 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 return queryset