ATH-01-008: fix web forms not submitting correctly when pressing enter
When submitting some forms with the Enter key instead of clicking "Confirm"/etc, the form would not get submitted correctly This would in the worst case is when setting a user's password, where the new password can end up in the URL, but the password was not actually saved to the user. Signed-off-by: Jens Langhammer <jens@goauthentik.io> # Conflicts: # web/src/admin/applications/ApplicationCheckAccessForm.ts # web/src/admin/crypto/CertificateGenerateForm.ts # web/src/admin/flows/FlowImportForm.ts # web/src/admin/groups/RelatedGroupList.ts # web/src/admin/policies/PolicyTestForm.ts # web/src/admin/property-mappings/PropertyMappingTestForm.ts # web/src/admin/providers/saml/SAMLProviderImportForm.ts # web/src/admin/users/RelatedUserList.ts # web/src/admin/users/ServiceAccountForm.ts # web/src/admin/users/UserPasswordForm.ts # web/src/admin/users/UserResetEmailForm.ts
This commit is contained in:
parent
1aff300171
commit
f05997740f
|
@ -63,8 +63,8 @@ def ldap_sync_password(sender, user: User, password: str, **_):
|
||||||
if not sources.exists():
|
if not sources.exists():
|
||||||
return
|
return
|
||||||
source = sources.first()
|
source = sources.first()
|
||||||
changer = LDAPPasswordChanger(source)
|
|
||||||
try:
|
try:
|
||||||
|
changer = LDAPPasswordChanger(source)
|
||||||
changer.change_password(user, password)
|
changer.change_password(user, password)
|
||||||
except LDAPOperationResult as exc:
|
except LDAPOperationResult as exc:
|
||||||
Event.new(
|
Event.new(
|
||||||
|
|
|
@ -115,9 +115,8 @@ export class ApplicationCheckAccessForm extends Form<{ forUser: number }> {
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
renderForm(): TemplateResult {
|
renderInlineForm(): TemplateResult {
|
||||||
return html`<form class="pf-c-form pf-m-horizontal">
|
return html`<ak-form-element-horizontal label=${t`User`} ?required=${true} name="forUser">
|
||||||
<ak-form-element-horizontal label=${t`User`} ?required=${true} name="forUser">
|
|
||||||
<ak-search-select
|
<ak-search-select
|
||||||
.fetchObjects=${async (query?: string): Promise<User[]> => {
|
.fetchObjects=${async (query?: string): Promise<User[]> => {
|
||||||
const args: CoreUsersListRequest = {
|
const args: CoreUsersListRequest = {
|
||||||
|
@ -144,7 +143,6 @@ export class ApplicationCheckAccessForm extends Form<{ forUser: number }> {
|
||||||
>
|
>
|
||||||
</ak-search-select>
|
</ak-search-select>
|
||||||
</ak-form-element-horizontal>
|
</ak-form-element-horizontal>
|
||||||
${this.result ? this.renderResult() : html``}
|
${this.result ? this.renderResult() : html``}`;
|
||||||
</form>`;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,9 +21,12 @@ export class CertificateKeyPairForm extends Form<CertificateGenerationRequest> {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
renderForm(): TemplateResult {
|
renderInlineForm(): TemplateResult {
|
||||||
return html`<form class="pf-c-form pf-m-horizontal">
|
return html`<ak-form-element-horizontal
|
||||||
<ak-form-element-horizontal label=${t`Common Name`} name="commonName" ?required=${true}>
|
label=${t`Common Name`}
|
||||||
|
name="commonName"
|
||||||
|
?required=${true}
|
||||||
|
>
|
||||||
<input type="text" class="pf-c-form-control" required />
|
<input type="text" class="pf-c-form-control" required />
|
||||||
</ak-form-element-horizontal>
|
</ak-form-element-horizontal>
|
||||||
<ak-form-element-horizontal label=${t`Subject-alt name`} name="subjectAltName">
|
<ak-form-element-horizontal label=${t`Subject-alt name`} name="subjectAltName">
|
||||||
|
@ -38,7 +41,6 @@ export class CertificateKeyPairForm extends Form<CertificateGenerationRequest> {
|
||||||
?required=${true}
|
?required=${true}
|
||||||
>
|
>
|
||||||
<input class="pf-c-form-control" type="number" value="365" />
|
<input class="pf-c-form-control" type="number" value="365" />
|
||||||
</ak-form-element-horizontal>
|
</ak-form-element-horizontal>`;
|
||||||
</form>`;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -87,15 +87,13 @@ export class FlowImportForm extends Form<Flow> {
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
renderForm(): TemplateResult {
|
renderInlineForm(): TemplateResult {
|
||||||
return html`<form class="pf-c-form pf-m-horizontal">
|
return html`<ak-form-element-horizontal label=${t`Flow`} name="flow">
|
||||||
<ak-form-element-horizontal label=${t`Flow`} name="flow">
|
|
||||||
<input type="file" value="" class="pf-c-form-control" />
|
<input type="file" value="" class="pf-c-form-control" />
|
||||||
<p class="pf-c-form__helper-text">
|
<p class="pf-c-form__helper-text">
|
||||||
${t`.yaml files, which can be found on goauthentik.io and can be exported by authentik.`}
|
${t`.yaml files, which can be found on goauthentik.io and can be exported by authentik.`}
|
||||||
</p>
|
</p>
|
||||||
</ak-form-element-horizontal>
|
</ak-form-element-horizontal>
|
||||||
${this.result ? this.renderResult() : html``}
|
${this.result ? this.renderResult() : html``}`;
|
||||||
</form>`;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,41 +46,39 @@ export class RelatedGroupAdd extends Form<{ groups: string[] }> {
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
renderForm(): TemplateResult {
|
renderInlineForm(): TemplateResult {
|
||||||
return html`<form class="pf-c-form pf-m-horizontal">
|
return html`<ak-form-element-horizontal label=${t`Groups to add`} name="groups">
|
||||||
<ak-form-element-horizontal label=${t`Groups to add`} name="groups">
|
<div class="pf-c-input-group">
|
||||||
<div class="pf-c-input-group">
|
<ak-user-group-select-table
|
||||||
<ak-user-group-select-table
|
.confirm=${(items: Group[]) => {
|
||||||
.confirm=${(items: Group[]) => {
|
this.groupsToAdd = items;
|
||||||
this.groupsToAdd = items;
|
this.requestUpdate();
|
||||||
this.requestUpdate();
|
return Promise.resolve();
|
||||||
return Promise.resolve();
|
}}
|
||||||
}}
|
>
|
||||||
>
|
<button slot="trigger" class="pf-c-button pf-m-control" type="button">
|
||||||
<button slot="trigger" class="pf-c-button pf-m-control" type="button">
|
<i class="fas fa-plus" aria-hidden="true"></i>
|
||||||
<i class="fas fa-plus" aria-hidden="true"></i>
|
</button>
|
||||||
</button>
|
</ak-user-group-select-table>
|
||||||
</ak-user-group-select-table>
|
<div class="pf-c-form-control">
|
||||||
<div class="pf-c-form-control">
|
<ak-chip-group>
|
||||||
<ak-chip-group>
|
${this.groupsToAdd.map((group) => {
|
||||||
${this.groupsToAdd.map((group) => {
|
return html`<ak-chip
|
||||||
return html`<ak-chip
|
.removable=${true}
|
||||||
.removable=${true}
|
value=${ifDefined(group.pk)}
|
||||||
value=${ifDefined(group.pk)}
|
@remove=${() => {
|
||||||
@remove=${() => {
|
const idx = this.groupsToAdd.indexOf(group);
|
||||||
const idx = this.groupsToAdd.indexOf(group);
|
this.groupsToAdd.splice(idx, 1);
|
||||||
this.groupsToAdd.splice(idx, 1);
|
this.requestUpdate();
|
||||||
this.requestUpdate();
|
}}
|
||||||
}}
|
>
|
||||||
>
|
${group.name}
|
||||||
${group.name}
|
</ak-chip>`;
|
||||||
</ak-chip>`;
|
})}
|
||||||
})}
|
</ak-chip-group>
|
||||||
</ak-chip-group>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</ak-form-element-horizontal>
|
</div>
|
||||||
</form> `;
|
</ak-form-element-horizontal>`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -116,9 +116,8 @@ export class PolicyTestForm extends Form<PolicyTestRequest> {
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
renderForm(): TemplateResult {
|
renderInlineForm(): TemplateResult {
|
||||||
return html`<form class="pf-c-form pf-m-horizontal">
|
return html`<ak-form-element-horizontal label=${t`User`} ?required=${true} name="user">
|
||||||
<ak-form-element-horizontal label=${t`User`} ?required=${true} name="user">
|
|
||||||
<ak-search-select
|
<ak-search-select
|
||||||
.fetchObjects=${async (query?: string): Promise<User[]> => {
|
.fetchObjects=${async (query?: string): Promise<User[]> => {
|
||||||
const args: CoreUsersListRequest = {
|
const args: CoreUsersListRequest = {
|
||||||
|
@ -155,7 +154,6 @@ export class PolicyTestForm extends Form<PolicyTestRequest> {
|
||||||
${t`Set custom attributes using YAML or JSON.`}
|
${t`Set custom attributes using YAML or JSON.`}
|
||||||
</p>
|
</p>
|
||||||
</ak-form-element-horizontal>
|
</ak-form-element-horizontal>
|
||||||
${this.result ? this.renderResult() : html``}
|
${this.result ? this.renderResult() : html``}`;
|
||||||
</form>`;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,9 +64,63 @@ export class PolicyTestForm extends Form<PolicyTestRequest> {
|
||||||
</ak-form-element-horizontal>`;
|
</ak-form-element-horizontal>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
renderForm(): TemplateResult {
|
renderExampleButtons(): TemplateResult {
|
||||||
return html`<form class="pf-c-form pf-m-horizontal">
|
const header = html`<p>${t`Example context data`}</p>`;
|
||||||
<ak-form-element-horizontal label=${t`User`} ?required=${true} name="user">
|
switch (this.mapping?.metaModelName) {
|
||||||
|
case "authentik_sources_ldap.ldappropertymapping":
|
||||||
|
return html`${header}${this.renderExampleLDAP()}`;
|
||||||
|
default:
|
||||||
|
return html``;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
renderExampleLDAP(): TemplateResult {
|
||||||
|
return html`
|
||||||
|
<button
|
||||||
|
class="pf-c-button pf-m-secondary"
|
||||||
|
role="button"
|
||||||
|
@click=${() => {
|
||||||
|
this.request = {
|
||||||
|
user: this.request?.user || 0,
|
||||||
|
context: {
|
||||||
|
ldap: {
|
||||||
|
name: "test-user",
|
||||||
|
objectSid: "S-1-5-21-2611707862-2219215769-354220275-1137",
|
||||||
|
objectClass: "person",
|
||||||
|
displayName: "authentik test user",
|
||||||
|
sAMAccountName: "sAMAccountName",
|
||||||
|
distinguishedName: "cn=user,ou=users,dc=goauthentik,dc=io",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
${t`Active Directory User`}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
class="pf-c-button pf-m-secondary"
|
||||||
|
role="button"
|
||||||
|
@click=${() => {
|
||||||
|
this.request = {
|
||||||
|
user: this.request?.user || 0,
|
||||||
|
context: {
|
||||||
|
ldap: {
|
||||||
|
name: "test-group",
|
||||||
|
objectSid: "S-1-5-21-2611707862-2219215769-354220275-1137",
|
||||||
|
objectClass: "group",
|
||||||
|
distinguishedName: "cn=group,ou=groups,dc=goauthentik,dc=io",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
${t`Active Directory Group`}
|
||||||
|
</button>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
renderInlineForm(): TemplateResult {
|
||||||
|
return html`<ak-form-element-horizontal label=${t`User`} ?required=${true} name="user">
|
||||||
<ak-search-select
|
<ak-search-select
|
||||||
.fetchObjects=${async (query?: string): Promise<User[]> => {
|
.fetchObjects=${async (query?: string): Promise<User[]> => {
|
||||||
const args: CoreUsersListRequest = {
|
const args: CoreUsersListRequest = {
|
||||||
|
@ -98,7 +152,6 @@ export class PolicyTestForm extends Form<PolicyTestRequest> {
|
||||||
>>
|
>>
|
||||||
</ak-codemirror>
|
</ak-codemirror>
|
||||||
</ak-form-element-horizontal>
|
</ak-form-element-horizontal>
|
||||||
${this.result ? this.renderResult() : html``}
|
${this.result ? this.renderResult() : html``}`;
|
||||||
</form>`;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,9 +37,8 @@ export class SAMLProviderImportForm extends Form<SAMLProvider> {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
renderForm(): TemplateResult {
|
renderInlineForm(): TemplateResult {
|
||||||
return html`<form class="pf-c-form pf-m-horizontal">
|
return html`<ak-form-element-horizontal label=${t`Name`} ?required=${true} name="name">
|
||||||
<ak-form-element-horizontal label=${t`Name`} ?required=${true} name="name">
|
|
||||||
<input type="text" class="pf-c-form-control" required />
|
<input type="text" class="pf-c-form-control" required />
|
||||||
</ak-form-element-horizontal>
|
</ak-form-element-horizontal>
|
||||||
<ak-form-element-horizontal
|
<ak-form-element-horizontal
|
||||||
|
@ -77,7 +76,6 @@ export class SAMLProviderImportForm extends Form<SAMLProvider> {
|
||||||
|
|
||||||
<ak-form-element-horizontal label=${t`Metadata`} name="metadata">
|
<ak-form-element-horizontal label=${t`Metadata`} name="metadata">
|
||||||
<input type="file" value="" class="pf-c-form-control" />
|
<input type="file" value="" class="pf-c-form-control" />
|
||||||
</ak-form-element-horizontal>
|
</ak-form-element-horizontal>`;
|
||||||
</form>`;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,9 +59,8 @@ export class RelatedUserAdd extends Form<{ users: number[] }> {
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
renderForm(): TemplateResult {
|
renderInlineForm(): TemplateResult {
|
||||||
return html`<form class="pf-c-form pf-m-horizontal">
|
return html`${this.group?.isSuperuser ? html`` : html``}
|
||||||
${this.group?.isSuperuser ? html`` : html``}
|
|
||||||
<ak-form-element-horizontal label=${t`Users to add`} name="users">
|
<ak-form-element-horizontal label=${t`Users to add`} name="users">
|
||||||
<div class="pf-c-input-group">
|
<div class="pf-c-input-group">
|
||||||
<ak-group-member-select-table
|
<ak-group-member-select-table
|
||||||
|
@ -93,8 +92,7 @@ export class RelatedUserAdd extends Form<{ users: number[] }> {
|
||||||
</ak-chip-group>
|
</ak-chip-group>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</ak-form-element-horizontal>
|
</ak-form-element-horizontal>`;
|
||||||
</form> `;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,9 +35,8 @@ export class ServiceAccountForm extends Form<UserServiceAccountRequest> {
|
||||||
this.result = undefined;
|
this.result = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
renderRequestForm(): TemplateResult {
|
renderInlineForm(): TemplateResult {
|
||||||
return html`<form class="pf-c-form pf-m-horizontal">
|
return html`<ak-form-element-horizontal label=${t`Username`} ?required=${true} name="name">
|
||||||
<ak-form-element-horizontal label=${t`Username`} ?required=${true} name="name">
|
|
||||||
<input type="text" value="" class="pf-c-form-control" required />
|
<input type="text" value="" class="pf-c-form-control" required />
|
||||||
<p class="pf-c-form__helper-text">
|
<p class="pf-c-form__helper-text">
|
||||||
${t`User's primary identifier. 150 characters or fewer.`}
|
${t`User's primary identifier. 150 characters or fewer.`}
|
||||||
|
@ -78,8 +77,7 @@ export class ServiceAccountForm extends Form<UserServiceAccountRequest> {
|
||||||
value="${dateTimeLocal(new Date(Date.now() + 1000 * 60 ** 2 * 24 * 360))}"
|
value="${dateTimeLocal(new Date(Date.now() + 1000 * 60 ** 2 * 24 * 360))}"
|
||||||
class="pf-c-form-control"
|
class="pf-c-form-control"
|
||||||
/>
|
/>
|
||||||
</ak-form-element-horizontal>
|
</ak-form-element-horizontal>`;
|
||||||
</form>`;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
renderResponseForm(): TemplateResult {
|
renderResponseForm(): TemplateResult {
|
||||||
|
@ -113,6 +111,6 @@ export class ServiceAccountForm extends Form<UserServiceAccountRequest> {
|
||||||
if (this.result) {
|
if (this.result) {
|
||||||
return this.renderResponseForm();
|
return this.renderResponseForm();
|
||||||
}
|
}
|
||||||
return this.renderRequestForm();
|
return super.renderForm();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,11 +26,13 @@ export class UserPasswordForm extends Form<UserPasswordSetRequest> {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
renderForm(): TemplateResult {
|
renderInlineForm(): TemplateResult {
|
||||||
return html`<form class="pf-c-form pf-m-horizontal">
|
return html`<ak-form-element-horizontal
|
||||||
<ak-form-element-horizontal label=${t`Password`} ?required=${true} name="password">
|
label=${t`Password`}
|
||||||
<input type="password" value="" class="pf-c-form-control" required />
|
?required=${true}
|
||||||
</ak-form-element-horizontal>
|
name="password"
|
||||||
</form>`;
|
>
|
||||||
|
<input type="password" value="" class="pf-c-form-control" required />
|
||||||
|
</ak-form-element-horizontal>`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,32 +32,34 @@ export class UserResetEmailForm extends Form<CoreUsersRecoveryEmailRetrieveReque
|
||||||
return new CoreApi(DEFAULT_CONFIG).coreUsersRecoveryEmailRetrieve(data);
|
return new CoreApi(DEFAULT_CONFIG).coreUsersRecoveryEmailRetrieve(data);
|
||||||
};
|
};
|
||||||
|
|
||||||
renderForm(): TemplateResult {
|
renderInlineForm(): TemplateResult {
|
||||||
return html`<form class="pf-c-form pf-m-horizontal">
|
return html`<ak-form-element-horizontal
|
||||||
<ak-form-element-horizontal label=${t`Email stage`} ?required=${true} name="emailStage">
|
label=${t`Email stage`}
|
||||||
<ak-search-select
|
?required=${true}
|
||||||
.fetchObjects=${async (query?: string): Promise<Stage[]> => {
|
name="emailStage"
|
||||||
const args: StagesAllListRequest = {
|
>
|
||||||
ordering: "name",
|
<ak-search-select
|
||||||
};
|
.fetchObjects=${async (query?: string): Promise<Stage[]> => {
|
||||||
if (query !== undefined) {
|
const args: StagesAllListRequest = {
|
||||||
args.search = query;
|
ordering: "name",
|
||||||
}
|
};
|
||||||
const stages = await new StagesApi(DEFAULT_CONFIG).stagesEmailList(args);
|
if (query !== undefined) {
|
||||||
return stages.results;
|
args.search = query;
|
||||||
}}
|
}
|
||||||
.groupBy=${(items: Stage[]) => {
|
const stages = await new StagesApi(DEFAULT_CONFIG).stagesEmailList(args);
|
||||||
return groupBy(items, (stage) => stage.verboseNamePlural);
|
return stages.results;
|
||||||
}}
|
}}
|
||||||
.renderElement=${(stage: Stage): string => {
|
.groupBy=${(items: Stage[]) => {
|
||||||
return stage.name;
|
return groupBy(items, (stage) => stage.verboseNamePlural);
|
||||||
}}
|
}}
|
||||||
.value=${(stage: Stage | undefined): string | undefined => {
|
.renderElement=${(stage: Stage): string => {
|
||||||
return stage?.pk;
|
return stage.name;
|
||||||
}}
|
}}
|
||||||
>
|
.value=${(stage: Stage | undefined): string | undefined => {
|
||||||
</ak-search-select>
|
return stage?.pk;
|
||||||
</ak-form-element-horizontal>
|
}}
|
||||||
</form>`;
|
>
|
||||||
|
</ak-search-select>
|
||||||
|
</ak-form-element-horizontal>`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -279,9 +279,23 @@ export abstract class Form<T> extends AKElement {
|
||||||
}
|
}
|
||||||
|
|
||||||
renderForm(): TemplateResult {
|
renderForm(): TemplateResult {
|
||||||
|
const inline = this.renderInlineForm();
|
||||||
|
if (inline) {
|
||||||
|
return html`<form class="pf-c-form pf-m-horizontal" @submit=${this.submit}>
|
||||||
|
${inline}
|
||||||
|
</form>`;
|
||||||
|
}
|
||||||
return html`<slot></slot>`;
|
return html`<slot></slot>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inline form render callback when inheriting this class, should be overwritten
|
||||||
|
* instead of `this.renderForm`
|
||||||
|
*/
|
||||||
|
renderInlineForm(): TemplateResult | undefined {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
renderNonFieldErrors(): TemplateResult {
|
renderNonFieldErrors(): TemplateResult {
|
||||||
if (!this.nonFieldErrors) {
|
if (!this.nonFieldErrors) {
|
||||||
return html``;
|
return html``;
|
||||||
|
|
Reference in a new issue