Add admin email test page #388

This commit is contained in:
Daniel Grams 2023-03-24 21:45:34 +01:00
parent a78932d81c
commit 5178e73843
23 changed files with 472 additions and 140 deletions

View File

@ -1,6 +1,7 @@
[run]
omit =
project/celery.py
project/base_tasks.py
project/celery_tasks.py
project/cli/test.py
project/templates/email/*

View File

@ -1,4 +1,4 @@
# Open Event Database
# EventCally - Open event calendar
![Tests](https://github.com/eventcally/eventcally/workflows/Tests/badge.svg) [![codecov](https://codecov.io/gh/eventcally/eventcally/branch/main/graph/badge.svg?token=66CLLWWV7Y)](https://codecov.io/gh/eventcally/eventcally) [![Cypress](https://img.shields.io/endpoint?url=https://dashboard.cypress.io/badge/simple/32g194/main&style=flat&logo=cypress)](https://dashboard.cypress.io/projects/32g194/runs) [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black) [![Docker Pulls](https://img.shields.io/docker/pulls/eventcally/eventcally)](https://hub.docker.com/r/eventcally/eventcally)

View File

@ -24,6 +24,7 @@ x-web-env:
JWT_PRIVATE_KEY: ${JWT_PRIVATE_KEY}
JWT_PUBLIC_JWKS: ${JWT_PUBLIC_JWKS}
DOCS_URL: ${DOCS_URL}
SITE_NAME: ${SITE_NAME}
x-web:
&default-web

View File

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2023-03-16 19:11+0100\n"
"POT-Creation-Date: 2023-03-24 21:24+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -198,93 +198,101 @@ msgstr ""
msgid "You have received an invitation"
msgstr ""
#: project/forms/admin.py:10 project/templates/layout.html:294
#: project/views/root.py:57
#: project/forms/admin.py:11 project/templates/layout.html:294
#: project/views/root.py:53
msgid "Terms of service"
msgstr ""
#: project/forms/admin.py:11 project/templates/layout.html:298
#: project/views/root.py:65
#: project/forms/admin.py:12 project/templates/layout.html:298
#: project/views/root.py:61
msgid "Legal notice"
msgstr ""
#: project/forms/admin.py:12 project/templates/_macros.html:1395
#: project/forms/admin.py:13 project/templates/_macros.html:1395
#: project/templates/layout.html:302
#: project/templates/widget/event_suggestion/create.html:204
#: project/views/admin_unit.py:73 project/views/root.py:73
#: project/views/admin_unit.py:73 project/views/root.py:69
msgid "Contact"
msgstr ""
#: project/forms/admin.py:13 project/templates/layout.html:306
#: project/views/root.py:81
#: project/forms/admin.py:14 project/templates/layout.html:306
#: project/views/root.py:77
msgid "Privacy"
msgstr ""
#: project/forms/admin.py:14
#: project/forms/admin.py:15
msgid "Start page"
msgstr ""
#: project/forms/admin.py:16 project/forms/oauth2_client.py:24
#: project/forms/admin.py:17 project/forms/oauth2_client.py:24
msgid "Save"
msgstr ""
#: project/forms/admin.py:20 project/forms/admin_unit_member.py:12
#: project/forms/admin.py:21 project/forms/admin_unit_member.py:12
#: project/forms/admin_unit_member.py:32
msgid "Roles"
msgstr ""
#: project/forms/admin.py:21 project/templates/admin/update_user.html:4
#: project/forms/admin.py:22 project/templates/admin/update_user.html:4
#: project/templates/admin/update_user.html:8
msgid "Update user"
msgstr ""
#: project/forms/admin.py:26
#: project/forms/admin.py:27
msgid "Incoming reference requests allowed"
msgstr ""
#: project/forms/admin.py:27
#: project/forms/admin.py:28
msgid ""
"If set, other organizations can ask this organization to reference their "
"event."
msgstr ""
#: project/forms/admin.py:33
#: project/forms/admin.py:34
msgid "Suggestions enabled"
msgstr ""
#: project/forms/admin.py:34
#: project/forms/admin.py:35
msgid "If set, the organization can work with suggestions."
msgstr ""
#: project/forms/admin.py:38
#: project/forms/admin.py:39
msgid "Create other organizations"
msgstr ""
#: project/forms/admin.py:39
#: project/forms/admin.py:40
msgid "If set, members of the organization can create other organizations."
msgstr ""
#: project/forms/admin.py:45
#: project/forms/admin.py:46
msgid "Invite other organizations"
msgstr ""
#: project/forms/admin.py:46
#: project/forms/admin.py:47
msgid "If set, members of the organization can invite other organizations."
msgstr ""
#: project/forms/admin.py:52
#: project/forms/admin.py:53
msgid "Verify other organizations"
msgstr ""
#: project/forms/admin.py:53
#: project/forms/admin.py:54
msgid "If set, members of the organization can verify other organizations."
msgstr ""
#: project/forms/admin.py:58 project/templates/admin/update_admin_unit.html:4
#: project/forms/admin.py:59 project/templates/admin/update_admin_unit.html:4
#: project/templates/admin/update_admin_unit.html:8
msgid "Update organization"
msgstr ""
#: project/forms/admin.py:63
msgid "Recipient"
msgstr ""
#: project/forms/admin.py:65
msgid "Send test mail synchronously"
msgstr ""
#: project/forms/admin_unit.py:15 project/forms/event_place.py:12
#: project/forms/organizer.py:12
msgid "Street"
@ -348,7 +356,8 @@ msgstr ""
#: project/forms/admin_unit_member.py:23 project/forms/admin_unit_member.py:28
#: project/forms/event.py:107 project/forms/event_suggestion.py:38
#: project/forms/organizer.py:27 project/templates/_macros.html:235
#: project/templates/_macros.html:1491 project/templates/admin/users.html:19
#: project/templates/_macros.html:1491 project/templates/admin/admin.html:27
#: project/templates/admin/users.html:19
msgid "Email"
msgstr ""
@ -1365,15 +1374,10 @@ msgstr ""
msgid "Enter list name"
msgstr ""
#: project/templates/home.html:27
#: project/templates/home.html:24
msgid "Manage"
msgstr ""
#: project/templates/home.html:29 project/templates/security/login_user.html:38
#: project/views/widget.py:159
msgid "Register for free"
msgstr ""
#: project/templates/layout.html:152 project/templates/layout.html:200
#: project/templates/manage/events.html:6
#: project/templates/manage/events.html:42
@ -1409,6 +1413,8 @@ msgstr ""
#: project/templates/admin/admin.html:3 project/templates/admin/admin.html:9
#: project/templates/admin/admin_units.html:10
#: project/templates/admin/email.html:65
#: project/templates/admin/settings.html:10
#: project/templates/admin/users.html:10 project/templates/layout.html:171
msgid "Admin"
msgstr ""
@ -1495,9 +1501,10 @@ msgstr ""
msgid "Organization invitations"
msgstr ""
#: project/templates/admin/admin.html:15
#: project/templates/admin/admin.html:15 project/templates/admin/email.html:4
#: project/templates/admin/email.html:66
#: project/templates/admin/settings.html:4
#: project/templates/admin/settings.html:8
#: project/templates/admin/settings.html:11
#: project/templates/admin_unit/update.html:6
#: project/templates/admin_unit/update.html:23
#: project/templates/layout.html:253 project/templates/manage/widgets.html:11
@ -1553,6 +1560,18 @@ msgstr ""
msgid "Edit"
msgstr ""
#: project/templates/admin/email.html:47 project/views/admin.py:119
msgid "Mail sent successfully"
msgstr ""
#: project/templates/admin/email.html:103
msgid "Test mail"
msgstr ""
#: project/templates/admin/email.html:111
msgid "Send test mail asynchronously"
msgstr ""
#: project/templates/admin_unit/create.html:58
#: project/templates/admin_unit/update.html:59
#: project/templates/event/create.html:347
@ -1665,6 +1684,14 @@ msgstr ""
msgid "The review status of your event has been updated."
msgstr ""
#: project/templates/email/test_email.html:4
msgid "This is a test mail"
msgstr ""
#: project/templates/email/test_email.html:5
msgid "Click here to open the site"
msgstr ""
#: project/templates/event/actions.html:5
#: project/templates/event/actions.html:22
msgid "Actions for event"
@ -1984,6 +2011,10 @@ msgstr ""
msgid "You do not have an account yet? Not a problem!"
msgstr ""
#: project/templates/security/login_user.html:38 project/views/widget.py:159
msgid "Register for free"
msgstr ""
#: project/templates/widget/event_date/list.html:5
msgid "Widget"
msgstr ""
@ -2004,15 +2035,20 @@ msgstr ""
msgid "Preview"
msgstr ""
#: project/views/admin.py:44
#: project/views/admin.py:55
msgid "Organization successfully updated"
msgstr ""
#: project/views/admin.py:68 project/views/manage.py:361
#: project/views/admin.py:79 project/views/manage.py:361
msgid "Settings successfully updated"
msgstr ""
#: project/views/admin.py:103
#: project/views/admin.py:108
#, python-format
msgid "Test mail from %(site_name)s"
msgstr ""
#: project/views/admin.py:152
msgid "User successfully updated"
msgstr ""

View File

@ -16,10 +16,18 @@ from flask_wtf.csrf import CSRFProtect
from project.custom_session_interface import CustomSessionInterface
def getenv_bool(name: str, default: str = "False"): # pragma: no cover
def getenv_bool(name: str, default: str = "False"):
return os.getenv(name, default).lower() in ("true", "1", "t")
def set_env_to_app(app: Flask, key: str, default: str = None):
if key in os.environ and os.environ[key]: # pragma: no cover
app.config[key] = os.environ[key]
if default:
app.config[key] = default
# Create app
app = Flask(__name__)
app.config["SQLALCHEMY_DATABASE_URI"] = os.environ["DATABASE_URL"]
@ -34,7 +42,6 @@ app.config["SECURITY_RECOVERABLE"] = True
app.config["SECURITY_CHANGEABLE"] = True
app.config["SECURITY_EMAIL_SENDER"] = os.getenv("MAIL_DEFAULT_SENDER")
app.config["LANGUAGES"] = ["en", "de"]
app.config["SITE_NAME"] = os.getenv("SITE_NAME", "eventcally")
app.config["SERVER_NAME"] = os.getenv("SERVER_NAME")
app.config["DOCS_URL"] = os.getenv("DOCS_URL")
app.config["ADMIN_UNIT_CREATE_REQUIRES_ADMIN"] = os.getenv(
@ -42,6 +49,7 @@ app.config["ADMIN_UNIT_CREATE_REQUIRES_ADMIN"] = os.getenv(
)
app.config["SEO_SITEMAP_PING_GOOGLE"] = getenv_bool("SEO_SITEMAP_PING_GOOGLE", "False")
app.config["GOOGLE_MAPS_API_KEY"] = os.getenv("GOOGLE_MAPS_API_KEY")
set_env_to_app(app, "SITE_NAME", "EventCally")
# Proxy handling
if os.getenv("PREFERRED_URL_SCHEME"): # pragma: no cover
@ -58,11 +66,8 @@ app.config.update(
"broker_url": app.config["REDIS_URL"],
"result_backend": app.config["REDIS_URL"],
"result_expires": timedelta(hours=1),
"broker_pool_limit": None,
"redis_max_connections": 2,
"timezone": "Europe/Berlin",
"broker_transport_options": {
"max_connections": 2,
"queue_order_strategy": "priority",
"priority_steps": list(range(3)),
"sep": ":",

10
project/base_tasks.py Normal file
View File

@ -0,0 +1,10 @@
from project import app, celery
from project.views.utils import send_mail
@celery.task(
base=getattr(app, "celery_http_task_cls"),
priority=0,
)
def send_mail_task(recipient, subject, template):
send_mail(recipient, subject, template)

View File

@ -2,13 +2,8 @@ from smtplib import SMTPException
from urllib.error import URLError
from celery import Celery
from celery.signals import (
after_setup_logger,
after_setup_task_logger,
task_postrun,
worker_ready,
)
from celery_singleton import Singleton, clear_locks
from celery import Task as BaseTask
from celery.signals import after_setup_logger, after_setup_task_logger, task_postrun
from requests.exceptions import RequestException
@ -19,7 +14,7 @@ class HttpTaskException(Exception):
def create_celery(app):
celery = Celery(app.import_name)
celery.conf.update(app.config["CELERY_CONFIG"])
TaskBase = Singleton
TaskBase = BaseTask
class ContextTask(TaskBase):
abstract = True
@ -71,13 +66,6 @@ def setup_task_logger(logger, *args, **kwargs):
init_logger_with_one_line_formatter(logger)
@worker_ready.connect
def unlock_all(**kwargs):
from project import celery
clear_locks(celery)
@task_postrun.connect
def close_session(*args, **kwargs):
from project import app

View File

@ -1,7 +1,8 @@
from flask_babelex import lazy_gettext
from flask_wtf import FlaskForm
from wtforms import BooleanField, SubmitField, TextAreaField
from wtforms.validators import Optional
from wtforms.fields.html5 import EmailField
from wtforms.validators import DataRequired, Optional
from project.forms.widgets import MultiCheckboxField
@ -56,3 +57,9 @@ class UpdateAdminUnitForm(FlaskForm):
validators=[Optional()],
)
submit = SubmitField(lazy_gettext("Update organization"))
class AdminTestEmailForm(FlaskForm):
recipient = EmailField(lazy_gettext("Recipient"), validators=[DataRequired()])
submit = SubmitField(lazy_gettext("Send test mail synchronously"))

View File

@ -26,6 +26,9 @@ def any_dict_value_true(data: dict):
def ensure_link_scheme(link: str):
if not link: # pragma: no cover
return link
if link.startswith("http://") or link.startswith("https://"):
return link

View File

@ -23,6 +23,10 @@
{{ _('Users') }}
<i class="fa fa-caret-right"></i>
</a>
<a href="{{ url_for('admin_email') }}" class="list-group-item">
{{ _('Email') }}
<i class="fa fa-caret-right"></i>
</a>
</div>
{% endblock %}

View File

@ -0,0 +1,124 @@
{% extends "layout.html" %}
{% from "_macros.html" import render_field, render_field_with_errors %}
{%- block title -%}
{{ _('Settings') }}
{%- endblock -%}
{% block header %}
<script>
function submit_async() {
handle_request_start();
$.ajax({
url: "{{ url_for('admin_email', async=1) }}",
type: "post",
dataType: "json",
data: $("#test_mail_form").serialize(),
error: function(xhr, status, error) {
handle_request_error(xhr, status, error);
},
success: function (data) {
poll(data["result_id"]);
}
});
}
function poll(result_id) {
$.ajax({
url: "{{ url_for('admin_email') }}",
type: "get",
dataType: "json",
data: "poll=" + result_id,
error: function(xhr, status, error) {
handle_request_error(xhr, status, error);
},
success: function (data) {
if (!data["ready"]) {
setTimeout(function() {
poll(result_id);
}, 500);
return;
}
if (!data["successful"]) {
console.error(data);
handle_request_error(null, JSON.stringify(data), data);
return;
}
$("#result_container").text("{{ _('Mail sent successfully') }}");
handle_request_success();
}
});
}
$( function() {
$("#submit_async").click(function(){
submit_async();
return false;
});
});
</script>
{% endblock %}
{% block content %}
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item"><a href="{{ url_for('admin') }}">{{ _('Admin') }}</a></li>
<li class="breadcrumb-item active" aria-current="page">{{ _('Settings') }}</li>
</ol>
</nav>
<table class="table table-striped table-bordered my-4">
<tbody>
<tr>
<td>MAIL_SUPPRESS_SEND</td>
<td>{{ config["MAIL_SUPPRESS_SEND"] }}</td>
</tr>
<tr>
<td>MAIL_SERVER</td>
<td>{{ config["MAIL_SERVER"] }}</td>
</tr>
<tr>
<td>MAIL_PORT</td>
<td>{{ config["MAIL_PORT"] }}</td>
</tr>
<tr>
<td>MAIL_USE_TLS</td>
<td>{{ config["MAIL_USE_TLS"] }}</td>
</tr>
<tr>
<td>MAIL_USE_SSL</td>
<td>{{ config["MAIL_USE_SSL"] }}</td>
</tr>
<tr>
<td>MAIL_USERNAME</td>
<td>{{ config["MAIL_USERNAME"] }}</td>
</tr>
<tr>
<td>MAIL_PASSWORD</td>
<td>{{ config["MAIL_PASSWORD"] }}</td>
</tr>
</tbody>
</table>
<h4>{{ _('Test mail')}} </h4>
<form id="test_mail_form" action="" method="POST">
{{ form.hidden_tag() }}
{{ render_field_with_errors(form.recipient) }}
{{ render_field(form.submit) }}
</form>
<p>
<button id="submit_async" type="button" class="btn btn-outline-primary">{{ _('Send test mail asynchronously') }}</button>
<div class="col-md">
<div id="result_container">
</div>
<div class="spinner-border m-3" role="status" id="spinner" style="display: none;">
<span class="sr-only">Loading&hellip;</span>
</div>
<div class="alert alert-danger m-3" role="alert" id="error_alert" style="display: none;"></div>
</div>
</p>
{% endblock %}

View File

@ -5,7 +5,12 @@
{%- endblock -%}
{% block content %}
<h1>{{ _('Settings') }}</h1>
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item"><a href="{{ url_for('admin') }}">{{ _('Admin') }}</a></li>
<li class="breadcrumb-item active" aria-current="page">{{ _('Settings') }}</li>
</ol>
</nav>
<form action="" method="POST">
{{ form.hidden_tag() }}

View File

@ -0,0 +1,6 @@
{% extends "email/layout.html" %}
{% from "_macros.html" import render_email_button %}
{% block content %}
<p>{{ _('This is a test mail') }}</p>
{{ render_email_button(url_for('home', _external=True), _('Click here to open the site')) }}
{% endblock %}

View File

@ -0,0 +1,3 @@
{{ _('This is a test mail') }}
{{ _('Click the link below to open the site') }}
{{ url_for('home', _external=True) }}

View File

@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2023-03-16 19:11+0100\n"
"POT-Creation-Date: 2023-03-24 21:24+0100\n"
"PO-Revision-Date: 2020-06-07 18:51+0200\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language: de\n"
@ -199,51 +199,51 @@ msgstr "message"
msgid "You have received an invitation"
msgstr "Du hast eine Einladung erhalten"
#: project/forms/admin.py:10 project/templates/layout.html:294
#: project/views/root.py:57
#: project/forms/admin.py:11 project/templates/layout.html:294
#: project/views/root.py:53
msgid "Terms of service"
msgstr "Nutzungsbedingungen"
#: project/forms/admin.py:11 project/templates/layout.html:298
#: project/views/root.py:65
#: project/forms/admin.py:12 project/templates/layout.html:298
#: project/views/root.py:61
msgid "Legal notice"
msgstr "Impressum"
#: project/forms/admin.py:12 project/templates/_macros.html:1395
#: project/forms/admin.py:13 project/templates/_macros.html:1395
#: project/templates/layout.html:302
#: project/templates/widget/event_suggestion/create.html:204
#: project/views/admin_unit.py:73 project/views/root.py:73
#: project/views/admin_unit.py:73 project/views/root.py:69
msgid "Contact"
msgstr "Kontakt"
#: project/forms/admin.py:13 project/templates/layout.html:306
#: project/views/root.py:81
#: project/forms/admin.py:14 project/templates/layout.html:306
#: project/views/root.py:77
msgid "Privacy"
msgstr "Datenschutz"
#: project/forms/admin.py:14
#: project/forms/admin.py:15
msgid "Start page"
msgstr "Startseite"
#: project/forms/admin.py:16 project/forms/oauth2_client.py:24
#: project/forms/admin.py:17 project/forms/oauth2_client.py:24
msgid "Save"
msgstr "Speichern"
#: project/forms/admin.py:20 project/forms/admin_unit_member.py:12
#: project/forms/admin.py:21 project/forms/admin_unit_member.py:12
#: project/forms/admin_unit_member.py:32
msgid "Roles"
msgstr "Rollen"
#: project/forms/admin.py:21 project/templates/admin/update_user.html:4
#: project/forms/admin.py:22 project/templates/admin/update_user.html:4
#: project/templates/admin/update_user.html:8
msgid "Update user"
msgstr "Nutzer aktualisieren"
#: project/forms/admin.py:26
#: project/forms/admin.py:27
msgid "Incoming reference requests allowed"
msgstr "Eingehende Empfehlungsanfragen erlauben"
#: project/forms/admin.py:27
#: project/forms/admin.py:28
msgid ""
"If set, other organizations can ask this organization to reference their "
"event."
@ -251,49 +251,57 @@ msgstr ""
"Wenn gesetzt, können andere Organisationen diese Organisation bitten, "
"deren Veranstaltungen zu empfehlen."
#: project/forms/admin.py:33
#: project/forms/admin.py:34
msgid "Suggestions enabled"
msgstr "Vorschläge aktiv"
#: project/forms/admin.py:34
#: project/forms/admin.py:35
msgid "If set, the organization can work with suggestions."
msgstr "Wenn gesetzt, kann die Organisation mit Vorschlägen arbeiten."
#: project/forms/admin.py:38
#: project/forms/admin.py:39
msgid "Create other organizations"
msgstr "Andere Organisationen erstellen"
#: project/forms/admin.py:39
#: project/forms/admin.py:40
msgid "If set, members of the organization can create other organizations."
msgstr ""
"Wenn gesetzt, können Mitglieder der Organisation andere Organisationen "
"erstellen."
#: project/forms/admin.py:45
#: project/forms/admin.py:46
msgid "Invite other organizations"
msgstr "Andere Organisationen einladen"
#: project/forms/admin.py:46
#: project/forms/admin.py:47
msgid "If set, members of the organization can invite other organizations."
msgstr ""
"Wenn gesetzt, können Mitglieder der Organisation andere Organisationen "
"einladen."
#: project/forms/admin.py:52
#: project/forms/admin.py:53
msgid "Verify other organizations"
msgstr "Andere Organisationen verifizieren"
#: project/forms/admin.py:53
#: project/forms/admin.py:54
msgid "If set, members of the organization can verify other organizations."
msgstr ""
"Wenn gesetzt, können Mitglieder der Organisation andere Organisationen "
"verifizieren."
#: project/forms/admin.py:58 project/templates/admin/update_admin_unit.html:4
#: project/forms/admin.py:59 project/templates/admin/update_admin_unit.html:4
#: project/templates/admin/update_admin_unit.html:8
msgid "Update organization"
msgstr "Organisation aktualisieren"
#: project/forms/admin.py:63
msgid "Recipient"
msgstr "Empfänger"
#: project/forms/admin.py:65
msgid "Send test mail synchronously"
msgstr "Test-Mail synchron senden"
#: project/forms/admin_unit.py:15 project/forms/event_place.py:12
#: project/forms/organizer.py:12
msgid "Street"
@ -360,7 +368,8 @@ msgstr "Link URL"
#: project/forms/admin_unit_member.py:23 project/forms/admin_unit_member.py:28
#: project/forms/event.py:107 project/forms/event_suggestion.py:38
#: project/forms/organizer.py:27 project/templates/_macros.html:235
#: project/templates/_macros.html:1491 project/templates/admin/users.html:19
#: project/templates/_macros.html:1491 project/templates/admin/admin.html:27
#: project/templates/admin/users.html:19
msgid "Email"
msgstr "Email"
@ -1415,15 +1424,10 @@ msgstr "Veranstalter eingeben"
msgid "Enter list name"
msgstr "Listenname eingeben"
#: project/templates/home.html:27
#: project/templates/home.html:24
msgid "Manage"
msgstr "Verwaltung"
#: project/templates/home.html:29 project/templates/security/login_user.html:38
#: project/views/widget.py:159
msgid "Register for free"
msgstr "Kostenlos registrieren"
#: project/templates/layout.html:152 project/templates/layout.html:200
#: project/templates/manage/events.html:6
#: project/templates/manage/events.html:42
@ -1459,6 +1463,8 @@ msgstr "Profil"
#: project/templates/admin/admin.html:3 project/templates/admin/admin.html:9
#: project/templates/admin/admin_units.html:10
#: project/templates/admin/email.html:65
#: project/templates/admin/settings.html:10
#: project/templates/admin/users.html:10 project/templates/layout.html:171
msgid "Admin"
msgstr "Administration"
@ -1545,9 +1551,10 @@ msgstr "Beziehungen"
msgid "Organization invitations"
msgstr "Organisationseinladungen"
#: project/templates/admin/admin.html:15
#: project/templates/admin/admin.html:15 project/templates/admin/email.html:4
#: project/templates/admin/email.html:66
#: project/templates/admin/settings.html:4
#: project/templates/admin/settings.html:8
#: project/templates/admin/settings.html:11
#: project/templates/admin_unit/update.html:6
#: project/templates/admin_unit/update.html:23
#: project/templates/layout.html:253 project/templates/manage/widgets.html:11
@ -1603,6 +1610,18 @@ msgstr "Benutzer"
msgid "Edit"
msgstr "Bearbeiten"
#: project/templates/admin/email.html:47 project/views/admin.py:119
msgid "Mail sent successfully"
msgstr "Mail erfolgreich gesendet"
#: project/templates/admin/email.html:103
msgid "Test mail"
msgstr "Test-Mail"
#: project/templates/admin/email.html:111
msgid "Send test mail asynchronously"
msgstr "Test-Mail asynchron senden"
#: project/templates/admin_unit/create.html:58
#: project/templates/admin_unit/update.html:59
#: project/templates/event/create.html:347
@ -1717,6 +1736,14 @@ msgstr "Klicke hier, um den Vorschlag zu prüfen"
msgid "The review status of your event has been updated."
msgstr "Der Prüfungsstatus deiner Veranstaltung wurde aktualisiert"
#: project/templates/email/test_email.html:4
msgid "This is a test mail"
msgstr "Das ist eine Test-Mail"
#: project/templates/email/test_email.html:5
msgid "Click here to open the site"
msgstr "Klicke hier, um die Seite zu öffnen"
#: project/templates/event/actions.html:5
#: project/templates/event/actions.html:22
msgid "Actions for event"
@ -2045,6 +2072,10 @@ msgstr "Angemeldet bleiben"
msgid "You do not have an account yet? Not a problem!"
msgstr "Du hast noch keinen Account? Kein Problem!"
#: project/templates/security/login_user.html:38 project/views/widget.py:159
msgid "Register for free"
msgstr "Kostenlos registrieren"
#: project/templates/widget/event_date/list.html:5
msgid "Widget"
msgstr "Widget"
@ -2065,15 +2096,20 @@ msgstr "Optionale Details"
msgid "Preview"
msgstr "Vorschau"
#: project/views/admin.py:44
#: project/views/admin.py:55
msgid "Organization successfully updated"
msgstr "Organisation erfolgreich aktualisiert"
#: project/views/admin.py:68 project/views/manage.py:361
#: project/views/admin.py:79 project/views/manage.py:361
msgid "Settings successfully updated"
msgstr "Einstellungen erfolgreich aktualisiert"
#: project/views/admin.py:103
#: project/views/admin.py:108
#, python-format
msgid "Test mail from %(site_name)s"
msgstr "Test-Mail from %(site_name)s"
#: project/views/admin.py:152
msgid "User successfully updated"
msgstr "Nutzer erfolgreich aktualisiert"

View File

@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2023-03-16 19:11+0100\n"
"POT-Creation-Date: 2023-03-24 21:24+0100\n"
"PO-Revision-Date: 2021-04-30 15:04+0200\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language: en\n"
@ -199,93 +199,101 @@ msgstr ""
msgid "You have received an invitation"
msgstr ""
#: project/forms/admin.py:10 project/templates/layout.html:294
#: project/views/root.py:57
#: project/forms/admin.py:11 project/templates/layout.html:294
#: project/views/root.py:53
msgid "Terms of service"
msgstr ""
#: project/forms/admin.py:11 project/templates/layout.html:298
#: project/views/root.py:65
#: project/forms/admin.py:12 project/templates/layout.html:298
#: project/views/root.py:61
msgid "Legal notice"
msgstr ""
#: project/forms/admin.py:12 project/templates/_macros.html:1395
#: project/forms/admin.py:13 project/templates/_macros.html:1395
#: project/templates/layout.html:302
#: project/templates/widget/event_suggestion/create.html:204
#: project/views/admin_unit.py:73 project/views/root.py:73
#: project/views/admin_unit.py:73 project/views/root.py:69
msgid "Contact"
msgstr ""
#: project/forms/admin.py:13 project/templates/layout.html:306
#: project/views/root.py:81
#: project/forms/admin.py:14 project/templates/layout.html:306
#: project/views/root.py:77
msgid "Privacy"
msgstr ""
#: project/forms/admin.py:14
#: project/forms/admin.py:15
msgid "Start page"
msgstr ""
#: project/forms/admin.py:16 project/forms/oauth2_client.py:24
#: project/forms/admin.py:17 project/forms/oauth2_client.py:24
msgid "Save"
msgstr ""
#: project/forms/admin.py:20 project/forms/admin_unit_member.py:12
#: project/forms/admin.py:21 project/forms/admin_unit_member.py:12
#: project/forms/admin_unit_member.py:32
msgid "Roles"
msgstr ""
#: project/forms/admin.py:21 project/templates/admin/update_user.html:4
#: project/forms/admin.py:22 project/templates/admin/update_user.html:4
#: project/templates/admin/update_user.html:8
msgid "Update user"
msgstr ""
#: project/forms/admin.py:26
#: project/forms/admin.py:27
msgid "Incoming reference requests allowed"
msgstr ""
#: project/forms/admin.py:27
#: project/forms/admin.py:28
msgid ""
"If set, other organizations can ask this organization to reference their "
"event."
msgstr ""
#: project/forms/admin.py:33
#: project/forms/admin.py:34
msgid "Suggestions enabled"
msgstr ""
#: project/forms/admin.py:34
#: project/forms/admin.py:35
msgid "If set, the organization can work with suggestions."
msgstr ""
#: project/forms/admin.py:38
#: project/forms/admin.py:39
msgid "Create other organizations"
msgstr ""
#: project/forms/admin.py:39
#: project/forms/admin.py:40
msgid "If set, members of the organization can create other organizations."
msgstr ""
#: project/forms/admin.py:45
#: project/forms/admin.py:46
msgid "Invite other organizations"
msgstr ""
#: project/forms/admin.py:46
#: project/forms/admin.py:47
msgid "If set, members of the organization can invite other organizations."
msgstr ""
#: project/forms/admin.py:52
#: project/forms/admin.py:53
msgid "Verify other organizations"
msgstr ""
#: project/forms/admin.py:53
#: project/forms/admin.py:54
msgid "If set, members of the organization can verify other organizations."
msgstr ""
#: project/forms/admin.py:58 project/templates/admin/update_admin_unit.html:4
#: project/forms/admin.py:59 project/templates/admin/update_admin_unit.html:4
#: project/templates/admin/update_admin_unit.html:8
msgid "Update organization"
msgstr ""
#: project/forms/admin.py:63
msgid "Recipient"
msgstr ""
#: project/forms/admin.py:65
msgid "Send test mail synchronously"
msgstr ""
#: project/forms/admin_unit.py:15 project/forms/event_place.py:12
#: project/forms/organizer.py:12
msgid "Street"
@ -349,7 +357,8 @@ msgstr ""
#: project/forms/admin_unit_member.py:23 project/forms/admin_unit_member.py:28
#: project/forms/event.py:107 project/forms/event_suggestion.py:38
#: project/forms/organizer.py:27 project/templates/_macros.html:235
#: project/templates/_macros.html:1491 project/templates/admin/users.html:19
#: project/templates/_macros.html:1491 project/templates/admin/admin.html:27
#: project/templates/admin/users.html:19
msgid "Email"
msgstr ""
@ -1366,15 +1375,10 @@ msgstr ""
msgid "Enter list name"
msgstr ""
#: project/templates/home.html:27
#: project/templates/home.html:24
msgid "Manage"
msgstr ""
#: project/templates/home.html:29 project/templates/security/login_user.html:38
#: project/views/widget.py:159
msgid "Register for free"
msgstr ""
#: project/templates/layout.html:152 project/templates/layout.html:200
#: project/templates/manage/events.html:6
#: project/templates/manage/events.html:42
@ -1410,6 +1414,8 @@ msgstr ""
#: project/templates/admin/admin.html:3 project/templates/admin/admin.html:9
#: project/templates/admin/admin_units.html:10
#: project/templates/admin/email.html:65
#: project/templates/admin/settings.html:10
#: project/templates/admin/users.html:10 project/templates/layout.html:171
msgid "Admin"
msgstr ""
@ -1496,9 +1502,10 @@ msgstr ""
msgid "Organization invitations"
msgstr ""
#: project/templates/admin/admin.html:15
#: project/templates/admin/admin.html:15 project/templates/admin/email.html:4
#: project/templates/admin/email.html:66
#: project/templates/admin/settings.html:4
#: project/templates/admin/settings.html:8
#: project/templates/admin/settings.html:11
#: project/templates/admin_unit/update.html:6
#: project/templates/admin_unit/update.html:23
#: project/templates/layout.html:253 project/templates/manage/widgets.html:11
@ -1554,6 +1561,18 @@ msgstr ""
msgid "Edit"
msgstr ""
#: project/templates/admin/email.html:47 project/views/admin.py:119
msgid "Mail sent successfully"
msgstr ""
#: project/templates/admin/email.html:103
msgid "Test mail"
msgstr ""
#: project/templates/admin/email.html:111
msgid "Send test mail asynchronously"
msgstr ""
#: project/templates/admin_unit/create.html:58
#: project/templates/admin_unit/update.html:59
#: project/templates/event/create.html:347
@ -1666,6 +1685,14 @@ msgstr ""
msgid "The review status of your event has been updated."
msgstr ""
#: project/templates/email/test_email.html:4
msgid "This is a test mail"
msgstr ""
#: project/templates/email/test_email.html:5
msgid "Click here to open the site"
msgstr ""
#: project/templates/event/actions.html:5
#: project/templates/event/actions.html:22
msgid "Actions for event"
@ -1985,6 +2012,10 @@ msgstr ""
msgid "You do not have an account yet? Not a problem!"
msgstr ""
#: project/templates/security/login_user.html:38 project/views/widget.py:159
msgid "Register for free"
msgstr ""
#: project/templates/widget/event_date/list.html:5
msgid "Widget"
msgstr ""
@ -2005,15 +2036,20 @@ msgstr ""
msgid "Preview"
msgstr ""
#: project/views/admin.py:44
#: project/views/admin.py:55
msgid "Organization successfully updated"
msgstr ""
#: project/views/admin.py:68 project/views/manage.py:361
#: project/views/admin.py:79 project/views/manage.py:361
msgid "Settings successfully updated"
msgstr ""
#: project/views/admin.py:103
#: project/views/admin.py:108
#, python-format
msgid "Test mail from %(site_name)s"
msgstr ""
#: project/views/admin.py:152
msgid "User successfully updated"
msgstr ""

View File

@ -1,15 +1,26 @@
from flask import flash, redirect, render_template, url_for
from flask import flash, redirect, render_template, request, url_for
from flask_babelex import gettext
from flask_security import roles_required
from sqlalchemy.exc import SQLAlchemyError
from sqlalchemy.sql import func
from project import app, db
from project.forms.admin import AdminSettingsForm, UpdateAdminUnitForm, UpdateUserForm
from project import app, celery, db
from project.base_tasks import send_mail_task
from project.forms.admin import (
AdminSettingsForm,
AdminTestEmailForm,
UpdateAdminUnitForm,
UpdateUserForm,
)
from project.models import AdminUnit, Role, User
from project.services.admin import upsert_settings
from project.services.user import set_roles_for_user
from project.views.utils import flash_errors, get_pagination_urls, handleSqlError
from project.views.utils import (
flash_errors,
get_pagination_urls,
handleSqlError,
send_mail,
)
@app.route("/admin")
@ -76,6 +87,44 @@ def admin_settings():
return render_template("admin/settings.html", form=form)
@app.route("/admin/email", methods=["GET", "POST"])
@roles_required("admin")
def admin_email():
form = AdminTestEmailForm()
if "poll" in request.args: # pragma: no cover
try:
result = celery.AsyncResult(request.args["poll"])
ready = result.ready()
return {
"ready": ready,
"successful": result.successful() if ready else None,
"value": result.get() if ready else result.result,
}
except Exception as e:
return {"ready": True, "successful": False, "error": str(e)}
if form.validate_on_submit():
subject = gettext(
"Test mail from %(site_name)s",
site_name=app.config["SITE_NAME"],
)
if "async" in request.args: # pragma: no cover
result = send_mail_task.delay(form.recipient.data, subject, "test_email")
return {"result_id": result.id}
try:
send_mail(form.recipient.data, subject, "test_email")
flash(gettext("Mail sent successfully"), "success")
except Exception as e: # pragma: no cover
flash(str(e), "danger")
else: # pragma: no cover
flash_errors(form)
return render_template("admin/email.html", form=form)
@app.route("/admin/users")
@roles_required("admin")
def admin_users():

View File

@ -27,7 +27,7 @@ def get_current_admin_unit(fallback=True):
if admin_unit:
return admin_unit
if current_user.is_authenticated:
if current_user and current_user.is_authenticated:
admin_unit = get_current_admin_unit_from_cookies()
if not admin_unit and fallback:
@ -44,7 +44,7 @@ def get_current_admin_unit(fallback=True):
def get_current_admin_unit_from_cookies():
try:
if "manage_admin_unit_id" in request.cookies:
if request and request.cookies and "manage_admin_unit_id" in request.cookies:
encoded = request.cookies.get("manage_admin_unit_id")
manage_admin_unit_id = int(decode_cookie(encoded))
return get_admin_unit_for_manage(manage_admin_unit_id)

View File

@ -17,7 +17,6 @@ black==23.1.0
blinker==1.4
cached-property==1.5.2
celery==5.2.7
celery-singleton==0.3.1
certifi==2020.12.5
cffi==1.14.4
cfgv==3.2.0
@ -121,7 +120,7 @@ TatSu==4.4.0
toml==0.10.2
tomli==2.0.1
typed-ast==1.5.4
typing_extensions==4.5.0
typing-extensions==4.5.0
urllib3==1.26.5
URLObject==2.4.3
validators==0.18.2

View File

@ -60,6 +60,25 @@ def test_admin_settings(client, seeder, utils, app, mocker, db_error):
assert settings.privacy == "Mein Datenschutz"
def test_admin_email(client, seeder, utils, app, mocker):
user_id, admin_unit_id = seeder.setup_base(True)
url = utils.get_url("admin_email")
response = utils.get_ok(url)
mail_mock = utils.mock_send_mails(mocker)
response = utils.post_form(
url,
response,
{
"recipient": "test@test.de",
},
)
utils.assert_response_ok(response)
utils.assert_send_mail_called(mail_mock, "test@test.de")
def test_admin_users(client, seeder, utils, app):
seeder.create_user(admin=True)
user = utils.login()

View File

@ -1,3 +1,3 @@
def test_index(client):
response = client.get("/")
assert b"eventcally" in response.data
assert b"EventCally" in response.data