646 lines
22 KiB
Python
646 lines
22 KiB
Python
from pathlib import Path
|
|
import re
|
|
from datetime import timedelta
|
|
from tempfile import NamedTemporaryFile
|
|
import json
|
|
from io import BytesIO
|
|
from celery import current_app
|
|
from django.conf import settings
|
|
from django.db import connection
|
|
from django.db import IntegrityError
|
|
from django.db.models import Q
|
|
from django.db.models import Count
|
|
from django.shortcuts import get_object_or_404, redirect, render
|
|
from django.contrib import messages
|
|
from django.contrib.auth import get_user_model, login as auth_login
|
|
from django.contrib.auth.decorators import login_required
|
|
from django.contrib.auth.tokens import default_token_generator
|
|
from django.http import JsonResponse
|
|
from django.views.decorators.http import require_POST
|
|
from django.views.decorators.csrf import ensure_csrf_cookie
|
|
from django.utils import timezone
|
|
from django.utils.encoding import force_bytes
|
|
from django.utils.http import urlsafe_base64_encode
|
|
from django.utils.translation import gettext as _
|
|
from django.urls import reverse
|
|
|
|
from .app_registry import build_portal_app_sections, get_portal_app_registry_rows, normalize_portal_app_sort_orders
|
|
from .backup_ops import (
|
|
create_backup_bundle,
|
|
delete_backup_bundle,
|
|
latest_backup_health_snapshot,
|
|
list_backup_bundles,
|
|
verify_backup_bundle,
|
|
)
|
|
from .branding import get_branding_email_copy, get_company_email_domain, get_default_notification_templates, get_portal_trial_config, is_trial_expired
|
|
from . import account_views, admin_config_views, integrations_views, request_views
|
|
from .admin_section_builders import (
|
|
build_branding_sections as _build_branding_sections,
|
|
build_company_config_sections as _build_company_config_sections,
|
|
)
|
|
from .admin_user_helpers import (
|
|
render_user_management as _render_user_management,
|
|
send_user_access_email as _send_user_access_email,
|
|
would_remove_last_platform_owner as _would_remove_last_platform_owner,
|
|
would_remove_last_super_admin as _would_remove_last_super_admin,
|
|
)
|
|
from .forms import AccountAvatarForm, AccountDetailsForm, AccountNotificationPreferencesForm, AccountTOTPDisableForm, AccountTOTPEnableForm, AccountTOTPRegenerateRecoveryCodesForm, AppLoginForm, AppTOTPChallengeForm, OffboardingRequestForm, OnboardingRequestForm, PortalBrandingForm, PortalCompanyConfigForm, PortalTrialConfigForm, UserManagementCreateForm
|
|
from .form_builder import (
|
|
DEFAULT_FIELD_ORDER,
|
|
DEFAULT_CONDITIONAL_RULES,
|
|
FORM_PRESETS,
|
|
LOCKED_FIELD_RULES,
|
|
LOCKED_SECTION_RULES,
|
|
OFFBOARDING_PAGE_LABELS,
|
|
OFFBOARDING_PAGE_ORDER,
|
|
ONBOARDING_DEFAULT_PAGE,
|
|
build_custom_field_key,
|
|
custom_field_target_key,
|
|
ensure_form_field_configs,
|
|
ensure_form_conditional_rule_configs,
|
|
ensure_form_section_configs,
|
|
get_custom_field_configs,
|
|
get_custom_section_configs,
|
|
get_default_page_map,
|
|
get_section_definitions,
|
|
get_section_labels,
|
|
get_section_order,
|
|
apply_form_preset,
|
|
)
|
|
from .form_builder_views import form_builder_page_impl
|
|
from .intro_builder_views import intro_builder_page_impl
|
|
from .observability_views import (
|
|
audit_log_page_impl,
|
|
backup_recovery_page_impl,
|
|
create_backup_from_admin_impl,
|
|
job_monitor_page_impl,
|
|
verify_backup_from_admin_impl,
|
|
)
|
|
from .view_audit import audit as _audit, audit_action_label as _audit_action_label, display_user_name as _display_user_name
|
|
from .view_context import (
|
|
form_field_labels as _form_field_labels,
|
|
request_custom_field_details as _request_custom_field_details,
|
|
request_status_label as _request_status_label,
|
|
request_target_label as _request_target_label,
|
|
)
|
|
from .view_form_runtime import (
|
|
CONDITIONAL_RULE_OPERATOR_CHOICES,
|
|
ONBOARDING_CHECKBOX_LISTS,
|
|
ONBOARDING_GROUPS,
|
|
ONBOARDING_INLINE_CHECKS,
|
|
active_conditional_target_keys as _active_conditional_target_keys,
|
|
build_offboarding_sections as _build_offboarding_sections,
|
|
build_onboarding_layout as _build_onboarding_layout,
|
|
build_onboarding_sections as _build_onboarding_sections,
|
|
conditional_rule_summary as _conditional_rule_summary,
|
|
field_rule_summary as _field_rule_summary,
|
|
normalized_conditional_rule_payload as _normalized_conditional_rule_payload,
|
|
translate_choice_list as _translate_choice_list,
|
|
)
|
|
from .view_permissions import require_capability as _require_capability
|
|
from .models import AdminAuditLog, AsyncTaskLog, EmployeeProfile, FormConditionalRuleConfig, FormCustomFieldConfig, FormCustomSectionConfig, FormFieldConfig, FormOption, FormSectionConfig, NotificationRule, NotificationTemplate, OffboardingRequest, OnboardingIntroductionSession, OnboardingRequest, PortalAppConfig, PortalBranding, PortalCompanyConfig, PortalTrialConfig, ScheduledWelcomeEmail, SystemEmailConfig, UserNotification, UserProfile, WorkflowConfig
|
|
from .emailing import send_system_email
|
|
from .notifications import notify_user
|
|
from .roles import ROLE_GROUP_NAMES, ROLE_LABELS, ROLE_PLATFORM_OWNER, ROLE_SUPER_ADMIN, assign_user_role, get_user_role_key, get_user_role_label, user_has_capability
|
|
from .services import get_email_test_redirect, is_email_test_mode, is_nextcloud_enabled, upload_to_nextcloud
|
|
from .totp import build_otpauth_uri, generate_recovery_codes, generate_totp_secret
|
|
from .tasks import (
|
|
_generate_onboarding_intro_pdf,
|
|
_generate_onboarding_intro_session_pdf,
|
|
build_intro_sections_for_request,
|
|
process_offboarding_request,
|
|
process_onboarding_request,
|
|
send_scheduled_welcome_email,
|
|
)
|
|
|
|
|
|
def _redirect_back(request, fallback: str):
|
|
target = (request.POST.get('next') or request.GET.get('next') or '').strip()
|
|
if target.startswith('/'):
|
|
return redirect(target)
|
|
referer = (request.META.get('HTTP_REFERER') or '').strip()
|
|
if referer.startswith('http://127.0.0.1') or referer.startswith('http://localhost') or referer.startswith('/'):
|
|
return redirect(referer)
|
|
return redirect(fallback)
|
|
|
|
|
|
@login_required
|
|
@require_POST
|
|
def mark_notification_read(request, notification_id: int):
|
|
notification = get_object_or_404(UserNotification, id=notification_id, user=request.user)
|
|
notification.mark_read()
|
|
return _redirect_back(request, 'home')
|
|
|
|
|
|
@login_required
|
|
@require_POST
|
|
def mark_all_notifications_read(request):
|
|
UserNotification.objects.filter(user=request.user, read_at__isnull=True).update(read_at=timezone.now())
|
|
return _redirect_back(request, 'home')
|
|
|
|
def healthz(request):
|
|
db_ok = True
|
|
try:
|
|
with connection.cursor() as cursor:
|
|
cursor.execute('SELECT 1')
|
|
cursor.fetchone()
|
|
except Exception:
|
|
db_ok = False
|
|
|
|
status_code = 200 if db_ok else 503
|
|
return JsonResponse(
|
|
{
|
|
'status': 'ok' if db_ok else 'degraded',
|
|
'service': 'workdock',
|
|
'db': 'ok' if db_ok else 'error',
|
|
'time': timezone.now().isoformat(),
|
|
},
|
|
status=status_code,
|
|
)
|
|
|
|
|
|
def login_page(request):
|
|
return account_views.login_page_impl(request)
|
|
|
|
|
|
def login_totp_page(request):
|
|
return account_views.login_totp_page_impl(request)
|
|
|
|
|
|
@login_required
|
|
def account_profile_page(request):
|
|
return account_views.account_profile_page_impl(request)
|
|
|
|
|
|
@login_required
|
|
def home(request):
|
|
config, _ = WorkflowConfig.objects.get_or_create(name='Default')
|
|
role_key = get_user_role_key(request.user)
|
|
return render(
|
|
request,
|
|
'workflows/home.html',
|
|
{
|
|
'nextcloud_enabled': is_nextcloud_enabled(),
|
|
'email_test_mode': is_email_test_mode(),
|
|
'workflow_config': config,
|
|
'role_label': get_user_role_label(request.user),
|
|
'role_key': role_key,
|
|
'portal_app_sections': build_portal_app_sections(request.user),
|
|
},
|
|
)
|
|
|
|
|
|
@_require_capability('manage_app_registry')
|
|
def portal_app_registry_page(request):
|
|
return admin_config_views.portal_app_registry_page_impl(request, translate_choice_list=_translate_choice_list)
|
|
|
|
|
|
@_require_capability('view_job_monitor')
|
|
def job_monitor_page(request):
|
|
return job_monitor_page_impl(request)
|
|
|
|
|
|
@_require_capability('manage_app_registry')
|
|
@require_POST
|
|
def save_portal_app_registry(request):
|
|
return admin_config_views.save_portal_app_registry_impl(request, audit_fn=_audit)
|
|
|
|
|
|
@_require_capability('manage_users')
|
|
def user_management_page(request):
|
|
return admin_config_views.user_management_page_impl(
|
|
request,
|
|
render_user_management_fn=lambda req, create_form=None, status_code=200: _render_user_management(
|
|
req,
|
|
create_form=create_form,
|
|
status_code=status_code,
|
|
audit_action_label_fn=_audit_action_label,
|
|
display_user_name_fn=_display_user_name,
|
|
),
|
|
)
|
|
|
|
|
|
@_require_capability('manage_product_branding')
|
|
def portal_branding_page(request):
|
|
return admin_config_views.portal_branding_page_impl(request, build_branding_sections_fn=_build_branding_sections)
|
|
|
|
|
|
@_require_capability('manage_product_branding')
|
|
@require_POST
|
|
def save_portal_branding(request):
|
|
return admin_config_views.save_portal_branding_impl(request, audit_fn=_audit, build_branding_sections_fn=_build_branding_sections)
|
|
|
|
|
|
@_require_capability('manage_company_config')
|
|
def portal_company_config_page(request):
|
|
return admin_config_views.portal_company_config_page_impl(request, build_company_config_sections_fn=_build_company_config_sections)
|
|
|
|
|
|
@_require_capability('manage_company_config')
|
|
@require_POST
|
|
def save_portal_company_config(request):
|
|
return admin_config_views.save_portal_company_config_impl(request, audit_fn=_audit, build_company_config_sections_fn=_build_company_config_sections)
|
|
|
|
|
|
@_require_capability('manage_trial_lifecycle')
|
|
def portal_trial_config_page(request):
|
|
return admin_config_views.portal_trial_config_page_impl(request)
|
|
|
|
|
|
@_require_capability('manage_trial_lifecycle')
|
|
@require_POST
|
|
def save_portal_trial_config(request):
|
|
return admin_config_views.save_portal_trial_config_impl(request, audit_fn=_audit)
|
|
|
|
|
|
@_require_capability('manage_users')
|
|
@require_POST
|
|
def create_user_from_admin(request):
|
|
return admin_config_views.create_user_from_admin_impl(
|
|
request,
|
|
render_user_management_fn=lambda req, create_form=None, status_code=200: _render_user_management(
|
|
req,
|
|
create_form=create_form,
|
|
status_code=status_code,
|
|
audit_action_label_fn=_audit_action_label,
|
|
display_user_name_fn=_display_user_name,
|
|
),
|
|
send_user_access_email_fn=lambda req, target_user, invitation: _send_user_access_email(
|
|
req,
|
|
target_user,
|
|
invitation=invitation,
|
|
display_user_name_fn=_display_user_name,
|
|
),
|
|
audit_fn=_audit,
|
|
display_user_name_fn=_display_user_name,
|
|
)
|
|
|
|
|
|
@_require_capability('manage_users')
|
|
@require_POST
|
|
def update_user_from_admin(request, user_id: int):
|
|
return admin_config_views.update_user_from_admin_impl(
|
|
request,
|
|
user_id,
|
|
would_remove_last_platform_owner_fn=_would_remove_last_platform_owner,
|
|
would_remove_last_super_admin_fn=_would_remove_last_super_admin,
|
|
audit_fn=_audit,
|
|
display_user_name_fn=_display_user_name,
|
|
)
|
|
|
|
|
|
@_require_capability('manage_users')
|
|
@require_POST
|
|
def send_password_reset_from_admin(request, user_id: int):
|
|
return admin_config_views.send_password_reset_from_admin_impl(
|
|
request,
|
|
user_id,
|
|
send_user_access_email_fn=lambda req, target_user, invitation: _send_user_access_email(
|
|
req,
|
|
target_user,
|
|
invitation=invitation,
|
|
display_user_name_fn=_display_user_name,
|
|
),
|
|
audit_fn=_audit,
|
|
display_user_name_fn=_display_user_name,
|
|
)
|
|
|
|
|
|
@_require_capability('manage_users')
|
|
@require_POST
|
|
def delete_user_from_admin(request, user_id: int):
|
|
return admin_config_views.delete_user_from_admin_impl(
|
|
request,
|
|
user_id,
|
|
would_remove_last_platform_owner_fn=_would_remove_last_platform_owner,
|
|
would_remove_last_super_admin_fn=_would_remove_last_super_admin,
|
|
audit_fn=_audit,
|
|
display_user_name_fn=_display_user_name,
|
|
)
|
|
|
|
|
|
@_require_capability('view_docs')
|
|
def handbook_page(request):
|
|
return admin_config_views.handbook_page_impl(request)
|
|
|
|
|
|
@_require_capability('view_docs')
|
|
def project_wiki_page(request):
|
|
return admin_config_views.project_wiki_page_impl(request)
|
|
|
|
|
|
@_require_capability('view_docs')
|
|
def developer_handbook_page(request):
|
|
return admin_config_views.developer_handbook_page_impl(request)
|
|
|
|
|
|
@_require_capability('view_docs')
|
|
def release_checklist_page(request):
|
|
return admin_config_views.release_checklist_page_impl(request)
|
|
|
|
|
|
@_require_capability('view_audit_log')
|
|
def audit_log_page(request):
|
|
return audit_log_page_impl(request)
|
|
|
|
|
|
@_require_capability('manage_backups')
|
|
def backup_recovery_page(request):
|
|
return backup_recovery_page_impl(request)
|
|
|
|
|
|
@_require_capability('manage_backups')
|
|
@require_POST
|
|
def create_backup_from_admin(request):
|
|
return create_backup_from_admin_impl(
|
|
request,
|
|
audit_fn=_audit,
|
|
notify_user_fn=notify_user,
|
|
create_backup_bundle_fn=create_backup_bundle,
|
|
)
|
|
|
|
|
|
@_require_capability('manage_backups')
|
|
@require_POST
|
|
def verify_backup_from_admin(request, backup_name: str):
|
|
return verify_backup_from_admin_impl(
|
|
request,
|
|
backup_name,
|
|
audit_fn=_audit,
|
|
notify_user_fn=notify_user,
|
|
verify_backup_bundle_fn=verify_backup_bundle,
|
|
)
|
|
|
|
|
|
@_require_capability('manage_backups')
|
|
@require_POST
|
|
def delete_backup_from_admin(request, backup_name: str):
|
|
try:
|
|
result = delete_backup_bundle(backup_name)
|
|
_audit(
|
|
request,
|
|
'backup_deleted',
|
|
target_type='backup_bundle',
|
|
target_label=backup_name,
|
|
details={},
|
|
)
|
|
messages.success(request, _('Backup wurde gelöscht: %(name)s') % {'name': result['name']})
|
|
except Exception as exc:
|
|
messages.error(request, _('Backup konnte nicht gelöscht werden: %(error)s') % {'error': exc})
|
|
return redirect('backup_recovery_page')
|
|
|
|
|
|
@_require_capability('view_request_timeline')
|
|
def request_timeline_page(request, kind: str, request_id: int):
|
|
return request_views.request_timeline_page_impl(
|
|
request,
|
|
kind,
|
|
request_id,
|
|
request_target_label_fn=_request_target_label,
|
|
request_custom_field_details_fn=_request_custom_field_details,
|
|
audit_action_label_fn=_audit_action_label,
|
|
)
|
|
|
|
|
|
@login_required
|
|
def requests_dashboard(request):
|
|
return request_views.requests_dashboard_impl(
|
|
request,
|
|
audit_fn=_audit,
|
|
request_target_label_fn=_request_target_label,
|
|
request_status_label_fn=_request_status_label,
|
|
)
|
|
|
|
|
|
@login_required
|
|
@ensure_csrf_cookie
|
|
def onboarding_create(request):
|
|
return request_views.onboarding_create_impl(
|
|
request,
|
|
build_onboarding_layout_fn=_build_onboarding_layout,
|
|
build_onboarding_sections_fn=_build_onboarding_sections,
|
|
normalized_conditional_rule_payload_fn=_normalized_conditional_rule_payload,
|
|
display_user_name_fn=_display_user_name,
|
|
onboarding_inline_checks=ONBOARDING_INLINE_CHECKS,
|
|
onboarding_checkbox_lists=ONBOARDING_CHECKBOX_LISTS,
|
|
)
|
|
|
|
|
|
@login_required
|
|
def onboarding_success(request, request_id: int):
|
|
return request_views.onboarding_success_impl(request, request_id)
|
|
|
|
|
|
@_require_capability('generate_intro_pdfs')
|
|
@require_POST
|
|
def generate_onboarding_intro_pdf(request, request_id: int):
|
|
return request_views.generate_onboarding_intro_pdf_impl(request, request_id, audit_fn=_audit)
|
|
|
|
|
|
@_require_capability('generate_intro_pdfs')
|
|
@require_POST
|
|
def generate_onboarding_intro_session_pdf(request, request_id: int):
|
|
return request_views.generate_onboarding_intro_session_pdf_impl(request, request_id, audit_fn=_audit, display_user_name_fn=_display_user_name)
|
|
|
|
|
|
@_require_capability('run_intro_session')
|
|
def onboarding_intro_session_page(request, request_id: int):
|
|
return request_views.onboarding_intro_session_page_impl(request, request_id, audit_fn=_audit, display_user_name_fn=_display_user_name)
|
|
|
|
|
|
@login_required
|
|
@ensure_csrf_cookie
|
|
def offboarding_create(request):
|
|
return request_views.offboarding_create_impl(
|
|
request,
|
|
build_offboarding_sections_fn=_build_offboarding_sections,
|
|
display_user_name_fn=_display_user_name,
|
|
)
|
|
|
|
|
|
@login_required
|
|
def offboarding_success(request, request_id: int):
|
|
return request_views.offboarding_success_impl(request, request_id)
|
|
|
|
|
|
@_require_capability('manage_builders')
|
|
def form_builder_page(request):
|
|
return form_builder_page_impl(
|
|
request,
|
|
audit_fn=_audit,
|
|
translate_choice_list=_translate_choice_list,
|
|
form_field_labels_fn=_form_field_labels,
|
|
field_rule_summary_fn=_field_rule_summary,
|
|
conditional_rule_summary_fn=_conditional_rule_summary,
|
|
onboarding_groups=ONBOARDING_GROUPS,
|
|
conditional_rule_operator_choices=CONDITIONAL_RULE_OPERATOR_CHOICES,
|
|
)
|
|
|
|
|
|
@_require_capability('manage_builders')
|
|
def intro_builder_page(request):
|
|
return intro_builder_page_impl(
|
|
request,
|
|
audit_fn=_audit,
|
|
translate_choice_list=_translate_choice_list,
|
|
)
|
|
|
|
|
|
@_require_capability('manage_integrations')
|
|
def integrations_setup_page(request):
|
|
return integrations_views.integrations_setup_page_impl(request)
|
|
|
|
|
|
@_require_capability('manage_welcome_emails')
|
|
def welcome_emails_page(request):
|
|
return integrations_views.welcome_emails_page_impl(request)
|
|
|
|
|
|
@_require_capability('manage_welcome_emails')
|
|
@require_POST
|
|
def trigger_welcome_email_now(request, schedule_id: int):
|
|
return integrations_views.trigger_welcome_email_now_impl(request, schedule_id, audit_fn=_audit)
|
|
|
|
|
|
@_require_capability('manage_welcome_emails')
|
|
@require_POST
|
|
def save_welcome_email_settings(request):
|
|
return integrations_views.save_welcome_email_settings_impl(request, audit_fn=_audit)
|
|
|
|
|
|
def _revoke_celery_task(task_id: str) -> None:
|
|
if not task_id:
|
|
return
|
|
try:
|
|
current_app.control.revoke(task_id, terminate=False)
|
|
except Exception:
|
|
return
|
|
|
|
|
|
def _parse_selected_schedule_ids(raw: str) -> list[int]:
|
|
if not raw:
|
|
return []
|
|
parsed: list[int] = []
|
|
seen: set[int] = set()
|
|
for token in raw.split(','):
|
|
token = token.strip()
|
|
if not token:
|
|
continue
|
|
try:
|
|
schedule_id = int(token)
|
|
except ValueError:
|
|
continue
|
|
if schedule_id in seen:
|
|
continue
|
|
seen.add(schedule_id)
|
|
parsed.append(schedule_id)
|
|
return parsed
|
|
|
|
|
|
@_require_capability('manage_welcome_emails')
|
|
@require_POST
|
|
def bulk_welcome_email_action(request):
|
|
return integrations_views.bulk_welcome_email_action_impl(request, audit_fn=_audit)
|
|
|
|
|
|
@_require_capability('manage_welcome_emails')
|
|
@require_POST
|
|
def pause_welcome_email(request, schedule_id: int):
|
|
return integrations_views.pause_welcome_email_impl(request, schedule_id, audit_fn=_audit)
|
|
|
|
|
|
@_require_capability('manage_welcome_emails')
|
|
@require_POST
|
|
def resume_welcome_email(request, schedule_id: int):
|
|
return integrations_views.resume_welcome_email_impl(request, schedule_id, audit_fn=_audit)
|
|
|
|
|
|
@_require_capability('manage_welcome_emails')
|
|
@require_POST
|
|
def cancel_welcome_email(request, schedule_id: int):
|
|
return integrations_views.cancel_welcome_email_impl(request, schedule_id, audit_fn=_audit)
|
|
|
|
|
|
@_require_capability('manage_builders')
|
|
@require_POST
|
|
def form_builder_save_order(request):
|
|
return integrations_views.form_builder_save_order_impl(request, audit_fn=_audit)
|
|
|
|
|
|
@_require_capability('manage_integrations')
|
|
@require_POST
|
|
def send_test_email(request):
|
|
return integrations_views.send_test_email_impl(request, audit_fn=_audit, redirect_back_fn=_redirect_back)
|
|
|
|
|
|
@_require_capability('manage_integrations')
|
|
@require_POST
|
|
def nextcloud_test_upload(request):
|
|
return integrations_views.nextcloud_test_upload_impl(request, audit_fn=_audit, redirect_back_fn=_redirect_back)
|
|
|
|
|
|
@_require_capability('manage_integrations')
|
|
@require_POST
|
|
def toggle_nextcloud_enabled(request):
|
|
return integrations_views.toggle_nextcloud_enabled_impl(request, audit_fn=_audit, redirect_back_fn=_redirect_back)
|
|
|
|
|
|
@_require_capability('manage_integrations')
|
|
@require_POST
|
|
def toggle_email_mode(request):
|
|
return integrations_views.toggle_email_mode_impl(request, audit_fn=_audit, redirect_back_fn=_redirect_back)
|
|
|
|
|
|
@_require_capability('manage_integrations')
|
|
@require_POST
|
|
def save_integrations_settings(request):
|
|
return integrations_views.save_integrations_settings_impl(request, audit_fn=_audit)
|
|
|
|
|
|
@_require_capability('manage_integrations')
|
|
@require_POST
|
|
def save_nextcloud_settings(request):
|
|
return integrations_views.save_nextcloud_settings_impl(request, audit_fn=_audit)
|
|
|
|
|
|
@_require_capability('manage_integrations')
|
|
@require_POST
|
|
def save_workflow_rules(request):
|
|
return integrations_views.save_workflow_rules_impl(request, audit_fn=_audit)
|
|
|
|
|
|
@_require_capability('manage_integrations')
|
|
@require_POST
|
|
def save_backup_settings(request):
|
|
return integrations_views.save_backup_settings_impl(request, audit_fn=_audit)
|
|
|
|
|
|
@_require_capability('manage_integrations')
|
|
@require_POST
|
|
def save_mail_settings(request):
|
|
return integrations_views.save_mail_settings_impl(request, audit_fn=_audit)
|
|
|
|
|
|
@_require_capability('manage_integrations')
|
|
@require_POST
|
|
def save_email_routing_settings(request):
|
|
return integrations_views.save_email_routing_settings_impl(request, audit_fn=_audit)
|
|
|
|
|
|
@_require_capability('manage_integrations')
|
|
@require_POST
|
|
def save_notification_rules(request):
|
|
return integrations_views.save_notification_rules_impl(request, audit_fn=_audit)
|
|
|
|
|
|
@_require_capability('delete_requests')
|
|
@require_POST
|
|
def delete_request_from_dashboard(request, kind: str, request_id: int):
|
|
return request_views.delete_request_from_dashboard_impl(request, kind, request_id, audit_fn=_audit, request_target_label_fn=_request_target_label)
|
|
|
|
|
|
@_require_capability('retry_requests')
|
|
@require_POST
|
|
def retry_request_from_dashboard(request, kind: str, request_id: int):
|
|
return request_views.retry_request_from_dashboard_impl(request, kind, request_id, audit_fn=_audit, request_target_label_fn=_request_target_label)
|