Merge pull request #1689 from umbraco/feature/mfa-small-design-update

Chore: Clean up UI around two-factor
This commit is contained in:
Jacob Overgaard
2024-04-23 10:55:01 +02:00
committed by GitHub
5 changed files with 169 additions and 199 deletions

View File

@@ -3,151 +3,164 @@ const { rest } = window.MockServiceWorker;
import type { PackageManifestResponse } from '../../packages/packages/types.js';
import { umbracoPath } from '@umbraco-cms/backoffice/utils';
const privateManifests: PackageManifestResponse = [
{
name: 'My Package Name',
version: '1.0.0',
extensions: [
{
type: 'bundle',
alias: 'My.Package.Bundle',
name: 'My Package Bundle',
js: '/App_Plugins/custom-bundle-package/index.js',
},
],
},
{
name: 'Named Package',
version: '1.0.0',
extensions: [
{
type: 'section',
alias: 'My.Section.Custom',
name: 'Custom Section',
js: '/App_Plugins/section.js',
elementName: 'my-section-custom',
weight: 1,
meta: {
label: 'Custom',
pathname: 'my-custom',
},
},
{
type: 'propertyEditorUi',
alias: 'My.PropertyEditorUI.Custom',
name: 'My Custom Property Editor UI',
js: '/App_Plugins/property-editor.js',
elementName: 'my-property-editor-ui-custom',
meta: {
label: 'My Custom Property',
icon: 'document',
group: 'Common',
propertyEditorSchema: 'Umbraco.TextBox',
},
},
],
},
{
name: 'Package with an entry point',
extensions: [
{
type: 'backofficeEntryPoint',
name: 'My Custom Entry Point',
alias: 'My.Entrypoint.Custom',
js: '/App_Plugins/custom-entrypoint.js',
},
],
},
{
name: 'My MFA Package',
extensions: [
{
type: 'mfaLoginProvider',
alias: 'My.MfaLoginProvider.Custom.Google',
name: 'My Custom Google MFA Provider',
forProviderName: 'Google Authenticator',
},
{
type: 'mfaLoginProvider',
alias: 'My.MfaLoginProvider.Custom.SMS',
name: 'My Custom SMS MFA Provider',
forProviderName: 'sms',
meta: {
label: 'Setup SMS Verification',
},
},
],
},
{
name: 'Package with a view',
extensions: [
{
type: 'packageView',
alias: 'My.PackageView.Custom',
name: 'My Custom Package View',
js: '/App_Plugins/package-view.js',
meta: {
packageName: 'Package with a view',
},
},
],
},
{
name: 'My MFA Package',
extensions: [
{
type: 'mfaLoginProvider',
alias: 'My.MfaLoginProvider.Custom',
name: 'My Custom MFA Provider',
forProviderName: 'sms',
meta: {
label: 'Setup SMS Verification',
},
},
],
},
];
const publicManifests: PackageManifestResponse = [
{
name: 'My Auth Package',
extensions: [
{
type: 'authProvider',
alias: 'My.AuthProvider.Google',
name: 'My Custom Auth Provider',
forProviderName: 'Umbraco.Google',
meta: {
label: 'Google',
defaultView: {
icon: 'icon-google',
},
linking: {
allowManualLinking: true,
},
},
},
{
type: 'authProvider',
alias: 'My.AuthProvider.Github',
name: 'My Github Auth Provider',
forProviderName: 'Umbraco.Github',
meta: {
label: 'GitHub',
defaultView: {
look: 'primary',
icon: 'icon-github',
color: 'success',
},
linking: {
allowManualLinking: true,
},
},
},
],
},
];
export const manifestDevelopmentHandlers = [
rest.get(umbracoPath('/manifest/manifest/private'), (_req, res, ctx) => {
return res(
// Respond with a 200 status code
ctx.status(200),
ctx.json<PackageManifestResponse>([
{
name: 'My Package Name',
version: '1.0.0',
extensions: [
{
type: 'bundle',
alias: 'My.Package.Bundle',
name: 'My Package Bundle',
js: '/App_Plugins/custom-bundle-package/index.js',
},
],
},
{
name: 'Named Package',
version: '1.0.0',
extensions: [
{
type: 'section',
alias: 'My.Section.Custom',
name: 'Custom Section',
js: '/App_Plugins/section.js',
elementName: 'my-section-custom',
weight: 1,
meta: {
label: 'Custom',
pathname: 'my-custom',
},
},
{
type: 'propertyEditorUi',
alias: 'My.PropertyEditorUI.Custom',
name: 'My Custom Property Editor UI',
js: '/App_Plugins/property-editor.js',
elementName: 'my-property-editor-ui-custom',
meta: {
label: 'My Custom Property',
icon: 'document',
group: 'Common',
propertyEditorSchema: 'Umbraco.TextBox',
},
},
],
},
{
name: 'Package with an entry point',
extensions: [
{
type: 'backofficeEntryPoint',
name: 'My Custom Entry Point',
alias: 'My.Entrypoint.Custom',
js: '/App_Plugins/custom-entrypoint.js',
},
],
},
{
name: 'My MFA Package',
extensions: [
{
type: 'mfaLoginProvider',
alias: 'My.MfaLoginProvider.Custom.Google',
name: 'My Custom Google MFA Provider',
forProviderName: 'Google Authenticator',
},
{
type: 'mfaLoginProvider',
alias: 'My.MfaLoginProvider.Custom.SMS',
name: 'My Custom SMS MFA Provider',
forProviderName: 'sms',
meta: {
label: 'Setup SMS Verification',
},
},
],
},
{
name: 'Package with a view',
extensions: [
{
type: 'packageView',
alias: 'My.PackageView.Custom',
name: 'My Custom Package View',
js: '/App_Plugins/package-view.js',
meta: {
packageName: 'Package with a view',
},
},
],
},
{
name: 'My MFA Package',
extensions: [
{
type: 'mfaLoginProvider',
alias: 'My.MfaLoginProvider.Custom',
name: 'My Custom MFA Provider',
forProviderName: 'sms',
meta: {
label: 'Setup SMS Verification',
},
},
],
},
]),
ctx.json<PackageManifestResponse>(privateManifests),
);
}),
rest.get(umbracoPath('/manifest/manifest/public'), (_req, res, ctx) => {
return res(
ctx.status(200),
ctx.json<PackageManifestResponse>([
{
name: 'My Auth Package',
extensions: [
{
type: 'authProvider',
alias: 'My.AuthProvider.Google',
name: 'My Custom Auth Provider',
forProviderName: 'Umbraco.Google',
meta: {
label: 'Sign in with Google',
},
},
{
type: 'authProvider',
alias: 'My.AuthProvider.Github',
name: 'My Github Auth Provider',
forProviderName: 'Umbraco.Github',
meta: {
label: 'GitHub',
defaultView: {
look: 'primary',
icon: 'icon-github',
color: 'success',
},
},
},
],
},
]),
);
return res(ctx.status(200), ctx.json<PackageManifestResponse>(publicManifests));
}),
rest.get(umbracoPath('/manifest/manifest'), (_req, res, ctx) => {
return res(ctx.status(200), ctx.json<PackageManifestResponse>([...privateManifests, ...publicManifests]));
}),
];
@@ -158,4 +171,7 @@ export const manifestEmptyHandlers = [
rest.get(umbracoPath('/manifest/manifest/public'), (_req, res, ctx) => {
return res(ctx.status(200), ctx.json<PackageManifestResponse>([]));
}),
rest.get(umbracoPath('/manifest/manifest'), (_req, res, ctx) => {
return res(ctx.status(200), ctx.json<PackageManifestResponse>([]));
}),
];

