diff --git a/apps/authentication/api/mfa.py b/apps/authentication/api/mfa.py index cc4f2ab6b..f95593bbe 100644 --- a/apps/authentication/api/mfa.py +++ b/apps/authentication/api/mfa.py @@ -1,6 +1,7 @@ # -*- coding: utf-8 -*- # import time +from django.utils.translation import ugettext as _ from rest_framework.permissions import AllowAny from rest_framework.generics import CreateAPIView from rest_framework.serializers import ValidationError @@ -56,4 +57,4 @@ class UserOtpVerifyApi(CreateAPIView): request.session["MFA_VERIFY_TIME"] = int(time.time()) return Response({"ok": "1"}) else: - return Response({"error": "Code not valid"}, status=400) + return Response({"error": _("Code is invalid")}, status=400) diff --git a/apps/locale/zh/LC_MESSAGES/django.mo b/apps/locale/zh/LC_MESSAGES/django.mo index 02bf6ef03..1fa128c6a 100644 Binary files a/apps/locale/zh/LC_MESSAGES/django.mo and b/apps/locale/zh/LC_MESSAGES/django.mo differ diff --git a/apps/locale/zh/LC_MESSAGES/django.po b/apps/locale/zh/LC_MESSAGES/django.po index e68fdec58..d2612f98a 100644 --- a/apps/locale/zh/LC_MESSAGES/django.po +++ b/apps/locale/zh/LC_MESSAGES/django.po @@ -986,7 +986,7 @@ msgstr "状态" msgid "Date login" msgstr "登录日期" -#: audits/serializers.py:61 audits/serializers.py:73 ops/models/adhoc.py:240 +#: audits/serializers.py:61 audits/serializers.py:73 ops/models/adhoc.py:244 msgid "Is success" msgstr "是否成功" @@ -1003,6 +1003,10 @@ msgstr "主机" msgid "Run as" msgstr "运行用户" +#: authentication/api/mfa.py:60 +msgid "Code is invalid" +msgstr "Code无效" + #: authentication/backends/api.py:53 msgid "Invalid signature header. No credentials provided." msgstr "" @@ -1500,46 +1504,46 @@ msgstr "Become" msgid "Create by" msgstr "创建者" -#: ops/models/adhoc.py:233 +#: ops/models/adhoc.py:237 msgid "Task display" msgstr "任务展示" -#: ops/models/adhoc.py:234 +#: ops/models/adhoc.py:238 msgid "Host amount" msgstr "主机数量" -#: ops/models/adhoc.py:236 +#: ops/models/adhoc.py:240 msgid "Start time" msgstr "开始时间" -#: ops/models/adhoc.py:237 +#: ops/models/adhoc.py:241 msgid "End time" msgstr "完成时间" -#: ops/models/adhoc.py:238 xpack/plugins/change_auth_plan/models.py:179 +#: ops/models/adhoc.py:242 xpack/plugins/change_auth_plan/models.py:179 #: xpack/plugins/change_auth_plan/models.py:310 #: xpack/plugins/gathered_user/models.py:79 msgid "Time" msgstr "时间" -#: ops/models/adhoc.py:239 ops/models/command.py:26 +#: ops/models/adhoc.py:243 ops/models/command.py:26 #: terminal/serializers/session.py:30 msgid "Is finished" msgstr "是否完成" -#: ops/models/adhoc.py:241 +#: ops/models/adhoc.py:245 msgid "Adhoc raw result" msgstr "结果" -#: ops/models/adhoc.py:242 +#: ops/models/adhoc.py:246 msgid "Adhoc result summary" msgstr "汇总" -#: ops/models/adhoc.py:282 xpack/plugins/change_auth_plan/utils.py:137 +#: ops/models/adhoc.py:286 xpack/plugins/change_auth_plan/utils.py:137 msgid "{} Start task: {}" msgstr "{} 任务开始: {}" -#: ops/models/adhoc.py:291 xpack/plugins/change_auth_plan/utils.py:149 +#: ops/models/adhoc.py:295 xpack/plugins/change_auth_plan/utils.py:149 msgid "{} Task finish" msgstr "{} 任务结束" diff --git a/apps/ops/api/adhoc.py b/apps/ops/api/adhoc.py index ee81f869f..aef4c9b06 100644 --- a/apps/ops/api/adhoc.py +++ b/apps/ops/api/adhoc.py @@ -4,14 +4,17 @@ from django.shortcuts import get_object_or_404 from rest_framework import viewsets, generics from rest_framework.views import Response -from django.db.models import Count, Q from common.permissions import IsOrgAdmin from common.serializers import CeleryTaskSerializer -from orgs.utils import current_org from ..models import Task, AdHoc, AdHocExecution -from ..serializers import TaskSerializer, AdHocSerializer, \ - AdHocExecutionSerializer, TaskDetailSerializer +from ..serializers import ( + TaskSerializer, + AdHocSerializer, + AdHocExecutionSerializer, + TaskDetailSerializer, + AdHocDetailSerializer, +) from ..tasks import run_ansible_task __all__ = [ @@ -53,6 +56,11 @@ class AdHocViewSet(viewsets.ModelViewSet): serializer_class = AdHocSerializer permission_classes = (IsOrgAdmin,) + def get_serializer_class(self): + if self.action == 'retrieve': + return AdHocDetailSerializer + return super().get_serializer_class() + def get_queryset(self): task_id = self.request.query_params.get('task') if task_id: diff --git a/apps/ops/models/adhoc.py b/apps/ops/models/adhoc.py index 013fdc628..36ebd77e0 100644 --- a/apps/ops/models/adhoc.py +++ b/apps/ops/models/adhoc.py @@ -150,6 +150,10 @@ class AdHoc(OrgModelMixin): created_by = models.CharField(max_length=64, default='', blank=True, null=True, verbose_name=_('Create by')) date_created = models.DateTimeField(auto_now_add=True, db_index=True) + @lazyproperty + def run_times(self): + return self.execution.count() + @property def inventory(self): if self.become: diff --git a/apps/ops/serializers/adhoc.py b/apps/ops/serializers/adhoc.py index d4e67371a..f07c1ca47 100644 --- a/apps/ops/serializers/adhoc.py +++ b/apps/ops/serializers/adhoc.py @@ -8,10 +8,16 @@ from ..models import Task, AdHoc, AdHocExecution, CommandExecution class AdHocExecutionSerializer(serializers.ModelSerializer): stat = serializers.SerializerMethodField() + last_success = serializers.ListField(source='success_hosts') + last_failure = serializers.DictField(source='failed_hosts') class Meta: model = AdHocExecution - fields = '__all__' + fields = [ + 'id', 'task', 'task_display', 'hosts_amount', 'adhoc', 'date_start', 'stat', + 'date_finished', 'timedelta', 'is_finished', 'is_success', 'result', 'summary', + 'short_id', 'adhoc_short_id', 'last_success', 'last_failure' + ] @staticmethod def get_task(obj): @@ -28,17 +34,15 @@ class AdHocExecutionSerializer(serializers.ModelSerializer): "failed": count_failed_hosts } - def get_field_names(self, declared_fields, info): - fields = super().get_field_names(declared_fields, info) - fields.extend(['short_id', 'adhoc_short_id']) - return fields - class AdHocExecutionExcludeResultSerializer(AdHocExecutionSerializer): - def get_field_names(self, declared_fields, info): - fields = super().get_field_names(declared_fields, info) - fields = [i for i in fields if i not in ['result', 'summary']] - return fields + class Meta: + model = AdHocExecution + fields = [ + 'id', 'task', 'task_display', 'hosts_amount', 'adhoc', 'date_start', 'stat', + 'date_finished', 'timedelta', 'is_finished', 'is_success', + 'short_id', 'adhoc_short_id', 'last_success', 'last_failure' + ] class TaskSerializer(serializers.ModelSerializer): @@ -60,15 +64,15 @@ class TaskSerializer(serializers.ModelSerializer): class TaskDetailSerializer(TaskSerializer): - last_success = serializers.ListField(source='latest_execution.success_hosts') - last_failure = serializers.DictField(source='latest_execution.failed_hosts') + contents = serializers.ListField(source='latest_adhoc.tasks') class Meta(TaskSerializer.Meta): - fields = TaskSerializer.Meta.fields + ['last_success', 'last_failure'] + fields = TaskSerializer.Meta.fields + ['contents'] class AdHocSerializer(serializers.ModelSerializer): become_display = serializers.ReadOnlyField() + tasks = serializers.ListField() class Meta: model = AdHoc @@ -86,6 +90,29 @@ class AdHocSerializer(serializers.ModelSerializer): } +class AdHocExecutionNestSerializer(serializers.ModelSerializer): + last_success = serializers.ListField(source='success_hosts') + last_failure = serializers.DictField(source='failed_hosts') + last_run = serializers.CharField(source='short_id') + + class Meta: + model = AdHocExecution + fields = ( + 'last_success', 'last_failure', 'last_run', 'timedelta', 'is_finished', + 'is_success' + ) + + +class AdHocDetailSerializer(AdHocSerializer): + latest_execution = AdHocExecutionNestSerializer(allow_null=True) + task_name = serializers.CharField(source='task.name') + + class Meta(AdHocSerializer.Meta): + fields = AdHocSerializer.Meta.fields + [ + 'latest_execution', 'created_by', 'run_times', 'task_name' + ] + + class CommandExecutionSerializer(serializers.ModelSerializer): result = serializers.JSONField(read_only=True) log_url = serializers.SerializerMethodField() diff --git a/apps/tickets/serializers/ticket.py b/apps/tickets/serializers/ticket.py index 0f564ad70..f6c995ae0 100644 --- a/apps/tickets/serializers/ticket.py +++ b/apps/tickets/serializers/ticket.py @@ -23,7 +23,8 @@ class TicketSerializer(serializers.ModelSerializer): ] extra_kwargs = { 'status': {'label': _('Status')}, - 'action': {'label': _('Action')} + 'action': {'label': _('Action')}, + 'user_display': {'label': _('User')} } def create(self, validated_data):