~homeworkprod/byceps

315e7c9d1e2cc2e0a0b8ffb124005042c633e84f — Jochen Kupperschmidt 10 months ago 1fa7c94
Move admin UI to update email configurations to brand settings, dissolve email admin blueprint
14 files changed, 83 insertions(+), 177 deletions(-)

M byceps/blueprints/admin/brand/forms.py
R byceps/blueprints/admin/{email/templates/admin/email/update_form.html => brand/templates/admin/brand/email_config_update_form.html}
M byceps/blueprints/admin/brand/templates/admin/brand/view.html
M byceps/blueprints/admin/brand/views.py
D byceps/blueprints/admin/email/__init__.py
D byceps/blueprints/admin/email/authorization.py
D byceps/blueprints/admin/email/forms.py
D byceps/blueprints/admin/email/views.py
M byceps/blueprints/blueprints.py
M scripts/data/permissions_and_roles.toml
M tests/integration/blueprints/admin/brand/test_views.py
D tests/integration/blueprints/admin/email/__init__.py
D tests/integration/blueprints/admin/email/conftest.py
D tests/integration/blueprints/admin/email/test_views.py
M byceps/blueprints/admin/brand/forms.py => byceps/blueprints/admin/brand/forms.py +6 -0
@@ 22,3 22,9 @@ class CreateForm(_BaseForm):

class UpdateForm(_BaseForm):
    image_filename = StringField('Bild-Dateiname', validators=[Optional()])


class EmailConfigUpdateForm(LocalizedForm):
    sender_address = StringField('Absender-Adresse', validators=[InputRequired()])
    sender_name = StringField('Absender-Name', validators=[Optional()])
    contact_address = StringField('Kontaktadresse', validators=[Optional()])

R byceps/blueprints/admin/email/templates/admin/email/update_form.html => byceps/blueprints/admin/brand/templates/admin/brand/email_config_update_form.html +5 -11
@@ 1,28 1,22 @@
{% extends 'layout/admin/base.html' %}
{% from 'macros/forms.html' import form_buttons, form_field, form_fieldset %}
{% from 'macros/icons.html' import render_icon %}
{% set current_page = 'email_admin' %}
{% set current_page = 'brand_admin' %}
{% set current_page_brand = brand %}
{% set title = 'Konfiguration bearbeiten' %}
{% set title = 'E-Mail-Konfiguration bearbeiten' %}

{% block body %}

  <nav class="breadcrumbs">
    <ol>
      <li><a href="{{ url_for('brand_admin.view', brand_id=config.brand_id) }}">Konfigurationen</a></li>
    </ol>
  </nav>
  <h1>{{ render_icon('edit') }} {{ title }}</h1>

  <form action="{{ url_for('.update', config_id=config.id) }}" method="post">
  <form action="{{ url_for('.email_config_update', brand_id=brand.id) }}" method="post">
    {% call form_fieldset() %}
      {{ form_field(form.config_id, readonly='readonly', autofocus='autofocus') }}
      {{ form_field(form.sender_address) }}
      {{ form_field(form.sender_address, autofocus='autofocus') }}
      {{ form_field(form.sender_name) }}
      {{ form_field(form.contact_address) }}
    {% endcall %}

    {{ form_buttons('Speichern', cancel_url=url_for('brand_admin.view', brand_id=config.brand_id)) }}
    {{ form_buttons('Speichern', cancel_url=url_for('.view', brand_id=brand.id)) }}
  </form>

{%- endblock %}

M byceps/blueprints/admin/brand/templates/admin/brand/view.html => byceps/blueprints/admin/brand/templates/admin/brand/view.html +2 -2
@@ 53,10 53,10 @@
    <div class="column-auto">
      <h2>E-Mail-Konfiguration</h2>
    </div>
    {%- if email_config and g.current_user.has_permission(EmailConfigPermission.update) %}
    {%- if email_config and g.current_user.has_permission(BrandPermission.update) %}
    <div class="column-auto">
      <div class="button-row button-row--right" style="margin-top: 2rem;">
        <a class="button button--compact" href="{{ url_for('email_admin.update_form', config_id=email_config.id) }}">{{ render_icon('edit') }} <span>Bearbeiten</span></a>
        <a class="button button--compact" href="{{ url_for('.email_config_update_form', brand_id=brand.id) }}">{{ render_icon('edit') }} <span>Bearbeiten</span></a>
      </div>
    </div>
    {%- endif %}