View File

@@ -1,6 +1,7 @@
const { rest } = window.MockServiceWorker;
import { umbUserMockDb } from '../../data/user/user.db.js';
import { UMB_SLUG } from './slug.js';
import type { LinkedLoginsRequestModel } from '@umbraco-cms/backoffice/external/backend-api';
import { umbracoPath } from '@umbraco-cms/backoffice/utils';
export const handlers = [
@@ -8,6 +9,19 @@ export const handlers = [
const loggedInUser = umbUserMockDb.getCurrentUser();
return res(ctx.status(200), ctx.json(loggedInUser));
}),
rest.get<LinkedLoginsRequestModel>(umbracoPath(`${UMB_SLUG}/current/logins`), (_req, res, ctx) => {
return res(
ctx.status(200),
ctx.json<LinkedLoginsRequestModel>({
linkedLogins: [
{
providerKey: 'google',
providerName: 'Umbraco.Google',
},
],
}),
);
}),
rest.get(umbracoPath(`${UMB_SLUG}/current/2fa`), (_req, res, ctx) => {
const mfaLoginProviders = umbUserMockDb.getMfaLoginProviders();
return res(ctx.status(200), ctx.json(mfaLoginProviders));

View File

@@ -1,54 +0,0 @@
import { UMB_CURRENT_USER_MFA_MODAL } from '../modals/current-user-mfa/current-user-mfa-modal.token.js';
import { html, customElement, state, nothing } from '@umbraco-cms/backoffice/external/lit';
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal';
import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry';
import { firstValueFrom } from '@umbraco-cms/backoffice/external/rxjs';
@customElement('umb-mfa-providers-current-user-app')
export class UmbMfaProvidersCurrentUserAppElement extends UmbLitElement {
@state()
_hasProviders = false;
constructor() {
super();
this.#init();
}
async #init() {
this._hasProviders = (await firstValueFrom(umbExtensionsRegistry.byType('mfaLoginProvider'))).length > 0;
}
render() {
if (!this._hasProviders) {
return nothing;
}
return html`
<uui-button
type="button"
look="primary"
label="${this.localize.term('user_configureTwoFactor')}"
@click=${this.#onClick}>
<uui-icon name="icon-rectangle-ellipsis"></uui-icon>
<umb-localize key="user_configureTwoFactor">Configure Two Factor</umb-localize>
</uui-button>
`;
}
async #onClick() {
const modalManagerContext = await this.getContext(UMB_MODAL_MANAGER_CONTEXT);
await modalManagerContext.open(this, UMB_CURRENT_USER_MFA_MODAL).onSubmit();
}
static styles = [UmbTextStyles];
}
export default UmbMfaProvidersCurrentUserAppElement;
declare global {
interface HTMLElementTagNameMap {
'umb-mfa-providers-current-user-app': UmbMfaProvidersCurrentUserAppElement;
}
}

