MAKENTNU/web

View on GitHub
src/util/ckeditor_utils.py

Summary

Maintainability
A
0 mins
Test Coverage
"""
Code based on https://github.com/xcom-data/xcom/blob/b2c51ce07f9f33e16742a61bd9e3d96f0683a317/xcom/util/ckeditor_utils.py
"""
from typing import Type
from urllib.parse import unquote, urlparse

from ckeditor_uploader import utils
from django.conf import settings
from django.db.models import Model
from django.urls import resolve
from django.utils import timezone
from django.utils.text import slugify

from docs.models import Page
from util.locale_utils import localize_lazy_string
from util.logging_utils import log_request_exception
from web import admin_urls


def get_filename(upload_name: str, request):
    """
    This function is used by the ``CKEDITOR_FILENAME_GENERATOR`` setting
    to set the name (incl. prefixed names of containing folders) of files uploaded using the CKEditor uploader widget.
    """
    filename = utils.slugify_filename(upload_name)
    date_prefix = timezone.localdate().strftime("%Y/%m/%d")

    try:
        folder_name = get_folder_name(request)
    except Exception as e:
        log_request_exception(f"Failed to determine the proper folder name for the file with name '{upload_name}'", e, request)
        # Fall back to the default date-prefixed format
        return f"{date_prefix}/{filename}" if should_prefix_date() else filename

    return f"{folder_name}/{date_prefix}/{filename}"


def get_folder_name(request):
    http_headers = request.headers
    origin_full_url = http_headers.get('REFERER')  # REFERER is supposed to have a typo
    if not origin_full_url:
        raise Exception("Could not find HTTP_REFERER among the request's headers")

    origin_path = urlparse(origin_full_url).path
    # Replace `%xx` escapes with their single-character equivalent, to prevent errors in `resolve()` below
    # - which could happen if resolving e.g. the path of a documentation page, which can contain `%xx` characters (like `%20` for space)
    origin_path = unquote(origin_path)

    view_func, _args, _kwargs = resolve(origin_path, request.urlconf)
    # If the URL config is the one for the Django admin subdomain:
    if request.urlconf == admin_urls.__name__:
        # The view must be a `ModelAdmin` subclass
        model: Type[Model] = view_func.model_admin.model
    else:
        # The view is (probably) a `SingleObjectMixin` subclass
        model: Type[Model] = view_func.view_class.model

    model_name_plural = get_model_name_plural(model)
    return slugify(model_name_plural).replace("-", "_")  # The naming convention for folders is snake_case


def get_model_name_plural(model: Type[Model]):
    if model == Page:
        return "docs"

    return localize_lazy_string(model._meta.verbose_name_plural, language_code="en")


def should_prefix_date():
    # If not grouping uploaded files by date, do it anyway, manually;
    # otherwise, the filename should already be date-prefixed
    return not getattr(settings, 'CKEDITOR_RESTRICT_BY_DATE', True)