admin: email debugging form

This commit is contained in:
Éloi Rivard 2021-12-23 19:21:29 +01:00
parent e415a4739e
commit d839dd763d
7 changed files with 124 additions and 52 deletions

View file

@ -1,20 +1,49 @@
from canaille.apputils import obj_to_b64
from canaille.flaskutils import permissions_needed
from canaille.mails import profile_hash
from canaille.mails import send_invitation_mail
from flask import Blueprint
from flask import current_app
from flask import flash
from flask import request
from flask import url_for
from flask_babel import gettext as _
from flask_themer import render_template
from flask_wtf import FlaskForm
from wtforms import StringField
from wtforms.validators import DataRequired
from wtforms.validators import Email
bp = Blueprint("admin_mails", __name__)
@bp.route("/")
class MailTestForm(FlaskForm):
mail = StringField(
_("Email"),
validators=[
DataRequired(),
Email(),
],
render_kw={
"placeholder": _("jane@doe.com"),
"spellcheck": "false",
"autocorrect": "off",
},
)
@bp.route("/", methods=["GET", "POST"])
@permissions_needed("manage_oidc")
def mail_index(user):
return render_template("admin/mails.html")
form = MailTestForm(request.form or None)
if request.form and form.validate():
if send_invitation_mail(form.mail.data, ""):
flash(_("The test invitation mail has been sent correctly"), "success")
else:
flash(_("The test invitation mail has been sent correctly"), "error")
return render_template("admin/mails.html", form=form)
@bp.route("/password-init.html")

View file

@ -1,15 +1,37 @@
{% extends theme('base.html') %}
{% import 'fomanticui.html' as sui %}
{% block content %}
<div class="ui attached segment">
<div class="ui segment">
<h2 class="ui center aligned header">
<div class="content">
{{ _("Test d'envoi") }}
</div>
</h2>
<div class="ui info message">
{% trans -%}
This form will a fake invitation email to the address you want.
This should be used for testing mail configuration.
{%- endtrans %}
</div>
{% call sui.render_form(form) %}
{{ sui.render_fields(form) }}
<div class="ui right aligned container">
<div class="ui stackable buttons">
<input type="submit" class="ui primary button" value="{{ _("Send") }}">
</div>
</div>
{% endcall %}
</div>
<div class="ui segment">
<h2 class="ui center aligned header">
<div class="content">
{{ _("Email preview") }}
</div>
</h2>
</div>
<div class="ui attached segment">
<div class="ui middle aligned divided list">
<div class="item">
<div class="right floated content">

View file

@ -9,8 +9,8 @@ indicator_text=none,
suffix_text=none,
display=true
) -%}
{% if container %}
{% set field_visible = field.type != 'HiddenField' and field.type !='CSRFTokenField' %}
{% if container and field_visible %}
<div class="field {{ kwargs.pop('class_', '') }}
{%- if field.errors %} error{% endif -%}
{%- if field.render_kw and "disabled" in field.render_kw %} disabled{% endif -%}"
@ -18,7 +18,7 @@ display=true
>
{% endif %}
{% if (field.type != 'HiddenField' and field.type !='CSRFTokenField') and label_visible %}
{% if field_visible and label_visible %}
{{ field.label() }}
{% if field.description %}
<div>{{ field.description }}</div>
@ -30,30 +30,32 @@ display=true
{% set required_indicator = "required" in field.flags %}
{% set corner_indicator = not noindicator and (indicator_icon or lock_indicator or required_indicator) %}
{% set labeled = suffix_text or corner_indicator %}
<div class="ui
{% if field_visible %}
<div class="ui
{% if suffix_text %}right{% endif %}
{% if corner_indicator %}corner{% endif %}
{% if labeled %}labeled{% endif %}
{% if icon %}left icon {% endif %}
{% if field.type not in ("BooleanField", "RadioField") %}input{% endif %}
">
{% if icon %}<i class="{{ icon }} icon"></i>{% endif %}
{% endif %}
{% if icon %}<i class="{{ icon }} icon"></i>{% endif %}
{% if field.type not in ("SelectField", "SelectMultipleField") %}
{% if field.type not in ("SelectField", "SelectMultipleField") %}
{{ field(**kwargs) }}
{% elif field.render_kw and "readonly" in field.render_kw %}
{% elif field.render_kw and "readonly" in field.render_kw %}
{{ field(class_="ui fluid dropdown multiple read-only", **kwargs) }}
{% else %}
{% else %}
{{ field(class_="ui fluid dropdown multiple", **kwargs) }}
{% endif %}
{% endif %}
{% if suffix_text %}
{% if suffix_text %}
<div class="ui basic label">
{{ suffix_text }}{% if corner_indicator %}&emsp;{% endif %}
</div>
{% endif %}
{% endif %}
{% if not noindicator %}
{% if not noindicator %}
{% if indicator_icon %}
<div class="ui corner label"{% if indicator_text %} title="{{ indicator_text }}"{% endif %}>
<i class="{{ indicator_icon }} icon"></i>
@ -67,8 +69,10 @@ display=true
<i class="asterisk icon"></i>
</div>
{% endif %}
{% endif %}
</div>
{% endif %}
{% if field_visible %}
</div>
{% endif %}
{% if field.errors %}
{% for error in field.errors %}
@ -77,7 +81,8 @@ display=true
</div>
{% endfor %}
{% endif %}
{% if container %}
{% if container and field_visible %}
</div>
{% endif %}
@ -96,7 +101,7 @@ display=true
{% macro render_form(
form,
action_text='submit',
action_text=none,
class_='',
btn_class='ui right floated primary button',
action=none,
@ -108,7 +113,11 @@ id=none) -%}
enctype="multipart/form-data"
class="ui form {{ class_ }}"
>
{% if caller %}
{{ caller() }}
{% else %}
{{ render_fields(form) }}
{% endif %}
{% if action_text %}
<button type="submit" class="{{ btn_class }}">{{ action_text }}</button>
{% endif %}

View file

@ -76,6 +76,10 @@
<i class="user secret icon"></i>
{% trans %}Codes{% endtrans %}
</a>
<a class="item" href="{{ url_for('admin_mails.mail_index') }}">
<i class="user mail icon"></i>
{% trans %}Emails{% endtrans %}
</a>
</div>
</div>
{% endif %}

View file

@ -1107,4 +1107,3 @@ msgstr ""
#: canaille/themes/default/base.html:84
msgid "Log out"
msgstr ""

View file

@ -329,6 +329,7 @@ def user(app, slapd_connection):
@pytest.fixture
def admin(app, slapd_connection):
User.ldap_object_classes(slapd_connection)
LDAPObject.ldap_object_attributes(slapd_connection)
u = User(
objectClass=["inetOrgPerson"],
cn="Jane Doe",

View file

@ -1,6 +1,14 @@
def test_reset_html(testclient, logged_admin):
testclient.get("/admin/mail/reset.html")
def test_send_test_email(testclient, logged_admin, smtpd):
assert len(smtpd.messages) == 0
res = testclient.get("/admin/mail")
res.form["mail"] = "test@test.com"
res = res.form.submit()
assert len(smtpd.messages) == 1
def test_reset_txt(testclient, logged_admin):
testclient.get("/admin/mail/reset.txt")
def test_mails(testclient, logged_admin):
for base in ["password-init", "reset", "admin/admin@admin.com/invitation"]:
testclient.get(f"/admin/mail/{base}.html")
testclient.get(f"/admin/mail/{base}.txt")