View File

@@ -79,9 +79,7 @@ export class UmbCurrentUserMfaModalElement extends UmbLitElement {
)}
</div>
<div slot="actions">
<uui-button @click=${this.#close} look="secondary" .label=${this.localize.term('general_close')}>
${this.localize.term('general_close')}
</uui-button>
<uui-button @click=${this.#close} look="secondary" .label=${this.localize.term('general_close')}></uui-button>
</div>
</umb-body-layout>
`;
@@ -98,7 +96,6 @@ export class UmbCurrentUserMfaModalElement extends UmbLitElement {
() => html`
<p style="margin-top:0">
<umb-localize key="user_2faProviderIsEnabled">This two-factor provider is enabled</umb-localize>
<uui-icon icon="check"></uui-icon>
</p>
<uui-button
type="button"

View File

@@ -79,9 +79,7 @@ export class UmbUserMfaModalElement extends UmbLitElement {
)}
</div>
<div slot="actions">
<uui-button @click=${this.#close} look="secondary" .label=${this.localize.term('general_close')}>
${this.localize.term('general_close')}
</uui-button>
<uui-button @click=${this.#close} look="secondary" .label=${this.localize.term('general_close')}></uui-button>
</div>
</umb-body-layout>
`;
@@ -98,7 +96,6 @@ export class UmbUserMfaModalElement extends UmbLitElement {
() => html`
<p style="margin-top:0">
<umb-localize key="user_2faProviderIsEnabled">This two-factor provider is enabled</umb-localize>
<uui-icon icon="check"></uui-icon>
</p>
<uui-button
type="button"