M byceps/blueprints/admin/brand/views.py => byceps/blueprints/admin/brand/views.py +64 -1
@@ 24,7 24,7 @@ from ...common.authorization.decorators import permission_required
from ...common.authorization.registry import permission_registry

from .authorization import BrandPermission
from .forms import CreateForm, UpdateForm
from .forms import CreateForm, EmailConfigUpdateForm, UpdateForm


blueprint = create_blueprint('brand_admin', __name__)


@@ 135,6 135,60 @@ def update(brand_id):


# -------------------------------------------------------------------- #
# email config


@blueprint.route('/brands/<brand_id>/email_config/update')
@permission_required(BrandPermission.update)
@templated
def email_config_update_form(brand_id, erroneous_form=None):
    """Show form to update e-mail config."""
    brand = _get_brand_or_404(brand_id)

    config = _get_email_config_or_404(brand.id)

    form = (
        erroneous_form
        if erroneous_form
        else EmailConfigUpdateForm(
            sender_address=config.sender.address,
            sender_name=config.sender.name,
            contact_address=config.contact_address,
        )
    )

    return {
        'brand': brand,
        'config': config,
        'form': form,
    }


@blueprint.route('/brands/<brand_id>/email_config', methods=['POST'])
@permission_required(BrandPermission.update)
def email_config_update(brand_id):
    """Update e-mail config."""
    brand = _get_brand_or_404(brand_id)

    config = _get_email_config_or_404(brand.id)

    form = EmailConfigUpdateForm(request.form)
    if not form.validate():
        return email_config_update_form(brand.id, form)

    sender_address = form.sender_address.data.strip()
    sender_name = form.sender_name.data.strip()
    contact_address = form.contact_address.data.strip()

    config = email_service.update_config(
        config.id, sender_address, sender_name, contact_address
    )

    flash_success(f'Die E-Mail-Konfiguration wurde aktualisiert.')
    return redirect_to('.view', brand_id=brand.id)


# -------------------------------------------------------------------- #
# helpers




@@ 145,3 199,12 @@ def _get_brand_or_404(brand_id):
        abort(404)

    return brand


def _get_email_config_or_404(brand_id):
    config = email_service.find_config_for_brand(brand_id)

    if config is None:
        abort(404)

    return config

D byceps/blueprints/admin/email/__init__.py => byceps/blueprints/admin/email/__init__.py +0 -0
D byceps/blueprints/admin/email/authorization.py => byceps/blueprints/admin/email/authorization.py +0 -14
@@ 1,14 0,0 @@
"""
byceps.blueprints.admin.email.authorization
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

:Copyright: 2006-2020 Jochen Kupperschmidt
:License: Revised BSD (see `LICENSE` file for details)
"""

from byceps.util.authorization import create_permission_enum


EmailConfigPermission = create_permission_enum('email_config', [
    'update',
])

D byceps/blueprints/admin/email/forms.py => byceps/blueprints/admin/email/forms.py +0 -19
@@ 1,19 0,0 @@
"""
byceps.blueprints.admin.email.forms
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

:Copyright: 2006-2020 Jochen Kupperschmidt
:License: Revised BSD (see `LICENSE` file for details)
"""

from wtforms import StringField
from wtforms.validators import InputRequired, Optional

from ....util.l10n import LocalizedForm


class UpdateForm(LocalizedForm):
    config_id = StringField('ID')
    sender_address = StringField('Absender-Adresse', validators=[InputRequired()])
    sender_name = StringField('Absender-Name', validators=[Optional()])
    contact_address = StringField('Kontaktadresse', validators=[Optional()])

D byceps/blueprints/admin/email/views.py => byceps/blueprints/admin/email/views.py +0 -82
@@ 1,82 0,0 @@
"""
byceps.blueprints.admin.email.views
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

:Copyright: 2006-2020 Jochen Kupperschmidt
:License: Revised BSD (see `LICENSE` file for details)
"""

from flask import abort, request

from ....services.email import service as email_service
from ....util.framework.blueprint import create_blueprint
from ....util.framework.flash import flash_success
from ....util.framework.templating import templated
from ....util.views import redirect_to

from ...common.authorization.decorators import permission_required
from ...common.authorization.registry import permission_registry

from .authorization import EmailConfigPermission
from .forms import UpdateForm


blueprint = create_blueprint('email_admin', __name__)


permission_registry.register_enum(EmailConfigPermission)


