stages/email: add support for custom template to API
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
This commit is contained in:
parent
d061868fdc
commit
d1cde64214
|
@ -1,8 +1,18 @@
|
|||
"""EmailStage API Views"""
|
||||
from drf_yasg.utils import swagger_auto_schema
|
||||
from rest_framework.decorators import action
|
||||
from rest_framework.request import Request
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.serializers import ValidationError
|
||||
from rest_framework.viewsets import ModelViewSet
|
||||
|
||||
from authentik.core.api.utils import TypeCreateSerializer
|
||||
from authentik.flows.api.stages import StageSerializer
|
||||
from authentik.stages.email.models import EmailStage, get_template_choices
|
||||
from authentik.stages.email.models import (
|
||||
EmailStage,
|
||||
EmailTemplates,
|
||||
get_template_choices,
|
||||
)
|
||||
|
||||
|
||||
class EmailStageSerializer(StageSerializer):
|
||||
|
@ -12,6 +22,13 @@ class EmailStageSerializer(StageSerializer):
|
|||
super().__init__(*args, **kwargs)
|
||||
self.fields["template"].choices = get_template_choices()
|
||||
|
||||
def validate_template(self, value: str) -> str:
|
||||
choices = get_template_choices()
|
||||
for path, _ in choices:
|
||||
if path == value:
|
||||
return value
|
||||
raise ValidationError(f"Invalid template '{value}' specified.")
|
||||
|
||||
class Meta:
|
||||
|
||||
model = EmailStage
|
||||
|
@ -39,3 +56,17 @@ class EmailStageViewSet(ModelViewSet):
|
|||
serializer_class = EmailStageSerializer
|
||||
|
||||
# TODO: Validate connection settings when use_global_settings is unchecked
|
||||
@swagger_auto_schema(responses={200: TypeCreateSerializer(many=True)})
|
||||
@action(detail=False, pagination_class=None, filter_backends=[])
|
||||
def templates(self, request: Request) -> Response:
|
||||
"""Get all available templates, including custom templates"""
|
||||
choices = []
|
||||
for value, label in get_template_choices():
|
||||
choices.append(
|
||||
{
|
||||
"name": value,
|
||||
"description": label,
|
||||
"component": "",
|
||||
}
|
||||
)
|
||||
return Response(TypeCreateSerializer(choices, many=True).data)
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
# Generated by Django 3.1.7 on 2021-04-04 10:54
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("authentik_stages_email", "0002_emailstage_use_global_settings"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name="emailstage",
|
||||
name="template",
|
||||
field=models.TextField(default="email/password_reset.html"),
|
||||
),
|
||||
]
|
|
@ -78,9 +78,7 @@ class EmailStage(Stage):
|
|||
default=30, help_text=_("Time in minutes the token sent is valid.")
|
||||
)
|
||||
subject = models.TextField(default="authentik")
|
||||
template = models.TextField(
|
||||
choices=get_template_choices(), default=EmailTemplates.PASSWORD_RESET
|
||||
)
|
||||
template = models.TextField(default=EmailTemplates.PASSWORD_RESET)
|
||||
|
||||
@property
|
||||
def serializer(self) -> BaseSerializer:
|
||||
|
|
23
swagger.yaml
23
swagger.yaml
|
@ -12081,6 +12081,25 @@ paths:
|
|||
tags:
|
||||
- stages
|
||||
parameters: []
|
||||
/stages/email/templates/:
|
||||
get:
|
||||
operationId: stages_email_templates
|
||||
description: Get all available templates, including custom templates
|
||||
parameters: []
|
||||
responses:
|
||||
'200':
|
||||
description: ''
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/definitions/TypeCreate'
|
||||
'403':
|
||||
description: Authentication credentials were invalid, absent or insufficient.
|
||||
schema:
|
||||
$ref: '#/definitions/GenericError'
|
||||
tags:
|
||||
- stages
|
||||
parameters: []
|
||||
/stages/email/{stage_uuid}/:
|
||||
get:
|
||||
operationId: stages_email_read
|
||||
|
@ -17693,9 +17712,7 @@ definitions:
|
|||
template:
|
||||
title: Template
|
||||
type: string
|
||||
enum:
|
||||
- email/password_reset.html
|
||||
- email/account_confirmation.html
|
||||
minLength: 1
|
||||
IdentificationStage:
|
||||
required:
|
||||
- name
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { EmailStage, EmailStageTemplateEnum, StagesApi } from "authentik-api";
|
||||
import { EmailStage, StagesApi } from "authentik-api";
|
||||
import { t } from "@lingui/macro";
|
||||
import { customElement, property } from "lit-element";
|
||||
import { html, TemplateResult } from "lit-html";
|
||||
|
@ -8,6 +8,7 @@ import { ifDefined } from "lit-html/directives/if-defined";
|
|||
import "../../../elements/forms/HorizontalFormElement";
|
||||
import "../../../elements/forms/FormGroup";
|
||||
import { first } from "../../../utils";
|
||||
import { until } from "lit-html/directives/until";
|
||||
|
||||
@customElement("ak-stage-email-form")
|
||||
export class EmailStageForm extends Form<EmailStage> {
|
||||
|
@ -153,14 +154,16 @@ export class EmailStageForm extends Form<EmailStage> {
|
|||
<ak-form-element-horizontal
|
||||
label=${t`Template`}
|
||||
?required=${true}
|
||||
name="subject">
|
||||
name="template">
|
||||
<select name="users" class="pf-c-form-control">
|
||||
<option value=${EmailStageTemplateEnum.AccountConfirmationHtml} ?selected=${this.stage?.template === EmailStageTemplateEnum.AccountConfirmationHtml}>
|
||||
${t`Account confirmation`}
|
||||
</option>
|
||||
<option value=${EmailStageTemplateEnum.PasswordResetHtml} ?selected=${this.stage?.template === EmailStageTemplateEnum.PasswordResetHtml}>
|
||||
${t`Password reset`}
|
||||
</option>
|
||||
${until(new StagesApi(DEFAULT_CONFIG).stagesEmailTemplates().then(templates => {
|
||||
return templates.map(template => {
|
||||
const selected = this.stage?.template === template.name;
|
||||
return html`<option value=${ifDefined(template.name)} ?selected=${selected}>
|
||||
${template.description}
|
||||
</option>`;
|
||||
});
|
||||
}), html`<option>${t`Loading...`}</option>`)}
|
||||
</select>
|
||||
</ak-form-element-horizontal>
|
||||
</div>
|
||||
|
|
Reference in New Issue