Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
a278cf6
Revert "Provide outbound link signing and redirects"
norbusan Feb 16, 2025
190c946
Reapply "Provide outbound link signing and redirects"
norbusan Feb 16, 2025
2ca2edf
Change texts in the front page of "Call for Speakers" (#274)
hongquan Feb 19, 2025
dbeccc0
Make login button label configurable (#275)
hongquan Feb 20, 2025
e50dc2f
Fix: Login button label is missing (#277)
hongquan Feb 21, 2025
15a400f
Fix: Speaker name in Talk is overwritten (#279)
hongquan Feb 26, 2025
8d0f2f1
Fix: Page width is wider then necessary (#281)
hongquan Feb 26, 2025
bfe9a8a
Disable the subheader login link when there is already login button (…
hongquan Feb 26, 2025
485b51d
Fix: Django not detect that our site is HTTPS
hongquan Feb 26, 2025
5906181
Add Swahili language
hongquan Feb 26, 2025
4d671be
Merge pull request #285 from hongquan/feature/swahili-language
hongquan Feb 27, 2025
5d4412d
Merge pull request #282 from hongquan/fix/django-https-detection
hongquan Feb 27, 2025
7002d06
Fix: User name is overwritten when logging in via WikiMedia SSO (#286)
hongquan Feb 28, 2025
60e14a6
Add `less` command to Docker image (#284)
hongquan Feb 28, 2025
5cd0006
Show avatar_source, avatar_license fields (#288)
hongquan Feb 28, 2025
0e2067b
Fix: pretalx is mentioned in irrelevant context (#290)
hongquan Feb 28, 2025
6cf116f
Fix: Error 500 when try loading missing calendar locale (#293)
hongquan Mar 1, 2025
ddf4f7b
Fix: Customized field label not loaded (#291)
hongquan Mar 1, 2025
059c53d
Fix duplicate avatar source field (#295)
hongquan Mar 2, 2025
89e07af
Translated using Weblate (Swahili)
Mar 3, 2025
1455872
Translated using Weblate (Swahili)
Mar 3, 2025
51db04f
Translated using Weblate (Swahili)
Mar 4, 2025
a4903e1
Translated using Weblate (Swahili)
Mar 4, 2025
886f091
Translated using Weblate (Swahili)
Mar 4, 2025
4b4a2a9
Added translation using Weblate (Persian)
abbasdp Oct 4, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -101,3 +101,8 @@ src/tests/**/*.yml

# Screenshots
screens/

# Stuff which were generated by our Docker containers
.bash_history
.npm
.python_history
3 changes: 2 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ RUN apt-get update && \
supervisor \
sudo \
locales \
less \
--no-install-recommends && \
apt-get clean && \
rm -rf /var/lib/apt/lists/* && \
Expand All @@ -18,7 +19,7 @@ RUN apt-get update && \
mkdir /public && \
groupadd -g $GID pretalxuser && \
useradd -r -u $UID -g pretalxuser -d /pretalx -ms /bin/bash pretalxuser && \
echo 'pretalxuser ALL=(ALL) NOPASSWD:SETENV: /usr/bin/supervisord' >> /etc/sudoers
echo 'pretalxuser ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers

ENV LC_ALL=C.UTF-8
ENV BASE_PATH=/talk
Expand Down
2 changes: 1 addition & 1 deletion deployment/docker/pretalx.bash
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ if [ "$AUTOMIGRATE" = "yes" ]; then
fi

if [ "$1" == "all" ]; then
exec sudo /usr/bin/supervisord -n -c /etc/supervisord.conf
exec sudo -E /usr/bin/supervisord -n -c /etc/supervisord.conf
fi

if [ "$1" == "webworker" ]; then
Expand Down
6 changes: 4 additions & 2 deletions src/pretalx.example.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,16 @@ static = /var/pretalx/static
debug = False
url = https://eventyay.mydomain.com
name = eventyay
# To select a variant from CALL_FOR_SPEAKER_LOGIN_BTN_LABELS.
call_for_speaker_login_button_label = default

[database]
backend = postgresql
name = pretalx
user = pretalx
# For PostgreSQL on the same host, we don't need one because we can use
# peer authentification if our PostgreSQL user matches our unix user.
password = Change this in production or you're going to have a bad time
password = Change this in production or you"'"re going to have a bad time
# For a remote host, supply an IP address
# For local postgres authentication, you can leave the host empty
host = localhost
Expand All @@ -27,6 +29,6 @@ from = admin@localhost
host = localhost
port = 25
user = admin
password = Change this in production or you're going to have a bad time
password = Change this in production or you"'"re going to have a bad time
tls = False
ssl = True
2 changes: 2 additions & 0 deletions src/pretalx/cfp/flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@
Track,
)

logger = logging.getLogger(__name__)


def i18n_string(data, locales):
if isinstance(data, LazyI18nString):
Expand Down
5 changes: 5 additions & 0 deletions src/pretalx/cfp/forms/cfp.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
import logging

logger = logging.getLogger(__name__)


class CfPFormMixin:
"""All forms used in the CfP step process should use this mixin.

Expand Down
6 changes: 3 additions & 3 deletions src/pretalx/cfp/templates/cfp/event/submission_base.html
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ <h2>{% block submission_step_title %}{{ title|default:'' }}{% endblock submissio
</button>
<button type="submit" class="btn btn-link text-center" name="action" value="draft">
{% translate "or save as draft for now" %}
<i class="fa fa-question-circle" data-toggle="tooltip" title="{% translate "You can save your proposal as a draft and submit it later. Organisers will not be able to see your proposal, though they will be able to send you reminder emails about the upcoming deadline." %}"></i>
<i class="fa fa-question-circle" title="{% translate "You can save your proposal as a draft and submit it later. Organisers will not be able to see your proposal, though they will be able to send you reminder emails about the upcoming deadline." %}"></i>
</button>
{% endif %}
</div>
Expand All @@ -82,8 +82,8 @@ <h2>{% block submission_step_title %}{{ title|default:'' }}{% endblock submissio
{% endblock buttons %}
</form>
{% else %}
<h2>{% translate "You are required to be logged in to submit a proposal" %}</h2>
<p>{% translate "To create your proposal, you need an account on this page. This not only gives us a way to contact you, it also gives you the possibility to edit your proposal or to view its current state." %}</p>
<h2>{{ _('You need to be logged in to submit a proposal') }}</h2>
<p>{{ _('Please log in or create an account to submit a proposal. This enables us to contact you and allows you to edit your proposal or check its status at any time.') }}</p>
{% include "common/auth.html" with form=form no_form=True no_buttons=True next_url=request.get_full_path %}
{% endif %}
{% endblock cfp_form %}
Expand Down
2 changes: 2 additions & 0 deletions src/pretalx/cfp/templates/cfp/event/user_profile.html
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ <h2>{% translate "Your Profile" %}</h2>
{% if request.event.cfp.request_avatar %}
{% include "common/avatar.html" with user=request.user form=profile_form %}
{% endif %}
{% if profile_form.avatar_source %}{{ profile_form.avatar_source.as_field_group }}{% endif %}
{% if profile_form.avatar_license %}{{ profile_form.avatar_license.as_field_group }}{% endif %}
{% if profile_form.availabilities %}
{% include "common/availabilities.html" %}
{{ profile_form.availabilities.as_field_group }}
Expand Down
5 changes: 5 additions & 0 deletions src/pretalx/cfp/views/auth.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import datetime as dt
import logging

from django.conf import settings
from django.contrib import messages
Expand All @@ -20,6 +21,7 @@
from pretalx.person.models import User

SessionStore = import_string(f"{settings.SESSION_ENGINE}.SessionStore")
logger = logging.getLogger(__name__)


class LogoutView(View):
Expand All @@ -42,6 +44,7 @@ class LoginView(GenericLoginView):

def dispatch(self, request, *args, **kwargs):
if not request.event.is_public:
logger.info("Event %s is not public. Blocking access.", request.event.slug)
raise Http404()
return super().dispatch(request, *args, **kwargs)

Expand All @@ -58,6 +61,8 @@ def get_password_reset_link(self):
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["register_url"] = settings.EVENTYAY_TICKET_BASE_PATH
# We already have a primary login button in this page, disable the subheader login link.
context["subheader_login_link_disabled"] = True
return context


Expand Down
2 changes: 1 addition & 1 deletion src/pretalx/cfp/views/locale.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ def get(self, request, *args, **kwargs):
str(
_(
"Your locale preferences have been saved. We like to think that we have excellent support "
"for English in pretalx, but if you encounter issues or errors, please contact us!"
"for English, but if you encounter issues or errors, please contact us!"
)
),
)
Expand Down
11 changes: 8 additions & 3 deletions src/pretalx/cfp/views/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,14 +63,19 @@ def token(self):
@cached_property
def profile_form(self):
bind = is_form_bound(self.request, "profile")
cfp_flow_config = self.request.event.cfp_flow.config
try:
# TODO: There may be a mismatch somewhere else between how the config was saved and how it is loaded.
# We should use Pydantic model for saving and loading, to make sure the data is consistent.
field_configuration = cfp_flow_config["steps"]["profile"]["fields"]
except KeyError:
field_configuration = None
return SpeakerProfileForm(
user=self.request.user,
event=self.request.event,
read_only=False,
with_email=False,
field_configuration=self.request.event.cfp_flow.config.get(
"profile", {}
).get("fields"),
field_configuration=field_configuration,
data=self.request.POST if bind else None,
files=self.request.FILES if bind else None,
)
Expand Down
3 changes: 3 additions & 0 deletions src/pretalx/cfp/views/wizard.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
from pretalx.common.exceptions import SendMailException
from pretalx.common.text.phrases import phrases

logger = logging.getLogger(__name__)


class SubmitStartView(EventPageMixin, View):
@staticmethod
Expand Down Expand Up @@ -57,6 +59,7 @@ def dispatch(self, request, *args, **kwargs):
if getattr(step, "is_before", False): # The current step URL is incorrect
raise Http404()
handler = getattr(step, request.method.lower(), self.http_method_not_allowed)
logger.debug("Handler: %s", handler)
result = handler(request)

if request.method == "POST" and request.POST.get("action", "submit") == "draft":
Expand Down
12 changes: 12 additions & 0 deletions src/pretalx/common/context_processors.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import logging
import sys
import warnings
from pathlib import Path

from django.conf import settings
from django.http import Http404
Expand All @@ -12,6 +14,8 @@
from pretalx.common.text.phrases import phrases
from pretalx.orga.utils.i18n import get_javascript_format, get_moment_locale

logger = logging.getLogger(__name__)


def add_events(request):
if (
Expand All @@ -35,6 +39,13 @@ def get_day_month_date_format():


def locale_context(request):
cal_static_dir = Path(__file__).parent.parent.joinpath(
"static", "vendored", "fullcalendar", "locales"
)
AVAILABLE_CALENDAR_LOCALES = tuple(
f.name.removesuffix(".global.min.js")
for f in cal_static_dir.rglob("*.global.min.js")
)
context = {
"js_date_format": get_javascript_format("DATE_INPUT_FORMATS"),
"js_datetime_format": get_javascript_format("DATETIME_INPUT_FORMATS"),
Expand All @@ -43,6 +54,7 @@ def locale_context(request):
"quotation_close": phrases.base.quotation_close,
"DAY_MONTH_DATE_FORMAT": get_day_month_date_format(),
"rtl": getattr(request, "LANGUAGE_CODE", "en") in settings.LANGUAGES_RTL,
"AVAILABLE_CALENDAR_LOCALES": AVAILABLE_CALENDAR_LOCALES,
}

lang = translation.get_language()
Expand Down
7 changes: 6 additions & 1 deletion src/pretalx/common/middleware/event.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,13 +78,18 @@ def _handle_login(request):
user, created = User.objects.get_or_create(email=payload["email"])
if created:
user.set_unusable_password()
user.name = payload.get("name", "")
logger.debug("JWT payload: %s", payload)
upstream_name = payload.get("name", "")
# Only update user's name if it's not set.
if not user.name and upstream_name:
user.name = upstream_name
user.is_active = True
user.is_staff = payload.get("is_staff", False)
user.locale = payload.get("locale", user.locale)
user.timezone = payload.get("timezone", user.timezone)
user.code = payload.get("customer_identifier", user.code)
user.save()
logger.info("Saved new data for user: %s", user.email)
login(
request, user, backend="django.contrib.auth.backends.ModelBackend"
)
Expand Down
1 change: 1 addition & 0 deletions src/pretalx/common/phrases.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
_phrase_book = {}


# TODO: It seems to be superseded by the pretalx.common.text.phrases module.
class PhrasesMetaClass(ABCMeta): # noqa
def __new__(cls, class_name, bases, namespace, app):
new = super().__new__(cls, class_name, bases, namespace)
Expand Down
26 changes: 20 additions & 6 deletions src/pretalx/common/settings/config.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
import configparser
import logging
import os
import sys
from configparser import RawConfigParser
from pathlib import Path

logger = logging.getLogger(__name__)


CONFIG = {
"filesystem": {
"base": {
Expand Down Expand Up @@ -157,10 +162,19 @@
}


def read_config_files(config):
if "PRETALX_CONFIG_FILE" in os.environ:
with open(os.environ.get("PRETALX_CONFIG_FILE"), encoding="utf-8") as fp:
config_files = config.read_file(fp)
def read_config_files(config: RawConfigParser) -> tuple[RawConfigParser, list[str]]:
if path_from_env := os.getenv("PRETALX_CONFIG_FILE"):
file_path = Path(path_from_env)
if file_path.exists():
with file_path.open(encoding="utf-8") as fp:
config.read_file(fp)
config_files = [str(file_path.resolve())]
else:
logger.warning(
"File specified by PRETALX_CONFIG_FILE does not exist. %s",
path_from_env,
)
config_files = []
else:
config_files = config.read(
[
Expand All @@ -185,7 +199,7 @@ def reduce_dict(data):
}


def read_layer(layer_name, config):
def read_layer(layer_name: str, config: RawConfigParser) -> RawConfigParser:
config_dict = reduce_dict(
{
section_name: {
Expand All @@ -198,7 +212,7 @@ def read_layer(layer_name, config):
return config


def build_config():
def build_config() -> tuple[RawConfigParser, list[str]]:
config = configparser.RawConfigParser()
config = read_layer("default", config)
config, config_files = read_config_files(config)
Expand Down
4 changes: 2 additions & 2 deletions src/pretalx/common/templates/common/auth.html
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
<div class="panel panel-default">
<div class="panel-heading text-center" id="headingOne">
<a class="btn btn-lg btn-primary btn-block mt-3" href="{% oauth_login_url next_url %}">
{% translate "Login with SSO" %}
{{ login_button_label }}
</a>
</div>
</div>
Expand All @@ -38,7 +38,7 @@
<div class="panel panel-default">
<div class="panel-heading text-center" id="headingTwo">
<a class="btn btn-lg btn-primary btn-block mt-3" href="{% register_account_url next_url %}">
{% translate "Register Speaker Account" %}
{{ _('Register account') }}
</a>
</div>
</div>
Expand Down
2 changes: 1 addition & 1 deletion src/pretalx/common/templates/common/availabilities.html
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
{% endcompress %}

{% with html_locale|slice:":2" as calendar_locale %}
{% if calendar_locale and calendar_locale != "en" %}
{% if calendar_locale and calendar_locale in AVAILABLE_CALENDAR_LOCALES %}
<script defer id="calendar-locale" data-locale="{{ calendar_locale }}" src="{% static "vendored/fullcalendar/"|add:calendar_locale|add:".js" %}"></script>
{% endif %}
{% endwith %}
2 changes: 1 addition & 1 deletion src/pretalx/common/templates/common/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ <h1>
</form>
</div>
</details>
{% elif not is_html_export %}
{% elif not subheader_login_link_disabled and not is_html_export %}
{% if request.event %}
<a href="{{ request.event.urls.login }}?next={{ request.path|urlencode }}">login</a>
{% else %}
Expand Down
9 changes: 9 additions & 0 deletions src/pretalx/common/text/phrases.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ def __init__(cls, *args, app, **kwargs):
super().__init__(*args, **kwargs)


# TODO: This utility seems to be for caching text. If so, we should use https://pypi.org/project/moka-py/
# to have proper type support.
class Phrases(metaclass=PhrasesMetaClass, app=""):
def __getattribute__(self, attribute):
result = super().__getattribute__(attribute)
Expand Down Expand Up @@ -102,3 +104,10 @@ class BasePhrases(Phrases, app="base"):
general = _("General")
email_subject = pgettext_lazy("email subject", "Subject")
text_body = _("Text")


# We want to show different button label depending on deployment site.
CALL_FOR_SPEAKER_LOGIN_BTN_LABELS = {
"default": _("Login"),
"mediawiki": _("Login with MediaWiki SSO or Email"),
}
Loading