web/elements: add support for non-field errors
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
This commit is contained in:
parent
55f68a9197
commit
3124b0f39c
|
@ -1,7 +1,12 @@
|
||||||
"""policy binding API Views"""
|
"""policy binding API Views"""
|
||||||
from typing import OrderedDict
|
from typing import OrderedDict
|
||||||
|
|
||||||
from django.core.exceptions import ObjectDoesNotExist
|
from django.core.exceptions import ObjectDoesNotExist
|
||||||
from rest_framework.serializers import ModelSerializer, PrimaryKeyRelatedField, ValidationError
|
from rest_framework.serializers import (
|
||||||
|
ModelSerializer,
|
||||||
|
PrimaryKeyRelatedField,
|
||||||
|
ValidationError,
|
||||||
|
)
|
||||||
from rest_framework.viewsets import ModelViewSet
|
from rest_framework.viewsets import ModelViewSet
|
||||||
from structlog.stdlib import get_logger
|
from structlog.stdlib import get_logger
|
||||||
|
|
||||||
|
@ -77,8 +82,7 @@ class PolicyBindingSerializer(ModelSerializer):
|
||||||
|
|
||||||
def validate(self, data: OrderedDict) -> OrderedDict:
|
def validate(self, data: OrderedDict) -> OrderedDict:
|
||||||
"""Check that either policy, group or user is set."""
|
"""Check that either policy, group or user is set."""
|
||||||
count = sum([bool(data["policy"]), bool(
|
count = sum([bool(data["policy"]), bool(data["group"]), bool(data["user"])])
|
||||||
data["group"]), bool(data["user"])])
|
|
||||||
invalid = count > 1
|
invalid = count > 1
|
||||||
empty = count < 1
|
empty = count < 1
|
||||||
if invalid:
|
if invalid:
|
||||||
|
@ -87,6 +91,7 @@ class PolicyBindingSerializer(ModelSerializer):
|
||||||
raise ValidationError("One of 'policy', 'group' or 'user' must be set.")
|
raise ValidationError("One of 'policy', 'group' or 'user' must be set.")
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
|
||||||
class PolicyBindingViewSet(ModelViewSet):
|
class PolicyBindingViewSet(ModelViewSet):
|
||||||
"""PolicyBinding Viewset"""
|
"""PolicyBinding Viewset"""
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ import PFButton from "@patternfly/patternfly/components/Button/button.css";
|
||||||
import AKGlobal from "../../authentik.css";
|
import AKGlobal from "../../authentik.css";
|
||||||
import PFForm from "@patternfly/patternfly/components/Form/form.css";
|
import PFForm from "@patternfly/patternfly/components/Form/form.css";
|
||||||
import PFFormControl from "@patternfly/patternfly/components/FormControl/form-control.css";
|
import PFFormControl from "@patternfly/patternfly/components/FormControl/form-control.css";
|
||||||
|
import PFAlert from "@patternfly/patternfly/components/Alert/alert.css";
|
||||||
import { MessageLevel } from "../messages/Message";
|
import { MessageLevel } from "../messages/Message";
|
||||||
import { IronFormElement } from "@polymer/iron-form/iron-form";
|
import { IronFormElement } from "@polymer/iron-form/iron-form";
|
||||||
import { camelToSnake } from "../../utils";
|
import { camelToSnake } from "../../utils";
|
||||||
|
@ -31,8 +32,11 @@ export class Form<T> extends LitElement {
|
||||||
@property()
|
@property()
|
||||||
send!: (data: T) => Promise<unknown>;
|
send!: (data: T) => Promise<unknown>;
|
||||||
|
|
||||||
|
@property({attribute: false})
|
||||||
|
nonFieldErrors?: string[];
|
||||||
|
|
||||||
static get styles(): CSSResult[] {
|
static get styles(): CSSResult[] {
|
||||||
return [PFBase, PFCard, PFButton, PFForm, PFFormControl, AKGlobal, css`
|
return [PFBase, PFCard, PFButton, PFForm, PFAlert, PFFormControl, AKGlobal, css`
|
||||||
select[multiple] {
|
select[multiple] {
|
||||||
height: 15em;
|
height: 15em;
|
||||||
}
|
}
|
||||||
|
@ -116,6 +120,7 @@ export class Form<T> extends LitElement {
|
||||||
if (errorMessage instanceof Error) {
|
if (errorMessage instanceof Error) {
|
||||||
throw errorMessage;
|
throw errorMessage;
|
||||||
}
|
}
|
||||||
|
// assign all input-related errors to their elements
|
||||||
const elements: PaperInputElement[] = ironForm._getSubmittableElements();
|
const elements: PaperInputElement[] = ironForm._getSubmittableElements();
|
||||||
elements.forEach((element) => {
|
elements.forEach((element) => {
|
||||||
const elementName = element.name;
|
const elementName = element.name;
|
||||||
|
@ -125,6 +130,9 @@ export class Form<T> extends LitElement {
|
||||||
element.invalid = true;
|
element.invalid = true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
if ("non_field_errors" in errorMessage) {
|
||||||
|
this.nonFieldErrors = errorMessage["non_field_errors"];
|
||||||
|
}
|
||||||
throw new APIError(errorMessage);
|
throw new APIError(errorMessage);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -136,6 +144,24 @@ export class Form<T> extends LitElement {
|
||||||
return html`<slot></slot>`;
|
return html`<slot></slot>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
renderNonFieldErrors(): TemplateResult {
|
||||||
|
if (!this.nonFieldErrors) {
|
||||||
|
return html``;
|
||||||
|
}
|
||||||
|
return html`<div class="pf-c-form__alert">
|
||||||
|
${this.nonFieldErrors.map(err => {
|
||||||
|
return html`<div class="pf-c-alert pf-m-inline pf-m-danger">
|
||||||
|
<div class="pf-c-alert__icon">
|
||||||
|
<i class="fas fa-exclamation-circle"></i>
|
||||||
|
</div>
|
||||||
|
<h4 class="pf-c-alert__title">
|
||||||
|
${err}
|
||||||
|
</h4>
|
||||||
|
</div>`;
|
||||||
|
})}
|
||||||
|
</div>`;
|
||||||
|
}
|
||||||
|
|
||||||
render(): TemplateResult {
|
render(): TemplateResult {
|
||||||
const rect = this.getBoundingClientRect();
|
const rect = this.getBoundingClientRect();
|
||||||
if (rect.x + rect.y + rect.width + rect.height === 0) {
|
if (rect.x + rect.y + rect.width + rect.height === 0) {
|
||||||
|
@ -143,6 +169,7 @@ export class Form<T> extends LitElement {
|
||||||
}
|
}
|
||||||
return html`<iron-form
|
return html`<iron-form
|
||||||
@iron-form-presubmit=${(ev: Event) => { this.submit(ev); }}>
|
@iron-form-presubmit=${(ev: Event) => { this.submit(ev); }}>
|
||||||
|
${this.renderNonFieldErrors()}
|
||||||
${this.renderForm()}
|
${this.renderForm()}
|
||||||
</iron-form>`;
|
</iron-form>`;
|
||||||
}
|
}
|
||||||
|
|
Reference in New Issue