From fb5230c1bbd2171eab7ca4538a6a48d8770167c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jesper=20M=C3=B8ller=20Jensen?= <26099018+JesmoDev@users.noreply.github.com> Date: Tue, 23 May 2023 19:31:08 +1200 Subject: [PATCH 01/24] init files --- .../apps/auth/src/auth-legacy.context.ts | 15 +++++++ .../apps/auth/src/auth-new.context.ts | 15 +++++++ .../apps/auth/src/login.element.ts | 44 +++++++++++-------- .../apps/auth/src/types.ts | 11 +++++ 4 files changed, 67 insertions(+), 18 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/apps/auth/src/auth-legacy.context.ts create mode 100644 src/Umbraco.Web.UI.Client/apps/auth/src/auth-new.context.ts create mode 100644 src/Umbraco.Web.UI.Client/apps/auth/src/types.ts diff --git a/src/Umbraco.Web.UI.Client/apps/auth/src/auth-legacy.context.ts b/src/Umbraco.Web.UI.Client/apps/auth/src/auth-legacy.context.ts new file mode 100644 index 0000000000..827d12d316 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/apps/auth/src/auth-legacy.context.ts @@ -0,0 +1,15 @@ +import { LoginRequestModel, UmbAuthContext } from './types'; + +export class UmbAuthLegacyContext implements UmbAuthContext { + returnUrl: string; + authUrl: string; + + constructor(authUrl: string, returnUrl: string) { + this.returnUrl = returnUrl; + this.authUrl = authUrl; + } + + login(data: LoginRequestModel): Promise { + throw new Error('Method not implemented.'); + } +} diff --git a/src/Umbraco.Web.UI.Client/apps/auth/src/auth-new.context.ts b/src/Umbraco.Web.UI.Client/apps/auth/src/auth-new.context.ts new file mode 100644 index 0000000000..3b8b7de839 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/apps/auth/src/auth-new.context.ts @@ -0,0 +1,15 @@ +import { LoginRequestModel, UmbAuthContext } from './types'; + +export class UmbAuthNewContext implements UmbAuthContext { + returnUrl: string; + authUrl: string; + + constructor(authUrl: string, returnUrl: string) { + this.returnUrl = returnUrl; + this.authUrl = authUrl; + } + + login(data: LoginRequestModel): Promise { + throw new Error('Method not implemented.'); + } +} diff --git a/src/Umbraco.Web.UI.Client/apps/auth/src/login.element.ts b/src/Umbraco.Web.UI.Client/apps/auth/src/login.element.ts index 1587e1a97a..1a16e00a8e 100644 --- a/src/Umbraco.Web.UI.Client/apps/auth/src/login.element.ts +++ b/src/Umbraco.Web.UI.Client/apps/auth/src/login.element.ts @@ -1,12 +1,35 @@ import { UUITextStyles } from '@umbraco-ui/uui-css'; import { css, CSSResultGroup, html, LitElement } from 'lit'; -import { customElement, state } from 'lit/decorators.js'; +import { customElement, property, state } from 'lit/decorators.js'; import { ifDefined } from 'lit/directives/if-defined.js'; import './auth-layout.element'; +import { UmbAuthContext } from './types'; +import { UmbAuthLegacyContext } from './auth-legacy.context'; +import { UmbAuthNewContext } from './auth-new.context'; @customElement('umb-login') export default class UmbLoginElement extends LitElement { + #authContext: UmbAuthContext; + + @property({ type: String, attribute: 'return-url' }) + returnUrl = ''; + + @property({ type: String, attribute: 'auth-url' }) + authUrl = ''; + + @property({ type: Boolean }) + isLegacy = false; + + constructor() { + super(); + if (this.isLegacy) { + this.#authContext = new UmbAuthLegacyContext(this.authUrl, this.returnUrl); + } else { + this.#authContext = new UmbAuthNewContext(this.authUrl, this.returnUrl); + } + } + @state() private _loggingIn = false; @@ -25,22 +48,9 @@ export default class UmbLoginElement extends LitElement { const password = formData.get('password') as string; const persist = formData.has('persist'); - this._login(username, password, persist); + this.#authContext.login({ username, password, persist }); }; - private async _login(username: string, password: string, persist: boolean) { - // TODO: Move login to new login app - this._loggingIn = true; - - try { - this._loggingIn = false; - console.log('login'); - } catch (error) { - console.log(error); - this._loggingIn = false; - } - } - private _greetings: Array = [ 'Happy super Sunday', 'Happy marvelous Monday', @@ -67,7 +77,6 @@ export default class UmbLoginElement extends LitElement { type="email" id="email" name="email" - placeholder="Enter your email..." required required-message="Email is required"> @@ -77,13 +86,12 @@ export default class UmbLoginElement extends LitElement { - Remember me + Remember me ; +} From 21fec8239e7cafa6047620e776b476f5648210ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jesper=20M=C3=B8ller=20Jensen?= <26099018+JesmoDev@users.noreply.github.com> Date: Tue, 23 May 2023 20:03:17 +1200 Subject: [PATCH 02/24] mock login --- .../apps/auth/src/auth-legacy.context.ts | 2 +- .../apps/auth/src/auth-new.context.ts | 17 +++++- .../apps/auth/src/login.element.ts | 58 +++++++++++++------ .../apps/auth/src/types.ts | 2 +- 4 files changed, 57 insertions(+), 22 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/apps/auth/src/auth-legacy.context.ts b/src/Umbraco.Web.UI.Client/apps/auth/src/auth-legacy.context.ts index 827d12d316..bb74714396 100644 --- a/src/Umbraco.Web.UI.Client/apps/auth/src/auth-legacy.context.ts +++ b/src/Umbraco.Web.UI.Client/apps/auth/src/auth-legacy.context.ts @@ -9,7 +9,7 @@ export class UmbAuthLegacyContext implements UmbAuthContext { this.authUrl = authUrl; } - login(data: LoginRequestModel): Promise { + login(data: LoginRequestModel): Promise<{ error?: string | undefined }> { throw new Error('Method not implemented.'); } } diff --git a/src/Umbraco.Web.UI.Client/apps/auth/src/auth-new.context.ts b/src/Umbraco.Web.UI.Client/apps/auth/src/auth-new.context.ts index 3b8b7de839..6699fc84e4 100644 --- a/src/Umbraco.Web.UI.Client/apps/auth/src/auth-new.context.ts +++ b/src/Umbraco.Web.UI.Client/apps/auth/src/auth-new.context.ts @@ -9,7 +9,20 @@ export class UmbAuthNewContext implements UmbAuthContext { this.authUrl = authUrl; } - login(data: LoginRequestModel): Promise { - throw new Error('Method not implemented.'); + async login(data: LoginRequestModel) { + //TODO: call authUrl with data + const { error } = await UmbMockAPI.login(data, true); + + //TODO Should the redirect be done here? or in the login element? + + return { error }; + } +} + +class UmbMockAPI { + static async login(data: LoginRequestModel, shouldFail = false) { + await new Promise((resolve) => setTimeout(resolve, 1000)); + + return shouldFail ? { error: 'Invalid credentials' } : {}; } } diff --git a/src/Umbraco.Web.UI.Client/apps/auth/src/login.element.ts b/src/Umbraco.Web.UI.Client/apps/auth/src/login.element.ts index 1a16e00a8e..79f6128e6f 100644 --- a/src/Umbraco.Web.UI.Client/apps/auth/src/login.element.ts +++ b/src/Umbraco.Web.UI.Client/apps/auth/src/login.element.ts @@ -4,6 +4,7 @@ import { customElement, property, state } from 'lit/decorators.js'; import { ifDefined } from 'lit/directives/if-defined.js'; import './auth-layout.element'; +import { UUIButtonState } from '@umbraco-ui/uui'; import { UmbAuthContext } from './types'; import { UmbAuthLegacyContext } from './auth-legacy.context'; import { UmbAuthNewContext } from './auth-new.context'; @@ -21,6 +22,12 @@ export default class UmbLoginElement extends LitElement { @property({ type: Boolean }) isLegacy = false; + @state() + private _loginState: UUIButtonState = undefined; + + @state() + private _loginError = ''; + constructor() { super(); if (this.isLegacy) { @@ -30,10 +37,7 @@ export default class UmbLoginElement extends LitElement { } } - @state() - private _loggingIn = false; - - private _handleSubmit = (e: SubmitEvent) => { + #handleSubmit = async (e: SubmitEvent) => { e.preventDefault(); const form = e.target as HTMLFormElement; @@ -48,21 +52,28 @@ export default class UmbLoginElement extends LitElement { const password = formData.get('password') as string; const persist = formData.has('persist'); - this.#authContext.login({ username, password, persist }); + this._loginState = 'waiting'; + + const { error } = await this.#authContext.login({ username, password, persist }); + + this._loginError = error || ''; + this._loginState = error ? 'failed' : 'success'; }; - private _greetings: Array = [ - 'Happy super Sunday', - 'Happy marvelous Monday', - 'Happy tubular Tuesday', - 'Happy wonderful Wednesday', - 'Happy thunderous Thursday', - 'Happy funky Friday', - 'Happy Saturday', - ]; - @state() - private _greeting: string = this._greetings[new Date().getDay()]; + private _greeting: string = this.#greeting; + + get #greeting() { + return [ + 'Happy super Sunday', + 'Happy marvelous Monday', + 'Happy tubular Tuesday', + 'Happy wonderful Wednesday', + 'Happy thunderous Thursday', + 'Happy funky Friday', + 'Happy Saturday', + ][new Date().getDay()]; + } render() { return html` @@ -70,7 +81,7 @@ export default class UmbLoginElement extends LitElement {

${this._greeting}

-
+ Email Remember me + ${this.#renderErrorMessage()} + + state=${this._loginState}>
@@ -107,6 +120,12 @@ export default class UmbLoginElement extends LitElement { `; } + #renderErrorMessage() { + if (!this._loginError || this._loginState !== 'failed') return; + + return html`

${this._loginError}

`; + } + static styles: CSSResultGroup = [ UUITextStyles, css` @@ -114,6 +133,9 @@ export default class UmbLoginElement extends LitElement { #password { width: 100%; } + .text-danger { + color: var(--uui-color-danger-standalone); + } `, ]; } diff --git a/src/Umbraco.Web.UI.Client/apps/auth/src/types.ts b/src/Umbraco.Web.UI.Client/apps/auth/src/types.ts index c8e43942ab..64965d0462 100644 --- a/src/Umbraco.Web.UI.Client/apps/auth/src/types.ts +++ b/src/Umbraco.Web.UI.Client/apps/auth/src/types.ts @@ -7,5 +7,5 @@ export type LoginRequestModel = { export interface UmbAuthContext { returnUrl: string; authUrl: string; - login(data: LoginRequestModel): Promise; + login(data: LoginRequestModel): Promise<{ error?: string }>; } From d6c9eab61f48dcdeff4994f383dc3f17c727a144 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jesper=20M=C3=B8ller=20Jensen?= <26099018+JesmoDev@users.noreply.github.com> Date: Wed, 24 May 2023 18:00:04 +1200 Subject: [PATCH 03/24] disable login button if form is not valid --- .../apps/auth/src/login.element.ts | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/apps/auth/src/login.element.ts b/src/Umbraco.Web.UI.Client/apps/auth/src/login.element.ts index 79f6128e6f..348b7f044c 100644 --- a/src/Umbraco.Web.UI.Client/apps/auth/src/login.element.ts +++ b/src/Umbraco.Web.UI.Client/apps/auth/src/login.element.ts @@ -28,6 +28,9 @@ export default class UmbLoginElement extends LitElement { @state() private _loginError = ''; + @state() + private _isFormValid = false; + constructor() { super(); if (this.isLegacy) { @@ -37,14 +40,22 @@ export default class UmbLoginElement extends LitElement { } } + #checkFormValidity(e: Event) { + const form = e.target as HTMLFormElement; + if (!form) return; + + this._isFormValid = form.checkValidity(); + } + #handleSubmit = async (e: SubmitEvent) => { e.preventDefault(); const form = e.target as HTMLFormElement; if (!form) return; - const isValid = form.checkValidity(); - if (!isValid) return; + this._isFormValid = form.checkValidity(); + + if (!this._isFormValid) return; const formData = new FormData(form); @@ -80,7 +91,7 @@ export default class UmbLoginElement extends LitElement {

${this._greeting}

- +
Email @@ -108,6 +119,7 @@ export default class UmbLoginElement extends LitElement { ${this.#renderErrorMessage()} Date: Wed, 24 May 2023 18:11:52 +1200 Subject: [PATCH 04/24] add redirecting --- src/Umbraco.Web.UI.Client/apps/auth/index.html | 2 +- src/Umbraco.Web.UI.Client/apps/auth/src/auth-new.context.ts | 2 +- src/Umbraco.Web.UI.Client/apps/auth/src/login.element.ts | 5 +++++ 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/apps/auth/index.html b/src/Umbraco.Web.UI.Client/apps/auth/index.html index 75922ccae2..de2b8a4cdc 100644 --- a/src/Umbraco.Web.UI.Client/apps/auth/index.html +++ b/src/Umbraco.Web.UI.Client/apps/auth/index.html @@ -10,6 +10,6 @@ - + diff --git a/src/Umbraco.Web.UI.Client/apps/auth/src/auth-new.context.ts b/src/Umbraco.Web.UI.Client/apps/auth/src/auth-new.context.ts index 6699fc84e4..8f4d726ab8 100644 --- a/src/Umbraco.Web.UI.Client/apps/auth/src/auth-new.context.ts +++ b/src/Umbraco.Web.UI.Client/apps/auth/src/auth-new.context.ts @@ -11,7 +11,7 @@ export class UmbAuthNewContext implements UmbAuthContext { async login(data: LoginRequestModel) { //TODO: call authUrl with data - const { error } = await UmbMockAPI.login(data, true); + const { error } = await UmbMockAPI.login(data, false); //TODO Should the redirect be done here? or in the login element? diff --git a/src/Umbraco.Web.UI.Client/apps/auth/src/login.element.ts b/src/Umbraco.Web.UI.Client/apps/auth/src/login.element.ts index 348b7f044c..5349e750b9 100644 --- a/src/Umbraco.Web.UI.Client/apps/auth/src/login.element.ts +++ b/src/Umbraco.Web.UI.Client/apps/auth/src/login.element.ts @@ -69,6 +69,11 @@ export default class UmbLoginElement extends LitElement { this._loginError = error || ''; this._loginState = error ? 'failed' : 'success'; + + if (error) return; + + //TODO: Should redirecting be done here or in the context? + location.replace(this.returnUrl); }; @state() From e00b626acb60df7a8892f95aee0afc7f668f456a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jesper=20M=C3=B8ller=20Jensen?= <26099018+JesmoDev@users.noreply.github.com> Date: Wed, 24 May 2023 18:16:46 +1200 Subject: [PATCH 05/24] cleanup --- .../apps/auth/src/auth-legacy.context.ts | 4 +--- .../apps/auth/src/auth-new.context.ts | 4 +--- .../apps/auth/src/login.element.ts | 17 +++++++---------- .../apps/auth/src/types.ts | 1 - 4 files changed, 9 insertions(+), 17 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/apps/auth/src/auth-legacy.context.ts b/src/Umbraco.Web.UI.Client/apps/auth/src/auth-legacy.context.ts index bb74714396..f506a1d108 100644 --- a/src/Umbraco.Web.UI.Client/apps/auth/src/auth-legacy.context.ts +++ b/src/Umbraco.Web.UI.Client/apps/auth/src/auth-legacy.context.ts @@ -1,11 +1,9 @@ import { LoginRequestModel, UmbAuthContext } from './types'; export class UmbAuthLegacyContext implements UmbAuthContext { - returnUrl: string; authUrl: string; - constructor(authUrl: string, returnUrl: string) { - this.returnUrl = returnUrl; + constructor(authUrl: string) { this.authUrl = authUrl; } diff --git a/src/Umbraco.Web.UI.Client/apps/auth/src/auth-new.context.ts b/src/Umbraco.Web.UI.Client/apps/auth/src/auth-new.context.ts index 8f4d726ab8..1216d700d6 100644 --- a/src/Umbraco.Web.UI.Client/apps/auth/src/auth-new.context.ts +++ b/src/Umbraco.Web.UI.Client/apps/auth/src/auth-new.context.ts @@ -1,11 +1,9 @@ import { LoginRequestModel, UmbAuthContext } from './types'; export class UmbAuthNewContext implements UmbAuthContext { - returnUrl: string; authUrl: string; - constructor(authUrl: string, returnUrl: string) { - this.returnUrl = returnUrl; + constructor(authUrl: string) { this.authUrl = authUrl; } diff --git a/src/Umbraco.Web.UI.Client/apps/auth/src/login.element.ts b/src/Umbraco.Web.UI.Client/apps/auth/src/login.element.ts index 5349e750b9..90069348c9 100644 --- a/src/Umbraco.Web.UI.Client/apps/auth/src/login.element.ts +++ b/src/Umbraco.Web.UI.Client/apps/auth/src/login.element.ts @@ -1,14 +1,14 @@ import { UUITextStyles } from '@umbraco-ui/uui-css'; import { css, CSSResultGroup, html, LitElement } from 'lit'; import { customElement, property, state } from 'lit/decorators.js'; -import { ifDefined } from 'lit/directives/if-defined.js'; -import './auth-layout.element'; import { UUIButtonState } from '@umbraco-ui/uui'; import { UmbAuthContext } from './types'; import { UmbAuthLegacyContext } from './auth-legacy.context'; import { UmbAuthNewContext } from './auth-new.context'; +import './auth-layout.element'; + @customElement('umb-login') export default class UmbLoginElement extends LitElement { #authContext: UmbAuthContext; @@ -34,18 +34,18 @@ export default class UmbLoginElement extends LitElement { constructor() { super(); if (this.isLegacy) { - this.#authContext = new UmbAuthLegacyContext(this.authUrl, this.returnUrl); + this.#authContext = new UmbAuthLegacyContext(this.authUrl); } else { - this.#authContext = new UmbAuthNewContext(this.authUrl, this.returnUrl); + this.#authContext = new UmbAuthNewContext(this.authUrl); } } - #checkFormValidity(e: Event) { + #checkFormValidity = (e: Event) => { const form = e.target as HTMLFormElement; if (!form) return; this._isFormValid = form.checkValidity(); - } + }; #handleSubmit = async (e: SubmitEvent) => { e.preventDefault(); @@ -76,9 +76,6 @@ export default class UmbLoginElement extends LitElement { location.replace(this.returnUrl); }; - @state() - private _greeting: string = this.#greeting; - get #greeting() { return [ 'Happy super Sunday', @@ -95,7 +92,7 @@ export default class UmbLoginElement extends LitElement { return html`
-

${this._greeting}

+

${this.#greeting}

diff --git a/src/Umbraco.Web.UI.Client/apps/auth/src/types.ts b/src/Umbraco.Web.UI.Client/apps/auth/src/types.ts index 64965d0462..a5f911472e 100644 --- a/src/Umbraco.Web.UI.Client/apps/auth/src/types.ts +++ b/src/Umbraco.Web.UI.Client/apps/auth/src/types.ts @@ -5,7 +5,6 @@ export type LoginRequestModel = { }; export interface UmbAuthContext { - returnUrl: string; authUrl: string; login(data: LoginRequestModel): Promise<{ error?: string }>; } From a805cd693a3182f6f587e35aa9dd5af1d60c5b91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jesper=20M=C3=B8ller=20Jensen?= <26099018+JesmoDev@users.noreply.github.com> Date: Wed, 24 May 2023 18:43:55 +1200 Subject: [PATCH 06/24] fix redirect --- .../apps/auth/src/login.element.ts | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/apps/auth/src/login.element.ts b/src/Umbraco.Web.UI.Client/apps/auth/src/login.element.ts index 90069348c9..ed4d97f166 100644 --- a/src/Umbraco.Web.UI.Client/apps/auth/src/login.element.ts +++ b/src/Umbraco.Web.UI.Client/apps/auth/src/login.element.ts @@ -40,11 +40,16 @@ export default class UmbLoginElement extends LitElement { } } - #checkFormValidity = (e: Event) => { - const form = e.target as HTMLFormElement; + //TODO: What is the correct type for this event? + #checkFormValidity = (e: any) => { + const form = e.target.closest('form') as HTMLFormElement; + if (!form) return; - this._isFormValid = form.checkValidity(); + //TODO: Why do we need to wait one frame for the check to work correctly? + requestAnimationFrame(() => { + this._isFormValid = form.checkValidity(); + }); }; #handleSubmit = async (e: SubmitEvent) => { @@ -55,6 +60,8 @@ export default class UmbLoginElement extends LitElement { this._isFormValid = form.checkValidity(); + console.log('what', this._isFormValid); + if (!this._isFormValid) return; const formData = new FormData(form); @@ -73,7 +80,7 @@ export default class UmbLoginElement extends LitElement { if (error) return; //TODO: Should redirecting be done here or in the context? - location.replace(this.returnUrl); + location.href = this.returnUrl; }; get #greeting() { @@ -93,8 +100,8 @@ export default class UmbLoginElement extends LitElement {

${this.#greeting}

- - + + Email Date: Wed, 24 May 2023 19:36:23 +1200 Subject: [PATCH 07/24] add url to login api --- .../apps/auth/src/auth-legacy.context.ts | 10 +++---- .../apps/auth/src/auth-new.context.ts | 26 ------------------- .../apps/auth/src/auth.context.ts | 24 +++++++++++++++++ .../apps/auth/src/auth.ts | 4 --- .../apps/auth/src/login.element.ts | 13 ++++------ .../apps/auth/src/types.ts | 9 +++++-- 6 files changed, 39 insertions(+), 47 deletions(-) delete mode 100644 src/Umbraco.Web.UI.Client/apps/auth/src/auth-new.context.ts create mode 100644 src/Umbraco.Web.UI.Client/apps/auth/src/auth.context.ts delete mode 100644 src/Umbraco.Web.UI.Client/apps/auth/src/auth.ts diff --git a/src/Umbraco.Web.UI.Client/apps/auth/src/auth-legacy.context.ts b/src/Umbraco.Web.UI.Client/apps/auth/src/auth-legacy.context.ts index f506a1d108..2920919eda 100644 --- a/src/Umbraco.Web.UI.Client/apps/auth/src/auth-legacy.context.ts +++ b/src/Umbraco.Web.UI.Client/apps/auth/src/auth-legacy.context.ts @@ -1,11 +1,7 @@ -import { LoginRequestModel, UmbAuthContext } from './types'; +import { LoginRequestModel, IUmbAuthContext } from './types'; -export class UmbAuthLegacyContext implements UmbAuthContext { - authUrl: string; - - constructor(authUrl: string) { - this.authUrl = authUrl; - } +export class UmbAuthLegacyContext implements IUmbAuthContext { + readonly #AUTH_URL = '/umbraco/backoffice/umbracoapi/authentication/postlogin'; login(data: LoginRequestModel): Promise<{ error?: string | undefined }> { throw new Error('Method not implemented.'); diff --git a/src/Umbraco.Web.UI.Client/apps/auth/src/auth-new.context.ts b/src/Umbraco.Web.UI.Client/apps/auth/src/auth-new.context.ts deleted file mode 100644 index 1216d700d6..0000000000 --- a/src/Umbraco.Web.UI.Client/apps/auth/src/auth-new.context.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { LoginRequestModel, UmbAuthContext } from './types'; - -export class UmbAuthNewContext implements UmbAuthContext { - authUrl: string; - - constructor(authUrl: string) { - this.authUrl = authUrl; - } - - async login(data: LoginRequestModel) { - //TODO: call authUrl with data - const { error } = await UmbMockAPI.login(data, false); - - //TODO Should the redirect be done here? or in the login element? - - return { error }; - } -} - -class UmbMockAPI { - static async login(data: LoginRequestModel, shouldFail = false) { - await new Promise((resolve) => setTimeout(resolve, 1000)); - - return shouldFail ? { error: 'Invalid credentials' } : {}; - } -} diff --git a/src/Umbraco.Web.UI.Client/apps/auth/src/auth.context.ts b/src/Umbraco.Web.UI.Client/apps/auth/src/auth.context.ts new file mode 100644 index 0000000000..50b9e92c85 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/apps/auth/src/auth.context.ts @@ -0,0 +1,24 @@ +import { LoginRequestModel, IUmbAuthContext } from './types'; + +export class UmbAuthContext implements IUmbAuthContext { + readonly #AUTH_URL = '/umbraco/management/api/v1.0/security/back-office'; + + async login(data: LoginRequestModel) { + //TODO: call authUrl with data + return UmbMockAPI.loginSuccess(data); + } +} + +class UmbMockAPI { + static async loginSuccess(data: LoginRequestModel) { + await new Promise((resolve) => setTimeout(resolve, 1000)); + + return {}; + } + + static async loginFail(data: LoginRequestModel) { + await new Promise((resolve) => setTimeout(resolve, 1000)); + + return { error: 'Invalid credentials' }; + } +} diff --git a/src/Umbraco.Web.UI.Client/apps/auth/src/auth.ts b/src/Umbraco.Web.UI.Client/apps/auth/src/auth.ts deleted file mode 100644 index f1965e558e..0000000000 --- a/src/Umbraco.Web.UI.Client/apps/auth/src/auth.ts +++ /dev/null @@ -1,4 +0,0 @@ -export default function() { - sessionStorage.setItem('is-authenticated', 'true'); - history.replaceState(null, '', 'section'); -} diff --git a/src/Umbraco.Web.UI.Client/apps/auth/src/login.element.ts b/src/Umbraco.Web.UI.Client/apps/auth/src/login.element.ts index ed4d97f166..eec0def905 100644 --- a/src/Umbraco.Web.UI.Client/apps/auth/src/login.element.ts +++ b/src/Umbraco.Web.UI.Client/apps/auth/src/login.element.ts @@ -3,22 +3,19 @@ import { css, CSSResultGroup, html, LitElement } from 'lit'; import { customElement, property, state } from 'lit/decorators.js'; import { UUIButtonState } from '@umbraco-ui/uui'; -import { UmbAuthContext } from './types'; +import { IUmbAuthContext } from './types'; import { UmbAuthLegacyContext } from './auth-legacy.context'; -import { UmbAuthNewContext } from './auth-new.context'; +import { UmbAuthContext } from './auth.context'; import './auth-layout.element'; @customElement('umb-login') export default class UmbLoginElement extends LitElement { - #authContext: UmbAuthContext; + #authContext: IUmbAuthContext; @property({ type: String, attribute: 'return-url' }) returnUrl = ''; - @property({ type: String, attribute: 'auth-url' }) - authUrl = ''; - @property({ type: Boolean }) isLegacy = false; @@ -34,9 +31,9 @@ export default class UmbLoginElement extends LitElement { constructor() { super(); if (this.isLegacy) { - this.#authContext = new UmbAuthLegacyContext(this.authUrl); + this.#authContext = new UmbAuthLegacyContext(); } else { - this.#authContext = new UmbAuthNewContext(this.authUrl); + this.#authContext = new UmbAuthContext(); } } diff --git a/src/Umbraco.Web.UI.Client/apps/auth/src/types.ts b/src/Umbraco.Web.UI.Client/apps/auth/src/types.ts index a5f911472e..b8f91c37dc 100644 --- a/src/Umbraco.Web.UI.Client/apps/auth/src/types.ts +++ b/src/Umbraco.Web.UI.Client/apps/auth/src/types.ts @@ -4,7 +4,12 @@ export type LoginRequestModel = { persist: boolean; }; -export interface UmbAuthContext { - authUrl: string; +export interface IUmbAuthContext { login(data: LoginRequestModel): Promise<{ error?: string }>; } + +export type ProblemDetails = { + type: string; + title: string; + message: string; +}; From fa210e79a39baada6f97321236a90c7d0d274d07 Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Wed, 24 May 2023 09:58:06 +0200 Subject: [PATCH 08/24] add vite build output --- src/Umbraco.Web.UI.Client/apps/auth/package.json | 1 + src/Umbraco.Web.UI.Client/apps/auth/vite.config.ts | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/src/Umbraco.Web.UI.Client/apps/auth/package.json b/src/Umbraco.Web.UI.Client/apps/auth/package.json index 18345cd875..0926ee2bdc 100644 --- a/src/Umbraco.Web.UI.Client/apps/auth/package.json +++ b/src/Umbraco.Web.UI.Client/apps/auth/package.json @@ -15,6 +15,7 @@ "scripts": { "dev": "vite", "build": "tsc && vite build", + "build:watch": "vite build --watch", "build:production": "tsc && vite build --mode production", "preview": "vite preview" } diff --git a/src/Umbraco.Web.UI.Client/apps/auth/vite.config.ts b/src/Umbraco.Web.UI.Client/apps/auth/vite.config.ts index 8da9c7dcb4..df6c489572 100644 --- a/src/Umbraco.Web.UI.Client/apps/auth/vite.config.ts +++ b/src/Umbraco.Web.UI.Client/apps/auth/vite.config.ts @@ -10,6 +10,11 @@ export default defineConfig({ fileName: 'main', }, sourcemap: true, + rollupOptions: { + external: [/^@umbraco-cms\/backoffice\//], + }, + outDir: '../../../Umbraco.Cms.StaticAssets/wwwroot/umbraco/login', + emptyOutDir: true, }, server: { fs: { From 02f6ecb1b48792b39d540d2eca243c6e2248d0c5 Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Wed, 24 May 2023 09:58:22 +0200 Subject: [PATCH 09/24] fix image import paths --- .../apps/auth/src/auth-layout.element.ts | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/apps/auth/src/auth-layout.element.ts b/src/Umbraco.Web.UI.Client/apps/auth/src/auth-layout.element.ts index 8ce9acb70b..005dda90e1 100644 --- a/src/Umbraco.Web.UI.Client/apps/auth/src/auth-layout.element.ts +++ b/src/Umbraco.Web.UI.Client/apps/auth/src/auth-layout.element.ts @@ -1,18 +1,16 @@ import { css, CSSResultGroup, html, LitElement, unsafeCSS } from 'lit'; import { customElement } from 'lit/decorators.js'; -import logoImg from '/umbraco_logomark_white.svg'; -import loginImg from '/login.jpeg'; @customElement('umb-auth-layout') export class UmbAuthLayoutElement extends LitElement { - + render() { return html`
@@ -22,7 +20,7 @@ export class UmbAuthLayoutElement extends LitElement {
`; } - + static styles: CSSResultGroup = [ css` #background { @@ -31,7 +29,7 @@ export class UmbAuthLayoutElement extends LitElement { background-position: 50%; background-repeat: no-repeat; background-size: cover; - background-image: url('${unsafeCSS(loginImg)}'); + background-image: url('login.jpeg'); width: 100vw; height: 100vh; } From 013c5c1b57f8417f3b92a8db451534895abf9a74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jesper=20M=C3=B8ller=20Jensen?= <26099018+JesmoDev@users.noreply.github.com> Date: Thu, 25 May 2023 18:10:09 +1200 Subject: [PATCH 10/24] call backend to login --- .../apps/auth/src/auth.context.ts | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/apps/auth/src/auth.context.ts b/src/Umbraco.Web.UI.Client/apps/auth/src/auth.context.ts index 50b9e92c85..b2c224191f 100644 --- a/src/Umbraco.Web.UI.Client/apps/auth/src/auth.context.ts +++ b/src/Umbraco.Web.UI.Client/apps/auth/src/auth.context.ts @@ -1,11 +1,23 @@ import { LoginRequestModel, IUmbAuthContext } from './types'; export class UmbAuthContext implements IUmbAuthContext { - readonly #AUTH_URL = '/umbraco/management/api/v1.0/security/back-office'; + readonly #AUTH_URL = '/umbraco/management/api/v1/security/back-office'; async login(data: LoginRequestModel) { //TODO: call authUrl with data - return UmbMockAPI.loginSuccess(data); + const request = new Request(this.#AUTH_URL + '/login', { + method: 'POST', + body: JSON.stringify({ + username: data.username, + password: data.password, + }), + headers: { + 'Content-Type': 'application/json', + }, + }); + const response = await fetch(request); + + return { error: response.ok ? undefined : response.statusText }; } } From 088d97f555fe41c0633ec7c7485da3b91cfcef8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jesper=20M=C3=B8ller=20Jensen?= <26099018+JesmoDev@users.noreply.github.com> Date: Thu, 25 May 2023 18:10:26 +1200 Subject: [PATCH 11/24] cleanup --- src/Umbraco.Web.UI.Client/apps/auth/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/apps/auth/index.html b/src/Umbraco.Web.UI.Client/apps/auth/index.html index de2b8a4cdc..75922ccae2 100644 --- a/src/Umbraco.Web.UI.Client/apps/auth/index.html +++ b/src/Umbraco.Web.UI.Client/apps/auth/index.html @@ -10,6 +10,6 @@ - + From 1de867d58668355f1610df058b35071b3aa13ab4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jesper=20M=C3=B8ller=20Jensen?= <26099018+JesmoDev@users.noreply.github.com> Date: Thu, 25 May 2023 18:27:13 +1200 Subject: [PATCH 12/24] cleanup --- src/Umbraco.Web.UI.Client/apps/auth/src/login.element.ts | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/apps/auth/src/login.element.ts b/src/Umbraco.Web.UI.Client/apps/auth/src/login.element.ts index eec0def905..0abc1641e2 100644 --- a/src/Umbraco.Web.UI.Client/apps/auth/src/login.element.ts +++ b/src/Umbraco.Web.UI.Client/apps/auth/src/login.element.ts @@ -1,5 +1,5 @@ import { UUITextStyles } from '@umbraco-ui/uui-css'; -import { css, CSSResultGroup, html, LitElement } from 'lit'; +import { css, CSSResultGroup, html, LitElement, nothing } from 'lit'; import { customElement, property, state } from 'lit/decorators.js'; import { UUIButtonState } from '@umbraco-ui/uui'; @@ -57,8 +57,6 @@ export default class UmbLoginElement extends LitElement { this._isFormValid = form.checkValidity(); - console.log('what', this._isFormValid); - if (!this._isFormValid) return; const formData = new FormData(form); @@ -76,7 +74,6 @@ export default class UmbLoginElement extends LitElement { if (error) return; - //TODO: Should redirecting be done here or in the context? location.href = this.returnUrl; }; @@ -139,7 +136,7 @@ export default class UmbLoginElement extends LitElement { } #renderErrorMessage() { - if (!this._loginError || this._loginState !== 'failed') return; + if (!this._loginError || this._loginState !== 'failed') return nothing; return html`

${this._loginError}

`; } From 8defd8b12df354034f2aa3081ab13084f546a396 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jesper=20M=C3=B8ller=20Jensen?= <26099018+JesmoDev@users.noreply.github.com> Date: Thu, 25 May 2023 18:27:20 +1200 Subject: [PATCH 13/24] add error text --- .../apps/auth/src/auth.context.ts | 26 ++++++++----------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/apps/auth/src/auth.context.ts b/src/Umbraco.Web.UI.Client/apps/auth/src/auth.context.ts index b2c224191f..274368a825 100644 --- a/src/Umbraco.Web.UI.Client/apps/auth/src/auth.context.ts +++ b/src/Umbraco.Web.UI.Client/apps/auth/src/auth.context.ts @@ -3,6 +3,16 @@ import { LoginRequestModel, IUmbAuthContext } from './types'; export class UmbAuthContext implements IUmbAuthContext { readonly #AUTH_URL = '/umbraco/management/api/v1/security/back-office'; + getErrorText(response: Response) { + switch (response.status) { + case 401: + return 'Oops! It seems like your login credentials are invalid or expired. Please double-check your username and password and try again.'; + + default: + return response.statusText; + } + } + async login(data: LoginRequestModel) { //TODO: call authUrl with data const request = new Request(this.#AUTH_URL + '/login', { @@ -17,20 +27,6 @@ export class UmbAuthContext implements IUmbAuthContext { }); const response = await fetch(request); - return { error: response.ok ? undefined : response.statusText }; - } -} - -class UmbMockAPI { - static async loginSuccess(data: LoginRequestModel) { - await new Promise((resolve) => setTimeout(resolve, 1000)); - - return {}; - } - - static async loginFail(data: LoginRequestModel) { - await new Promise((resolve) => setTimeout(resolve, 1000)); - - return { error: 'Invalid credentials' }; + return { error: response.ok ? undefined : this.getErrorText(response) }; } } From 47bed001ac5b90dc8c900457fda2dec15d125279 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jesper=20M=C3=B8ller=20Jensen?= <26099018+JesmoDev@users.noreply.github.com> Date: Fri, 26 May 2023 13:58:08 +1200 Subject: [PATCH 14/24] add repository --- .../apps/auth/src/auth.context.ts | 28 ++---------- .../apps/auth/src/auth.repository.ts | 44 +++++++++++++++++++ .../apps/auth/src/types.ts | 10 ++--- 3 files changed, 53 insertions(+), 29 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/apps/auth/src/auth.repository.ts diff --git a/src/Umbraco.Web.UI.Client/apps/auth/src/auth.context.ts b/src/Umbraco.Web.UI.Client/apps/auth/src/auth.context.ts index 274368a825..d648b49ee9 100644 --- a/src/Umbraco.Web.UI.Client/apps/auth/src/auth.context.ts +++ b/src/Umbraco.Web.UI.Client/apps/auth/src/auth.context.ts @@ -1,32 +1,12 @@ +import { UmbAuthRepository } from './auth.repository'; import { LoginRequestModel, IUmbAuthContext } from './types'; export class UmbAuthContext implements IUmbAuthContext { readonly #AUTH_URL = '/umbraco/management/api/v1/security/back-office'; - getErrorText(response: Response) { - switch (response.status) { - case 401: - return 'Oops! It seems like your login credentials are invalid or expired. Please double-check your username and password and try again.'; + #authRepository = new UmbAuthRepository(this.#AUTH_URL); - default: - return response.statusText; - } - } - - async login(data: LoginRequestModel) { - //TODO: call authUrl with data - const request = new Request(this.#AUTH_URL + '/login', { - method: 'POST', - body: JSON.stringify({ - username: data.username, - password: data.password, - }), - headers: { - 'Content-Type': 'application/json', - }, - }); - const response = await fetch(request); - - return { error: response.ok ? undefined : this.getErrorText(response) }; + public async login(data: LoginRequestModel) { + return this.#authRepository.login(data); } } diff --git a/src/Umbraco.Web.UI.Client/apps/auth/src/auth.repository.ts b/src/Umbraco.Web.UI.Client/apps/auth/src/auth.repository.ts new file mode 100644 index 0000000000..c35700a1f0 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/apps/auth/src/auth.repository.ts @@ -0,0 +1,44 @@ +import { LoginRequestModel } from './types'; + +export class UmbAuthRepository { + #authURL = ''; + + constructor(authUrl: string) { + this.#authURL = authUrl; + } + + public async login(data: LoginRequestModel) { + const request = new Request(this.#authURL + '/login', { + method: 'POST', + body: JSON.stringify({ + username: data.username, + password: data.password, + }), + headers: { + 'Content-Type': 'application/json', + }, + }); + const response = await fetch(request); + + //TODO: What kind of data does the old backoffice expect? + //NOTE: this conditionally adds error and data to the response object + return { + status: response.status, + ...(!response.ok && { error: this.#getErrorText(response) }), + ...(response.ok && { data: 'WHAT DATA SHOULD BE RETURNED?' }), + }; + } + + #getErrorText(response: Response) { + switch (response.status) { + case 401: + return 'Oops! It seems like your login credentials are invalid or expired. Please double-check your username and password and try again.'; + + case 500: + return "We're sorry, but the server encountered an unexpected error. Please refresh the page or try again later.."; + + default: + return response.statusText; + } + } +} diff --git a/src/Umbraco.Web.UI.Client/apps/auth/src/types.ts b/src/Umbraco.Web.UI.Client/apps/auth/src/types.ts index b8f91c37dc..aa6fdb629e 100644 --- a/src/Umbraco.Web.UI.Client/apps/auth/src/types.ts +++ b/src/Umbraco.Web.UI.Client/apps/auth/src/types.ts @@ -5,11 +5,11 @@ export type LoginRequestModel = { }; export interface IUmbAuthContext { - login(data: LoginRequestModel): Promise<{ error?: string }>; + login(data: LoginRequestModel): Promise; } -export type ProblemDetails = { - type: string; - title: string; - message: string; +export type LoginResponse = { + data?: string; + error?: string; + status: number; }; From 268cb6ac2339ff13130141c6aea82bb99d90b593 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jesper=20M=C3=B8ller=20Jensen?= <26099018+JesmoDev@users.noreply.github.com> Date: Fri, 26 May 2023 13:58:20 +1200 Subject: [PATCH 15/24] cleanup --- .../apps/auth/src/auth-legacy.context.ts | 4 ++-- src/Umbraco.Web.UI.Client/apps/auth/src/login.element.ts | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/apps/auth/src/auth-legacy.context.ts b/src/Umbraco.Web.UI.Client/apps/auth/src/auth-legacy.context.ts index 2920919eda..c7b8f05647 100644 --- a/src/Umbraco.Web.UI.Client/apps/auth/src/auth-legacy.context.ts +++ b/src/Umbraco.Web.UI.Client/apps/auth/src/auth-legacy.context.ts @@ -1,9 +1,9 @@ -import { LoginRequestModel, IUmbAuthContext } from './types'; +import { LoginRequestModel, IUmbAuthContext, LoginResponse } from './types'; export class UmbAuthLegacyContext implements IUmbAuthContext { readonly #AUTH_URL = '/umbraco/backoffice/umbracoapi/authentication/postlogin'; - login(data: LoginRequestModel): Promise<{ error?: string | undefined }> { + login(data: LoginRequestModel): Promise { throw new Error('Method not implemented.'); } } diff --git a/src/Umbraco.Web.UI.Client/apps/auth/src/login.element.ts b/src/Umbraco.Web.UI.Client/apps/auth/src/login.element.ts index 0abc1641e2..378b113ec1 100644 --- a/src/Umbraco.Web.UI.Client/apps/auth/src/login.element.ts +++ b/src/Umbraco.Web.UI.Client/apps/auth/src/login.element.ts @@ -67,12 +67,12 @@ export default class UmbLoginElement extends LitElement { this._loginState = 'waiting'; - const { error } = await this.#authContext.login({ username, password, persist }); + const response = await this.#authContext.login({ username, password, persist }); - this._loginError = error || ''; - this._loginState = error ? 'failed' : 'success'; + this._loginError = response.error || ''; + this._loginState = response.error ? 'failed' : 'success'; - if (error) return; + if (response.error) return; location.href = this.returnUrl; }; From d8268713f1937b666fef00f8b93e20b977b37e34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jesper=20M=C3=B8ller=20Jensen?= <26099018+JesmoDev@users.noreply.github.com> Date: Tue, 30 May 2023 19:11:35 +1200 Subject: [PATCH 16/24] fix linting errors --- .../apps/auth/src/auth-layout.element.ts | 4 +--- .../apps/auth/src/auth-legacy.context.ts | 2 +- src/Umbraco.Web.UI.Client/apps/auth/src/auth.context.ts | 4 ++-- .../apps/auth/src/auth.repository.ts | 2 +- src/Umbraco.Web.UI.Client/apps/auth/src/login.element.ts | 8 ++++---- 5 files changed, 9 insertions(+), 11 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/apps/auth/src/auth-layout.element.ts b/src/Umbraco.Web.UI.Client/apps/auth/src/auth-layout.element.ts index 005dda90e1..163ece1736 100644 --- a/src/Umbraco.Web.UI.Client/apps/auth/src/auth-layout.element.ts +++ b/src/Umbraco.Web.UI.Client/apps/auth/src/auth-layout.element.ts @@ -1,10 +1,8 @@ -import { css, CSSResultGroup, html, LitElement, unsafeCSS } from 'lit'; +import { css, CSSResultGroup, html, LitElement } from 'lit'; import { customElement } from 'lit/decorators.js'; @customElement('umb-auth-layout') export class UmbAuthLayoutElement extends LitElement { - - render() { return html`
diff --git a/src/Umbraco.Web.UI.Client/apps/auth/src/auth-legacy.context.ts b/src/Umbraco.Web.UI.Client/apps/auth/src/auth-legacy.context.ts index c7b8f05647..b9d3a0b1cd 100644 --- a/src/Umbraco.Web.UI.Client/apps/auth/src/auth-legacy.context.ts +++ b/src/Umbraco.Web.UI.Client/apps/auth/src/auth-legacy.context.ts @@ -1,4 +1,4 @@ -import { LoginRequestModel, IUmbAuthContext, LoginResponse } from './types'; +import { LoginRequestModel, IUmbAuthContext, LoginResponse } from './types.js'; export class UmbAuthLegacyContext implements IUmbAuthContext { readonly #AUTH_URL = '/umbraco/backoffice/umbracoapi/authentication/postlogin'; diff --git a/src/Umbraco.Web.UI.Client/apps/auth/src/auth.context.ts b/src/Umbraco.Web.UI.Client/apps/auth/src/auth.context.ts index d648b49ee9..2048cdf863 100644 --- a/src/Umbraco.Web.UI.Client/apps/auth/src/auth.context.ts +++ b/src/Umbraco.Web.UI.Client/apps/auth/src/auth.context.ts @@ -1,5 +1,5 @@ -import { UmbAuthRepository } from './auth.repository'; -import { LoginRequestModel, IUmbAuthContext } from './types'; +import { UmbAuthRepository } from './auth.repository.js'; +import { LoginRequestModel, IUmbAuthContext } from './types.js'; export class UmbAuthContext implements IUmbAuthContext { readonly #AUTH_URL = '/umbraco/management/api/v1/security/back-office'; diff --git a/src/Umbraco.Web.UI.Client/apps/auth/src/auth.repository.ts b/src/Umbraco.Web.UI.Client/apps/auth/src/auth.repository.ts index c35700a1f0..f615a915c1 100644 --- a/src/Umbraco.Web.UI.Client/apps/auth/src/auth.repository.ts +++ b/src/Umbraco.Web.UI.Client/apps/auth/src/auth.repository.ts @@ -1,4 +1,4 @@ -import { LoginRequestModel } from './types'; +import { LoginRequestModel } from './types.js'; export class UmbAuthRepository { #authURL = ''; diff --git a/src/Umbraco.Web.UI.Client/apps/auth/src/login.element.ts b/src/Umbraco.Web.UI.Client/apps/auth/src/login.element.ts index 378b113ec1..1c839d7d6e 100644 --- a/src/Umbraco.Web.UI.Client/apps/auth/src/login.element.ts +++ b/src/Umbraco.Web.UI.Client/apps/auth/src/login.element.ts @@ -3,11 +3,11 @@ import { css, CSSResultGroup, html, LitElement, nothing } from 'lit'; import { customElement, property, state } from 'lit/decorators.js'; import { UUIButtonState } from '@umbraco-ui/uui'; -import { IUmbAuthContext } from './types'; -import { UmbAuthLegacyContext } from './auth-legacy.context'; -import { UmbAuthContext } from './auth.context'; +import { IUmbAuthContext } from './types.js'; +import { UmbAuthLegacyContext } from './auth-legacy.context.js'; +import { UmbAuthContext } from './auth.context.js'; -import './auth-layout.element'; +import './auth-layout.element.js'; @customElement('umb-login') export default class UmbLoginElement extends LitElement { From 1010292da8055b6d3509bb1b2f9239cd4d35ca12 Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Tue, 30 May 2023 10:09:34 +0200 Subject: [PATCH 17/24] fix uui warnings --- src/Umbraco.Web.UI.Client/apps/auth/src/login.element.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/apps/auth/src/login.element.ts b/src/Umbraco.Web.UI.Client/apps/auth/src/login.element.ts index 1c839d7d6e..42b62971b8 100644 --- a/src/Umbraco.Web.UI.Client/apps/auth/src/login.element.ts +++ b/src/Umbraco.Web.UI.Client/apps/auth/src/login.element.ts @@ -2,8 +2,8 @@ import { UUITextStyles } from '@umbraco-ui/uui-css'; import { css, CSSResultGroup, html, LitElement, nothing } from 'lit'; import { customElement, property, state } from 'lit/decorators.js'; -import { UUIButtonState } from '@umbraco-ui/uui'; -import { IUmbAuthContext } from './types.js'; +import type { UUIButtonState } from '@umbraco-ui/uui'; +import type { IUmbAuthContext } from './types.js'; import { UmbAuthLegacyContext } from './auth-legacy.context.js'; import { UmbAuthContext } from './auth.context.js'; @@ -102,6 +102,7 @@ export default class UmbLoginElement extends LitElement { type="email" id="email" name="email" + label="Email" required required-message="Email is required">
@@ -111,6 +112,7 @@ export default class UmbLoginElement extends LitElement { From cf761f0d25a13cc6d7147bbe7f74742d47cc3ba7 Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Tue, 30 May 2023 10:09:44 +0200 Subject: [PATCH 18/24] package.json stuff --- src/Umbraco.Web.UI.Client/apps/auth/package.json | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/apps/auth/package.json b/src/Umbraco.Web.UI.Client/apps/auth/package.json index 0926ee2bdc..addf6d7ebf 100644 --- a/src/Umbraco.Web.UI.Client/apps/auth/package.json +++ b/src/Umbraco.Web.UI.Client/apps/auth/package.json @@ -1,5 +1,5 @@ { - "name": "umbraco-backoffice-auth", + "name": "@umbraco-cms/login", "version": "0.0.0", "license": "MIT", "author": { @@ -7,7 +7,6 @@ "email": "backoffice@umbraco.com" }, "type": "module", - "main": "dist/main.js", "module": "dist/main.js", "files": [ "dist" @@ -16,7 +15,6 @@ "dev": "vite", "build": "tsc && vite build", "build:watch": "vite build --watch", - "build:production": "tsc && vite build --mode production", "preview": "vite preview" } } From 409fb313b5e7b8984437e241802e9b2b85c3b393 Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Tue, 30 May 2023 10:10:02 +0200 Subject: [PATCH 19/24] prevent tsconfig from outputting anything --- src/Umbraco.Web.UI.Client/apps/auth/tsconfig.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/apps/auth/tsconfig.json b/src/Umbraco.Web.UI.Client/apps/auth/tsconfig.json index 7743919df7..3f90319d83 100644 --- a/src/Umbraco.Web.UI.Client/apps/auth/tsconfig.json +++ b/src/Umbraco.Web.UI.Client/apps/auth/tsconfig.json @@ -1,7 +1,7 @@ { "extends": "../../tsconfig.json", "compilerOptions": { - "outDir": "./types" + "declaration": false }, "include": ["src/**/*.ts"], "references": [ From 1b76bdcfd7a92f3921ca9f95c05dd75547cb42e2 Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Tue, 30 May 2023 10:10:15 +0200 Subject: [PATCH 20/24] set target to esnext to slim down build --- src/Umbraco.Web.UI.Client/apps/auth/vite.config.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Umbraco.Web.UI.Client/apps/auth/vite.config.ts b/src/Umbraco.Web.UI.Client/apps/auth/vite.config.ts index df6c489572..30c9cfb3bd 100644 --- a/src/Umbraco.Web.UI.Client/apps/auth/vite.config.ts +++ b/src/Umbraco.Web.UI.Client/apps/auth/vite.config.ts @@ -9,6 +9,7 @@ export default defineConfig({ formats: ['es'], fileName: 'main', }, + target: 'esnext', sourcemap: true, rollupOptions: { external: [/^@umbraco-cms\/backoffice\//], From 9b2924441992a5cd85237aa0f84cc61fcc4a0e17 Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Tue, 30 May 2023 10:10:51 +0200 Subject: [PATCH 21/24] add uui as a manual chunk --- src/Umbraco.Web.UI.Client/apps/auth/vite.config.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Umbraco.Web.UI.Client/apps/auth/vite.config.ts b/src/Umbraco.Web.UI.Client/apps/auth/vite.config.ts index 30c9cfb3bd..c542eee6bd 100644 --- a/src/Umbraco.Web.UI.Client/apps/auth/vite.config.ts +++ b/src/Umbraco.Web.UI.Client/apps/auth/vite.config.ts @@ -13,6 +13,11 @@ export default defineConfig({ sourcemap: true, rollupOptions: { external: [/^@umbraco-cms\/backoffice\//], + output: { + manualChunks: { + uui: ['@umbraco-ui/uui'], + }, + }, }, outDir: '../../../Umbraco.Cms.StaticAssets/wwwroot/umbraco/login', emptyOutDir: true, From 8020c51113add590deaaf865bf492516c4469f74 Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Tue, 30 May 2023 10:10:58 +0200 Subject: [PATCH 22/24] import correct css file --- src/Umbraco.Web.UI.Client/apps/auth/src/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/apps/auth/src/index.ts b/src/Umbraco.Web.UI.Client/apps/auth/src/index.ts index 90fcae79a8..43ef4da338 100644 --- a/src/Umbraco.Web.UI.Client/apps/auth/src/index.ts +++ b/src/Umbraco.Web.UI.Client/apps/auth/src/index.ts @@ -1,7 +1,7 @@ import 'element-internals-polyfill'; import '@umbraco-ui/uui-css/dist/uui-css.css'; -import '../../../src/shared/css/custom-properties.css'; +import '../../../src/css/umb-css.css'; import '@umbraco-ui/uui'; import './login.element.js'; From 96f2020433992665c26dd3fca13553a0d5b4028a Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Tue, 30 May 2023 10:17:19 +0200 Subject: [PATCH 23/24] remove checkValidity on each input event (Does not seem like it is very useful) --- .../apps/auth/src/login.element.ts | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/apps/auth/src/login.element.ts b/src/Umbraco.Web.UI.Client/apps/auth/src/login.element.ts index 42b62971b8..57ae36f50b 100644 --- a/src/Umbraco.Web.UI.Client/apps/auth/src/login.element.ts +++ b/src/Umbraco.Web.UI.Client/apps/auth/src/login.element.ts @@ -37,18 +37,6 @@ export default class UmbLoginElement extends LitElement { } } - //TODO: What is the correct type for this event? - #checkFormValidity = (e: any) => { - const form = e.target.closest('form') as HTMLFormElement; - - if (!form) return; - - //TODO: Why do we need to wait one frame for the check to work correctly? - requestAnimationFrame(() => { - this._isFormValid = form.checkValidity(); - }); - }; - #handleSubmit = async (e: SubmitEvent) => { e.preventDefault(); @@ -95,7 +83,7 @@ export default class UmbLoginElement extends LitElement {

${this.#greeting}

- + Email Date: Tue, 30 May 2023 10:17:44 +0200 Subject: [PATCH 24/24] add a check to each auth context to mark if it supports persisting the login --- .../apps/auth/src/auth-legacy.context.ts | 1 + src/Umbraco.Web.UI.Client/apps/auth/src/auth.context.ts | 1 + src/Umbraco.Web.UI.Client/apps/auth/src/login.element.ts | 8 +++++--- src/Umbraco.Web.UI.Client/apps/auth/src/types.ts | 1 + 4 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/apps/auth/src/auth-legacy.context.ts b/src/Umbraco.Web.UI.Client/apps/auth/src/auth-legacy.context.ts index b9d3a0b1cd..42b0679aab 100644 --- a/src/Umbraco.Web.UI.Client/apps/auth/src/auth-legacy.context.ts +++ b/src/Umbraco.Web.UI.Client/apps/auth/src/auth-legacy.context.ts @@ -2,6 +2,7 @@ import { LoginRequestModel, IUmbAuthContext, LoginResponse } from './types.js'; export class UmbAuthLegacyContext implements IUmbAuthContext { readonly #AUTH_URL = '/umbraco/backoffice/umbracoapi/authentication/postlogin'; + readonly supportsPersistLogin = true; login(data: LoginRequestModel): Promise { throw new Error('Method not implemented.'); diff --git a/src/Umbraco.Web.UI.Client/apps/auth/src/auth.context.ts b/src/Umbraco.Web.UI.Client/apps/auth/src/auth.context.ts index 2048cdf863..c38afcb618 100644 --- a/src/Umbraco.Web.UI.Client/apps/auth/src/auth.context.ts +++ b/src/Umbraco.Web.UI.Client/apps/auth/src/auth.context.ts @@ -3,6 +3,7 @@ import { LoginRequestModel, IUmbAuthContext } from './types.js'; export class UmbAuthContext implements IUmbAuthContext { readonly #AUTH_URL = '/umbraco/management/api/v1/security/back-office'; + readonly supportsPersistLogin = false; #authRepository = new UmbAuthRepository(this.#AUTH_URL); diff --git a/src/Umbraco.Web.UI.Client/apps/auth/src/login.element.ts b/src/Umbraco.Web.UI.Client/apps/auth/src/login.element.ts index 57ae36f50b..20bf03b421 100644 --- a/src/Umbraco.Web.UI.Client/apps/auth/src/login.element.ts +++ b/src/Umbraco.Web.UI.Client/apps/auth/src/login.element.ts @@ -105,9 +105,11 @@ export default class UmbLoginElement extends LitElement { required-message="Password is required"> - - Remember me - + ${this.#authContext.supportsPersistLogin + ? html` + Remember me + ` + : nothing} ${this.#renderErrorMessage()} diff --git a/src/Umbraco.Web.UI.Client/apps/auth/src/types.ts b/src/Umbraco.Web.UI.Client/apps/auth/src/types.ts index aa6fdb629e..114c515c5d 100644 --- a/src/Umbraco.Web.UI.Client/apps/auth/src/types.ts +++ b/src/Umbraco.Web.UI.Client/apps/auth/src/types.ts @@ -6,6 +6,7 @@ export type LoginRequestModel = { export interface IUmbAuthContext { login(data: LoginRequestModel): Promise; + supportsPersistLogin: boolean; } export type LoginResponse = {