From 4cdd9f1d35dc619afec3e3cafa66e43a7ed9f53f Mon Sep 17 00:00:00 2001 From: odkhang Date: Tue, 2 Jul 2024 23:47:46 +0700 Subject: [PATCH] Add plugins to autodeployment with docker (#112) * add plugin for auto deployment --- Dockerfile | 1 - pyproject.toml | 2 + src/pretalx/common/models/mixins.py | 46 +++++++++++++ src/pretalx/common/text/phrases.py | 103 ++++++++++++++++++++++++++++ 4 files changed, 151 insertions(+), 1 deletion(-) create mode 100644 src/pretalx/common/models/mixins.py create mode 100644 src/pretalx/common/text/phrases.py diff --git a/Dockerfile b/Dockerfile index 4af3c6ff7..451d2b76c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -31,7 +31,6 @@ RUN pip3 install -U pip setuptools wheel typing && \ pip3 install pylibmc && \ pip3 install gunicorn - RUN python3 -m pretalx makemigrations RUN python3 -m pretalx migrate diff --git a/pyproject.toml b/pyproject.toml index 12954d597..2ecab5160 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -65,6 +65,8 @@ dependencies = [ "vobject~=0.9.0", "whitenoise~=6.6.0", "zxcvbn~=4.4.0", + 'pretalx_pages @ git+https://github.com/fossasia/eventyay-talk-pages.git@main', + 'pretalx_venueless @ git+https://github.com/fossasia/eventyay-talk-video.git@main' ] [project.optional-dependencies] diff --git a/src/pretalx/common/models/mixins.py b/src/pretalx/common/models/mixins.py new file mode 100644 index 000000000..a82b69650 --- /dev/null +++ b/src/pretalx/common/models/mixins.py @@ -0,0 +1,46 @@ +import json + +from django.contrib.contenttypes.models import ContentType +from i18nfield.utils import I18nJSONEncoder + +SENSITIVE_KEYS = ["password", "secret", "api_key"] + + +class LogMixin: + def log_action(self, action, data=None, person=None, orga=False): + if not self.pk: + return + + from pretalx.common.models import ActivityLog + + if data and isinstance(data, dict): + for key, value in data.items(): + if any(sensitive_key in key for sensitive_key in SENSITIVE_KEYS): + value = data[key] + data[key] = "********" if value else value + data = json.dumps(data, cls=I18nJSONEncoder) + elif data: + raise TypeError( + f"Logged data should always be a dictionary, not {type(data)}." + ) + + return ActivityLog.objects.create( + event=getattr(self, "event", None), + person=person, + content_object=self, + action_type=action, + data=data, + is_orga_action=orga, + ) + + def logged_actions(self): + from pretalx.common.models import ActivityLog + + return ( + ActivityLog.objects.filter( + content_type=ContentType.objects.get_for_model(type(self)), + object_id=self.pk, + ) + .select_related("event", "person") + .prefetch_related("content_object") + ) diff --git a/src/pretalx/common/text/phrases.py b/src/pretalx/common/text/phrases.py new file mode 100644 index 000000000..acee36915 --- /dev/null +++ b/src/pretalx/common/text/phrases.py @@ -0,0 +1,103 @@ +import random +from abc import ABCMeta + +from django.utils.translation import gettext_lazy as _ +from django.utils.translation import pgettext_lazy + +_phrase_book = {} + + +class PhrasesMetaClass(ABCMeta): # noqa + def __new__(cls, class_name, bases, namespace, app): + new = super().__new__(cls, class_name, bases, namespace) + _phrase_book[app] = new() + return new + + def __init__(cls, *args, app, **kwargs): + super().__init__(*args, **kwargs) + + +class Phrases(metaclass=PhrasesMetaClass, app=""): + def __getattribute__(self, attribute): + result = super().__getattribute__(attribute) + if isinstance(result, (list, tuple)): + return random.choice(result) + return result + + +class PhraseBook: + def __getattribute__(self, attribute): + return _phrase_book.get(attribute) + + +phrases = PhraseBook() + + +class BasePhrases(Phrases, app="base"): + """ + This class contains base phrases that are guaranteed to remain the same. + """ + + send = _("Send") + save = _("Save") + cancel = _("Cancel") + edit = _("Edit") + all_choices = _("all") + back_button = _("Back") + delete_button = _("Delete") + + delete_confirm_heading = _("Confirm deletion") + delete_warning = _( + "Please make sure that this is the item you want to delete. This action cannot be undone!" + ) + + saved = _("Your changes have been saved.") + back_try_again = _("Please go back and try again.") + bad_request = _("Bad request.") + error_sending_mail = _( + "There was an error sending the mail. Please try again later." + ) + error_saving_changes = _( + "We had trouble saving your input – Please see below for details." + ) + error_permissions_action = _("You do not have permission to perform this action.") + + permission_denied = _("Permission denied.") + permission_denied_long = ( + _("Sorry, you do not have the required permissions to access this page."), + ) + not_found = _("Page not found.") + not_found_long = [ + _("This page does not exist."), + _("Huh, I could have sworn there was something here."), + "", + _("This page is no more."), + _("This page has ceased to be."), + _("Huh."), + ] + + enter_email = _("Email address") + new_password = _("New password") + password_repeat = _("New password (again)") + passwords_differ = _( + "You entered two different passwords. Please enter the same one twice!" + ) + password_reset_heading = pgettext_lazy("noun / heading", "Reset password") + password_reset_question = _("Forgot your password?") + password_reset_action = _("Let me set a new one!") + password_reset_nearly_done = _( + "Now you just need to choose your new password and you are ready to go." + ) + password_reset_success = _("The password was reset.") + + use_markdown = _("You can use {link_start}Markdown{link_end} here.").format( + link_start='', + link_end="", + ) + public_content = _("This content will be shown publicly.") + quotation_open = pgettext_lazy("opening quotation mark", "“") + quotation_close = pgettext_lazy("closing quotation mark", "”") + language = _("Language") + general = _("General") + email_subject = pgettext_lazy("email subject", "Subject") + text_body = _("Text")