@blueprint.route('/configs/<config_id>/update')
@permission_required(EmailConfigPermission.update)
@templated
def update_form(config_id, erroneous_form=None):
    """Show form to update an e-mail config."""
    config = _get_config_or_404(config_id)

    form = (
        erroneous_form
        if erroneous_form
        else UpdateForm(
            config_id=config.id,
            sender_address=config.sender.address,
            sender_name=config.sender.name,
            contact_address=config.contact_address,
        )
    )

    return {
        'config': config,
        'form': form,
    }


@blueprint.route('/configs/<config_id>', methods=['POST'])
@permission_required(EmailConfigPermission.update)
def update(config_id):
    """Update an e-mail config."""
    config = _get_config_or_404(config_id)

    form = UpdateForm(request.form)
    if not form.validate():
        return update_form(config.id, form)

    sender_address = form.sender_address.data.strip()
    sender_name = form.sender_name.data.strip()
    contact_address = form.contact_address.data.strip()

    config = email_service.update_config(
        config.id, sender_address, sender_name, contact_address
    )

    flash_success(f'Die E-Mail-Konfiguration wurde aktualisiert.')
    return redirect_to('brand_admin.view', brand_id=config.brand_id)


def _get_config_or_404(config_id):
    config = email_service.find_config(config_id)

    if config is None:
        abort(404)

    return config

M byceps/blueprints/blueprints.py => byceps/blueprints/blueprints.py +0 -1
@@ 88,7 88,6 @@ def _get_blueprints_admin() -> Iterator[BlueprintReg]:
        ('admin.consent',                   '/admin/consent'            ),
        ('admin.core',                      None                        ),
        ('admin.dashboard',                 '/admin/dashboard'          ),
        ('admin.email',                     '/admin/email'              ),
        ('admin.news',                      '/admin/news'               ),
        ('admin.newsletter',                '/admin/newsletter'         ),
        ('admin.jobs',                      '/admin/jobs'               ),

M scripts/data/permissions_and_roles.toml => scripts/data/permissions_and_roles.toml +0 -11
@@ 91,10 91,6 @@ id = 'consent.administrate'
title = 'Zustimmungen verwalten'

[[permissions]]
id = 'email_config.update'
title = 'E-Mail-Konfigurationen bearbeiten'

[[permissions]]
id = 'jobs.view'
title = 'Jobs anzeigen'



@@ 402,13 398,6 @@ title = 'Zustimmungen verwalten'
assigned_permissions = ['consent.administrate']

[[roles]]
id = 'email_admin'
title = 'E-Mail-Konfigurationen verwalten'
assigned_permissions = [
    'email_config.update',
]

[[roles]]
id = 'jobs_admin'
title = 'Jobs verwalten'
assigned_permissions = ['jobs.view']

M tests/integration/blueprints/admin/brand/test_views.py => tests/integration/blueprints/admin/brand/test_views.py +6 -0
@@ 50,3 50,9 @@ def test_update_form(brand_admin_client, brand):
    url = f'/admin/brands/brands/{brand.id}/update'
    response = brand_admin_client.get(url)
    assert response.status_code == 200


def test_email_config_update_form(brand_admin_client, email_config):
    url = f'/admin/brands/brands/{email_config.brand_id}/email_config/update'
    response = brand_admin_client.get(url)
    assert response.status_code == 200

D tests/integration/blueprints/admin/email/__init__.py => tests/integration/blueprints/admin/email/__init__.py +0 -0
D tests/integration/blueprints/admin/email/conftest.py => tests/integration/blueprints/admin/email/conftest.py +0 -24
@@ 1,24 0,0 @@
"""
:Copyright: 2006-2020 Jochen Kupperschmidt
:License: Revised BSD (see `LICENSE` file for details)
"""

import pytest

from tests.helpers import login_user


@pytest.fixture(scope='package')
def email_admin(make_admin):
    permission_ids = {
        'admin.access',
        'email_config.update',
    }
    admin = make_admin('EmailAdmin', permission_ids)
    login_user(admin.id)
    return admin


@pytest.fixture(scope='package')
def email_admin_client(make_client, admin_app, email_admin):
    return make_client(admin_app, user_id=email_admin.id)

D tests/integration/blueprints/admin/email/test_views.py => tests/integration/blueprints/admin/email/test_views.py +0 -12
@@ 1,12 0,0 @@
"""
:Copyright: 2006-2020 Jochen Kupperschmidt
:License: Revised BSD (see `LICENSE` file for details)
"""

import byceps.services.email.service as email_service


def test_update_form(email_admin_client, email_config):
    url = f'/admin/email/configs/{email_config.id}/update'
    response = email_admin_client.get(url)
    assert response.status_code == 200