Compare commits
2 Commits
6fe2daf4a3
...
510b988a38
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
510b988a38 | ||
|
|
fd4af8e103 |
245
src/elexam_core/errors.py
Normal file
245
src/elexam_core/errors.py
Normal file
@ -0,0 +1,245 @@
|
||||
from enum import Enum
|
||||
|
||||
|
||||
class ErrorCode(str, Enum):
|
||||
|
||||
# --- common ---
|
||||
# Универсальные коды для случаев, когда доменный код избыточен
|
||||
COMMON_INTERNAL_ERROR = "common.internal_error" # Непредвиденная ошибка на сервере — используй, когда нет подходящего доменного кода
|
||||
COMMON_SERVICE_UNAVAILABLE = "common.service_unavailable" # Зависимый сервис (RabbitMQ, Redis, БД) временно недоступен
|
||||
COMMON_VALIDATION_FAILED = "common.validation_failed" # Тело запроса не прошло схемную валидацию Pydantic
|
||||
COMMON_NOT_FOUND = "common.not_found" # Запрошенный ресурс не найден — резервный код, если нет доменного аналога
|
||||
COMMON_FORBIDDEN = "common.forbidden" # Прав доступа недостаточно для выполнения операции
|
||||
COMMON_UNAUTHORIZED = "common.unauthorized" # Запрос без токена или с нераспознанным токеном
|
||||
COMMON_RATE_LIMITED = "common.rate_limited" # Клиент превысил допустимое число запросов в единицу времени
|
||||
COMMON_CONFLICT = "common.conflict" # Конфликт состояния: операция несовместима с текущим состоянием ресурса
|
||||
COMMON_METHOD_NOT_ALLOWED = "common.method_not_allowed" # HTTP-метод не поддерживается для данного эндпоинта
|
||||
COMMON_PAYLOAD_TOO_LARGE = "common.payload_too_large" # Тело запроса превышает допустимый размер
|
||||
|
||||
# --- auth ---
|
||||
AUTH_TOKEN_EXPIRED = "auth.token.expired" # JWT access-токен просрочен (exp пройден) — клиент должен обновить через refresh
|
||||
AUTH_TOKEN_INVALID = "auth.token.invalid" # Подпись токена невалидна или структура JWT нарушена
|
||||
AUTH_TOKEN_REVOKED = "auth.token.revoked" # Токен явно отозван (logout или смена пароля)
|
||||
AUTH_CREDENTIALS_INVALID = "auth.credentials.invalid" # Неверный логин или пароль при аутентификации
|
||||
AUTH_ACCOUNT_LOCKED = "auth.account.locked" # Аккаунт заблокирован администратором вручную
|
||||
AUTH_ACCOUNT_DEPRECATED = "auth.account.deprecated" # Аккаунт деактивирован (soft-delete) — вход запрещён
|
||||
AUTH_DEVICE_UNTRUSTED = "auth.device.untrusted" # Устройство не добавлено в список доверенных (MFA-сценарий)
|
||||
AUTH_DEVICE_NOT_FOUND = "auth.device.not_found" # Указанный device_id не зарегистрирован в системе
|
||||
AUTH_REFRESH_EXPIRED = "auth.refresh.expired" # Refresh-токен просрочен — требуется повторный вход
|
||||
AUTH_REFRESH_REVOKED = "auth.refresh.revoked" # Refresh-токен отозван (ротация или принудительный logout)
|
||||
AUTH_ORG_SUSPENDED = "auth.org.suspended" # Применяется, когда организация заморожена gateway'ем по событию billing
|
||||
AUTH_BRUTE_FORCE = "auth.brute_force" # Порог брутфорса достигнут — фиксируется журналом + rate-limit-ом
|
||||
|
||||
# --- user ---
|
||||
USER_NOT_FOUND = "user.not_found" # Пользователь с данным ID не существует
|
||||
USER_EMAIL_TAKEN = "user.email.taken" # Email уже зарегистрирован в системе — дубликат
|
||||
USER_DEPRECATED = "user.deprecated" # Аккаунт пользователя деактивирован (soft-delete)
|
||||
USER_ORG_NOT_FOUND = "user.org.not_found" # Организация, к которой привязан пользователь, не найдена
|
||||
USER_ORG_DEPRECATED = "user.org.deprecated" # Организация деактивирована — операции для её участников заблокированы
|
||||
USER_BRANCH_NOT_FOUND = "user.branch.not_found" # Указанное подразделение (филиал) организации не найдено
|
||||
USER_MEMBERSHIP_EXISTS = "user.membership.exists" # Пользователь уже состоит в данной организации или роли
|
||||
USER_MEMBERSHIP_NOT_FOUND = "user.membership.not_found" # Запись членства пользователя в организации не найдена
|
||||
USER_ROLE_NOT_FOUND = "user.role.not_found" # Указанная роль не существует в системе
|
||||
USER_PERMISSION_NOT_FOUND = "user.permission.not_found" # Указанное право доступа не зарегистрировано в системе
|
||||
|
||||
# --- exam ---
|
||||
EXAM_NOT_FOUND = "exam.not_found" # Экзамен с данным ID не найден
|
||||
EXAM_ALREADY_PUBLISHED = "exam.already_published" # Экзамен уже опубликован — повторная публикация невозможна
|
||||
EXAM_CLOSED = "exam.closed" # Экзамен закрыт для новых попыток (дедлайн прошёл или ручное закрытие)
|
||||
EXAM_DRAFT_EMPTY = "exam.draft.empty" # Нельзя опубликовать черновик без единого вопроса
|
||||
EXAM_VERSION_NOT_FOUND = "exam.version.not_found" # Запрошенная immutable-версия (снимок) экзамена не найдена
|
||||
EXAM_QUESTION_NOT_FOUND = "exam.question.not_found" # Вопрос с данным ID не входит в состав экзамена
|
||||
EXAM_QUESTION_DUPLICATE = "exam.question.duplicate" # Вопрос уже добавлен в экзамен — дублирование запрещено
|
||||
EXAM_ATTEMPT_NOT_FOUND = "exam.attempt.not_found" # Попытка с данным ID не найдена или не принадлежит студенту
|
||||
EXAM_ATTEMPT_ALREADY_STARTED = "exam.attempt.already_started" # Попытка уже запущена — двойной старт невозможен
|
||||
EXAM_ATTEMPT_MAX_EXCEEDED = "exam.attempt.max_exceeded" # Студент исчерпал максимум попыток (exam.settings.attempts.max)
|
||||
EXAM_ATTEMPT_TIMED_OUT = "exam.attempt.timed_out" # Серверный дедлайн истёк до сабмита
|
||||
EXAM_ATTEMPT_VOIDED = "exam.attempt.voided" # Попытка аннулирована по вердикту прокторинга
|
||||
EXAM_ATTEMPT_SUBMITTED = "exam.attempt.submitted" # Попытка уже закрыта (submitted) — нельзя добавлять ответы
|
||||
EXAM_ATTEMPT_CONSENT_REQUIRED = "exam.attempt.consent_required" # Старт заблокирован: нет факта согласия (proctoring.consent_given)
|
||||
EXAM_ATTEMPT_COOLDOWN_ACTIVE = "exam.attempt.cooldown_active" # Повторная попытка раньше cooldown_seconds
|
||||
|
||||
# --- proctoring ---
|
||||
PROCTORING_CONSENT_ALREADY_GIVEN = "proctoring.consent.already_given" # Студент уже подписал согласие для данной попытки
|
||||
PROCTORING_CONSENT_NOT_FOUND = "proctoring.consent.not_found" # Запись согласия не найдена — студент ещё не давал согласие
|
||||
PROCTORING_SESSION_NOT_FOUND = "proctoring.session.not_found" # Сессия прокторинга с данным ID не найдена
|
||||
PROCTORING_SESSION_ALREADY_ACTIVE = "proctoring.session.already_active" # Для данной попытки уже открыта активная сессия прокторинга
|
||||
PROCTORING_SESSION_CLOSED = "proctoring.session.closed" # Сессия уже закрыта (closed) — новые сигналы не принимаются
|
||||
PROCTORING_SIGNAL_REJECTED = "proctoring.signal.rejected" # Сигнал не прошёл валидацию схемы (неизвестный type, невалидный payload)
|
||||
PROCTORING_INCIDENT_NOT_FOUND = "proctoring.incident.not_found" # Инцидент с данным ID не найден в сессии
|
||||
PROCTORING_VERDICT_ALREADY_ISSUED = "proctoring.verdict.already_issued" # Вердикт по этой сессии уже вынесен (один вердикт на сессию — аудит)
|
||||
PROCTORING_VERDICT_NOT_FOUND = "proctoring.verdict.not_found" # Вердикт для данной сессии ещё не вынесен
|
||||
PROCTORING_IDENTITY_SHOT_MISSING = "proctoring.identity_shot.missing" # Снимок для ручной идентификации не загружен при открытии сессии
|
||||
PROCTORING_CHANNEL_NOT_CONSENTED = "proctoring.channel.not_consented" # Клиент пытается слать данные по каналу (напр. mic), на который не давал согласия
|
||||
|
||||
# --- result ---
|
||||
RESULT_NOT_FOUND = "result.not_found" # Результат попытки с данным ID не найден
|
||||
RESULT_VOIDED = "result.voided" # Результат аннулирован — изменения невозможны
|
||||
RESULT_ALREADY_FINALIZED = "result.already_finalized" # Итог уже финализирован — повторная финализация запрещена
|
||||
RESULT_PENDING_GRADING = "result.pending_grading" # Финализация невозможна: остались непроверенные grading-записи
|
||||
RESULT_GRADING_NOT_FOUND = "result.grading.not_found" # Запись оценки для данного вопроса не найдена
|
||||
RESULT_GRADING_ALREADY_DONE = "result.grading.already_done" # Вопрос уже оценён — повторная оценка без апелляции запрещена
|
||||
RESULT_APPEAL_NOT_ALLOWED = "result.appeal.not_allowed" # Апелляции отключены в настройках экзамена (appeals.enabled = false)
|
||||
RESULT_APPEAL_NOT_FOUND = "result.appeal.not_found" # Апелляция для данного результата не найдена
|
||||
RESULT_APPEAL_ALREADY_OPEN = "result.appeal.already_open" # По этому результату уже открыта апелляция (одна активная)
|
||||
RESULT_APPEAL_CLOSED = "result.appeal.closed" # Апелляция уже закрыта (accepted/rejected)
|
||||
|
||||
# --- notification ---
|
||||
NOTIFICATION_NOT_FOUND = "notification.not_found" # Уведомление с данным ID не найдено
|
||||
NOTIFICATION_TEMPLATE_NOT_FOUND = "notification.template.not_found" # Шаблон уведомления (по типу события) не зарегистрирован
|
||||
NOTIFICATION_CHANNEL_DISABLED = "notification.channel.disabled" # Канал (email/telegram) отключён настройками пользователя
|
||||
NOTIFICATION_DELIVERY_FAILED = "notification.delivery.failed" # Внешний провайдер (SMTP / Telegram API) вернул ошибку
|
||||
NOTIFICATION_DUPLICATE = "notification.duplicate" # Уведомление по этому event_id уже существует (идемпотентный дедуп)
|
||||
NOTIFICATION_PREF_NOT_FOUND = "notification.pref.not_found" # Настройки уведомлений пользователя не найдены (ещё не сохранялись)
|
||||
|
||||
# --- billing ---
|
||||
BILLING_PLAN_NOT_FOUND = "billing.plan.not_found" # Тарифный план с данным ID не существует
|
||||
BILLING_SUBSCRIPTION_NOT_FOUND = "billing.subscription.not_found" # Активная подписка для организации не найдена
|
||||
BILLING_SUBSCRIPTION_ALREADY_EXISTS = "billing.subscription.already_exists" # Организация уже имеет подписку — создание дубликата запрещено
|
||||
BILLING_SUBSCRIPTION_EXPIRED = "billing.subscription.expired" # Подписка истекла и не продлена (период закончился)
|
||||
BILLING_SUBSCRIPTION_SUSPENDED = "billing.subscription.suspended" # Организация заморожена (suspended) — операции недоступны
|
||||
BILLING_LIMIT_EXCEEDED = "billing.limit.exceeded" # Лимит тарифа исчерпан (напр. max_concurrent_attempts)
|
||||
BILLING_INVOICE_NOT_FOUND = "billing.invoice.not_found" # Счёт на оплату с данным ID не найден
|
||||
BILLING_PAYMENT_FAILED = "billing.payment.failed" # Платёжный провайдер отклонил транзакцию
|
||||
|
||||
# --- bot ---
|
||||
BOT_LINK_NOT_FOUND = "bot.link.not_found" # Привязка Telegram-аккаунта к пользователю не найдена
|
||||
BOT_LINK_ALREADY_EXISTS = "bot.link.already_exists" # Пользователь уже привязан к Telegram-чату
|
||||
BOT_LINK_CODE_NOT_FOUND = "bot.link_code.not_found" # Одноразовый код привязки не найден или был удалён
|
||||
BOT_LINK_CODE_EXPIRED = "bot.link_code.expired" # Одноразовый код привязки истёк (expires_at пройден)
|
||||
BOT_LINK_CODE_USED = "bot.link_code.used" # Код уже был активирован — повторное использование невозможно
|
||||
BOT_DELIVERY_FAILED = "bot.delivery.failed" # Telegram Bot API вернул ошибку при отправке
|
||||
|
||||
# --- storage ---
|
||||
STORAGE_FILE_NOT_FOUND = "storage.file.not_found" # Файл с данным ID не найден в хранилище
|
||||
STORAGE_UPLOAD_TOO_LARGE = "storage.upload.too_large" # Размер загружаемого файла превышает допустимый лимит
|
||||
STORAGE_TYPE_NOT_ALLOWED = "storage.type.not_allowed" # MIME-тип загружаемого файла не входит в список разрешённых
|
||||
STORAGE_QUOTA_EXCEEDED = "storage.quota.exceeded" # Квота хранилища организации исчерпана (billing.limits.storage_gb)
|
||||
STORAGE_UPLOAD_FAILED = "storage.upload.failed" # Хранилище недоступно или вернуло ошибку при записи
|
||||
|
||||
# --- journal ---
|
||||
JOURNAL_AUDIT_NOT_FOUND = "journal.audit.not_found" # Запись аудит-лога с данным ID не найдена
|
||||
JOURNAL_STATS_NOT_FOUND = "journal.stats.not_found" # Статистика по запрошенным параметрам ещё не сформирована
|
||||
JOURNAL_EXPORT_TOO_LARGE = "journal.export.too_large" # Запрошенный экспорт слишком велик для синхронной выдачи
|
||||
|
||||
|
||||
ERROR_META: dict[ErrorCode, dict] = {
|
||||
|
||||
# --- common ---
|
||||
ErrorCode.COMMON_INTERNAL_ERROR: {"http": 500, "severity": "error"},
|
||||
ErrorCode.COMMON_SERVICE_UNAVAILABLE: {"http": 503, "severity": "error"},
|
||||
ErrorCode.COMMON_VALIDATION_FAILED: {"http": 422, "severity": "warning"},
|
||||
ErrorCode.COMMON_NOT_FOUND: {"http": 404, "severity": "warning"},
|
||||
ErrorCode.COMMON_FORBIDDEN: {"http": 403, "severity": "warning"},
|
||||
ErrorCode.COMMON_UNAUTHORIZED: {"http": 401, "severity": "warning"},
|
||||
ErrorCode.COMMON_RATE_LIMITED: {"http": 429, "severity": "warning"},
|
||||
ErrorCode.COMMON_CONFLICT: {"http": 409, "severity": "warning"},
|
||||
ErrorCode.COMMON_METHOD_NOT_ALLOWED: {"http": 405, "severity": "warning"},
|
||||
ErrorCode.COMMON_PAYLOAD_TOO_LARGE: {"http": 413, "severity": "warning"},
|
||||
|
||||
# --- auth ---
|
||||
ErrorCode.AUTH_TOKEN_EXPIRED: {"http": 401, "severity": "info"},
|
||||
ErrorCode.AUTH_TOKEN_INVALID: {"http": 401, "severity": "warning"},
|
||||
ErrorCode.AUTH_TOKEN_REVOKED: {"http": 401, "severity": "info"},
|
||||
ErrorCode.AUTH_CREDENTIALS_INVALID: {"http": 401, "severity": "warning"},
|
||||
ErrorCode.AUTH_ACCOUNT_LOCKED: {"http": 403, "severity": "warning"},
|
||||
ErrorCode.AUTH_ACCOUNT_DEPRECATED: {"http": 403, "severity": "info"},
|
||||
ErrorCode.AUTH_DEVICE_UNTRUSTED: {"http": 403, "severity": "info"},
|
||||
ErrorCode.AUTH_DEVICE_NOT_FOUND: {"http": 404, "severity": "info"},
|
||||
ErrorCode.AUTH_REFRESH_EXPIRED: {"http": 401, "severity": "info"},
|
||||
ErrorCode.AUTH_REFRESH_REVOKED: {"http": 401, "severity": "info"},
|
||||
ErrorCode.AUTH_ORG_SUSPENDED: {"http": 403, "severity": "warning"},
|
||||
ErrorCode.AUTH_BRUTE_FORCE: {"http": 429, "severity": "error"},
|
||||
|
||||
# --- user ---
|
||||
ErrorCode.USER_NOT_FOUND: {"http": 404, "severity": "warning"},
|
||||
ErrorCode.USER_EMAIL_TAKEN: {"http": 409, "severity": "info"},
|
||||
ErrorCode.USER_DEPRECATED: {"http": 403, "severity": "info"},
|
||||
ErrorCode.USER_ORG_NOT_FOUND: {"http": 404, "severity": "warning"},
|
||||
ErrorCode.USER_ORG_DEPRECATED: {"http": 403, "severity": "warning"},
|
||||
ErrorCode.USER_BRANCH_NOT_FOUND: {"http": 404, "severity": "warning"},
|
||||
ErrorCode.USER_MEMBERSHIP_EXISTS: {"http": 409, "severity": "info"},
|
||||
ErrorCode.USER_MEMBERSHIP_NOT_FOUND: {"http": 404, "severity": "warning"},
|
||||
ErrorCode.USER_ROLE_NOT_FOUND: {"http": 404, "severity": "warning"},
|
||||
ErrorCode.USER_PERMISSION_NOT_FOUND: {"http": 404, "severity": "warning"},
|
||||
|
||||
# --- exam ---
|
||||
ErrorCode.EXAM_NOT_FOUND: {"http": 404, "severity": "warning"},
|
||||
ErrorCode.EXAM_ALREADY_PUBLISHED: {"http": 409, "severity": "info"},
|
||||
ErrorCode.EXAM_CLOSED: {"http": 409, "severity": "warning"},
|
||||
ErrorCode.EXAM_DRAFT_EMPTY: {"http": 422, "severity": "warning"},
|
||||
ErrorCode.EXAM_VERSION_NOT_FOUND: {"http": 404, "severity": "warning"},
|
||||
ErrorCode.EXAM_QUESTION_NOT_FOUND: {"http": 404, "severity": "warning"},
|
||||
ErrorCode.EXAM_QUESTION_DUPLICATE: {"http": 409, "severity": "info"},
|
||||
ErrorCode.EXAM_ATTEMPT_NOT_FOUND: {"http": 404, "severity": "warning"},
|
||||
ErrorCode.EXAM_ATTEMPT_ALREADY_STARTED: {"http": 409, "severity": "info"},
|
||||
ErrorCode.EXAM_ATTEMPT_MAX_EXCEEDED: {"http": 409, "severity": "warning"},
|
||||
ErrorCode.EXAM_ATTEMPT_TIMED_OUT: {"http": 409, "severity": "warning"},
|
||||
ErrorCode.EXAM_ATTEMPT_VOIDED: {"http": 409, "severity": "warning"},
|
||||
ErrorCode.EXAM_ATTEMPT_SUBMITTED: {"http": 409, "severity": "info"},
|
||||
ErrorCode.EXAM_ATTEMPT_CONSENT_REQUIRED: {"http": 403, "severity": "warning"},
|
||||
ErrorCode.EXAM_ATTEMPT_COOLDOWN_ACTIVE: {"http": 429, "severity": "info"},
|
||||
|
||||
# --- proctoring ---
|
||||
ErrorCode.PROCTORING_CONSENT_ALREADY_GIVEN: {"http": 409, "severity": "info"},
|
||||
ErrorCode.PROCTORING_CONSENT_NOT_FOUND: {"http": 404, "severity": "warning"},
|
||||
ErrorCode.PROCTORING_SESSION_NOT_FOUND: {"http": 404, "severity": "warning"},
|
||||
ErrorCode.PROCTORING_SESSION_ALREADY_ACTIVE: {"http": 409, "severity": "info"},
|
||||
ErrorCode.PROCTORING_SESSION_CLOSED: {"http": 409, "severity": "warning"},
|
||||
ErrorCode.PROCTORING_SIGNAL_REJECTED: {"http": 422, "severity": "info"},
|
||||
ErrorCode.PROCTORING_INCIDENT_NOT_FOUND: {"http": 404, "severity": "warning"},
|
||||
ErrorCode.PROCTORING_VERDICT_ALREADY_ISSUED: {"http": 409, "severity": "info"},
|
||||
ErrorCode.PROCTORING_VERDICT_NOT_FOUND: {"http": 404, "severity": "warning"},
|
||||
ErrorCode.PROCTORING_IDENTITY_SHOT_MISSING: {"http": 422, "severity": "warning"},
|
||||
ErrorCode.PROCTORING_CHANNEL_NOT_CONSENTED: {"http": 403, "severity": "info"},
|
||||
|
||||
# --- result ---
|
||||
ErrorCode.RESULT_NOT_FOUND: {"http": 404, "severity": "warning"},
|
||||
ErrorCode.RESULT_VOIDED: {"http": 409, "severity": "warning"},
|
||||
ErrorCode.RESULT_ALREADY_FINALIZED: {"http": 409, "severity": "info"},
|
||||
ErrorCode.RESULT_PENDING_GRADING: {"http": 409, "severity": "info"},
|
||||
ErrorCode.RESULT_GRADING_NOT_FOUND: {"http": 404, "severity": "warning"},
|
||||
ErrorCode.RESULT_GRADING_ALREADY_DONE: {"http": 409, "severity": "info"},
|
||||
ErrorCode.RESULT_APPEAL_NOT_ALLOWED: {"http": 403, "severity": "info"},
|
||||
ErrorCode.RESULT_APPEAL_NOT_FOUND: {"http": 404, "severity": "warning"},
|
||||
ErrorCode.RESULT_APPEAL_ALREADY_OPEN: {"http": 409, "severity": "info"},
|
||||
ErrorCode.RESULT_APPEAL_CLOSED: {"http": 409, "severity": "info"},
|
||||
|
||||
# --- notification ---
|
||||
ErrorCode.NOTIFICATION_NOT_FOUND: {"http": 404, "severity": "warning"},
|
||||
ErrorCode.NOTIFICATION_TEMPLATE_NOT_FOUND: {"http": 404, "severity": "warning"},
|
||||
ErrorCode.NOTIFICATION_CHANNEL_DISABLED: {"http": 422, "severity": "info"},
|
||||
ErrorCode.NOTIFICATION_DELIVERY_FAILED: {"http": 502, "severity": "error"},
|
||||
ErrorCode.NOTIFICATION_DUPLICATE: {"http": 409, "severity": "info"},
|
||||
ErrorCode.NOTIFICATION_PREF_NOT_FOUND: {"http": 404, "severity": "info"},
|
||||
|
||||
# --- billing ---
|
||||
ErrorCode.BILLING_PLAN_NOT_FOUND: {"http": 404, "severity": "warning"},
|
||||
ErrorCode.BILLING_SUBSCRIPTION_NOT_FOUND: {"http": 404, "severity": "warning"},
|
||||
ErrorCode.BILLING_SUBSCRIPTION_ALREADY_EXISTS: {"http": 409, "severity": "info"},
|
||||
ErrorCode.BILLING_SUBSCRIPTION_EXPIRED: {"http": 403, "severity": "warning"},
|
||||
ErrorCode.BILLING_SUBSCRIPTION_SUSPENDED: {"http": 403, "severity": "warning"},
|
||||
ErrorCode.BILLING_LIMIT_EXCEEDED: {"http": 429, "severity": "warning"},
|
||||
ErrorCode.BILLING_INVOICE_NOT_FOUND: {"http": 404, "severity": "warning"},
|
||||
ErrorCode.BILLING_PAYMENT_FAILED: {"http": 402, "severity": "error"},
|
||||
|
||||
# --- bot ---
|
||||
ErrorCode.BOT_LINK_NOT_FOUND: {"http": 404, "severity": "warning"},
|
||||
ErrorCode.BOT_LINK_ALREADY_EXISTS: {"http": 409, "severity": "info"},
|
||||
ErrorCode.BOT_LINK_CODE_NOT_FOUND: {"http": 404, "severity": "warning"},
|
||||
ErrorCode.BOT_LINK_CODE_EXPIRED: {"http": 410, "severity": "info"},
|
||||
ErrorCode.BOT_LINK_CODE_USED: {"http": 409, "severity": "info"},
|
||||
ErrorCode.BOT_DELIVERY_FAILED: {"http": 502, "severity": "error"},
|
||||
|
||||
# --- storage ---
|
||||
ErrorCode.STORAGE_FILE_NOT_FOUND: {"http": 404, "severity": "warning"},
|
||||
ErrorCode.STORAGE_UPLOAD_TOO_LARGE: {"http": 413, "severity": "warning"},
|
||||
ErrorCode.STORAGE_TYPE_NOT_ALLOWED: {"http": 422, "severity": "warning"},
|
||||
ErrorCode.STORAGE_QUOTA_EXCEEDED: {"http": 429, "severity": "warning"},
|
||||
ErrorCode.STORAGE_UPLOAD_FAILED: {"http": 502, "severity": "error"},
|
||||
|
||||
# --- journal ---
|
||||
ErrorCode.JOURNAL_AUDIT_NOT_FOUND: {"http": 404, "severity": "info"},
|
||||
ErrorCode.JOURNAL_STATS_NOT_FOUND: {"http": 404, "severity": "info"},
|
||||
ErrorCode.JOURNAL_EXPORT_TOO_LARGE: {"http": 413, "severity": "warning"},
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user