remove temp login screen

This commit is contained in:
Jacob Overgaard
2024-04-05 15:28:39 +02:00
parent 8e56c64d65
commit 9a5fe32c61
24 changed files with 1 additions and 695 deletions

View File

@@ -1,19 +0,0 @@
import { expect, test } from '@playwright/test';
test('login', async ({ page }) => {
await page.goto('/');
// Fill input[name="email"]
await page.locator('input[name="email"]').fill('test@umbraco.com');
// Fill input[name="password"]
await page.locator('input[name="password"]').fill('test123456');
// Wait for console.log to be called
page.on('console', (message) => {
expect(message.text()).toBe('login');
});
// Click [aria-label="Login"]
await page.locator('[aria-label="Login"]').click();
});

View File

@@ -1,15 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="favicon.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Umbraco Auth</title>
<script type="module" src="/src/index.ts"></script>
<base href="/" />
</head>
<body class="uui-font uui-text" style="margin: 0; padding: 0; overflow: hidden">
<umb-login></umb-login>
</body>
</html>

View File

@@ -1,20 +0,0 @@
{
"name": "@umbraco-cms/login",
"version": "0.0.0",
"license": "MIT",
"author": {
"name": "Umbraco HQ",
"email": "backoffice@umbraco.com"
},
"type": "module",
"module": "dist/main.js",
"files": [
"dist"
],
"scripts": {
"dev": "vite",
"build": "tsc && vite build",
"build:watch": "vite build --watch",
"preview": "vite preview"
}
}

View File

@@ -1,108 +0,0 @@
import type { PlaywrightTestConfig } from '@playwright/test';
import { devices } from '@playwright/test';
/**
* Read environment variables from file.
* https://github.com/motdotla/dotenv
*/
// require('dotenv').config();
/**
* See https://playwright.dev/docs/test-configuration.
*/
const config: PlaywrightTestConfig = {
testDir: './e2e',
/* Maximum time one test can run for. */
timeout: 30 * 1000,
expect: {
/**
* Maximum time expect() should wait for the condition to be met.
* For example in `await expect(locator).toHaveText();`
*/
timeout: 5000,
},
/* Run tests in files in parallel */
fullyParallel: true,
/* Fail the build on CI if you accidentally left test.only in the source code. */
forbidOnly: !!process.env.CI,
/* Retry on CI only */
retries: process.env.CI ? 2 : 0,
/* Opt out of parallel tests on CI. */
workers: process.env.CI ? 1 : undefined,
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
reporter: 'html',
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
use: {
/* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */
actionTimeout: 0,
/* Base URL to use in actions like `await page.goto('/')`. */
// baseURL: 'http://localhost:3000',
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
trace: 'on-first-retry',
},
/* Configure projects for major browsers */
projects: [
{
name: 'chromium',
use: {
...devices['Desktop Chrome'],
},
},
{
name: 'firefox',
use: {
...devices['Desktop Firefox'],
},
},
{
name: 'webkit',
use: {
...devices['Desktop Safari'],
},
},
/* Test against mobile viewports. */
// {
// name: 'Mobile Chrome',
// use: {
// ...devices['Pixel 5'],
// },
// },
// {
// name: 'Mobile Safari',
// use: {
// ...devices['iPhone 12'],
// },
// },
/* Test against branded browsers. */
// {
// name: 'Microsoft Edge',
// use: {
// channel: 'msedge',
// },
// },
// {
// name: 'Google Chrome',
// use: {
// channel: 'chrome',
// },
// },
],
/* Folder for test artifacts such as screenshots, videos, traces, etc. */
// outputDir: 'test-results/',
/* Run your local dev server before starting the tests */
webServer: {
command: 'npm run dev',
port: 5173,
reuseExistingServer: !process.env.CI,
},
};
export default config;

View File

@@ -1,17 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 25.2.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 40 40" style="enable-background:new 0 0 40 40;" xml:space="preserve">
<style type="text/css">
.st0{fill-rule:evenodd;clip-rule:evenodd;fill:#3544B1;}
.st1{fill:#3544B1;}
</style>
<path class="st1" d="M0,20C0,8.9,9,0,20,0s20,9,20,20s-9,20-20,20C8.9,40,0,31,0,20L0,20z M19.6,26.8c-1.6,0-3.1-0.1-4.6-0.4
c-1.1-0.2-2.1-1-2.5-2c-0.5-1-0.7-2.6-0.7-4.8c0-1.1,0.1-2.3,0.2-3.4c0.1-1.1,0.3-2,0.4-2.7l0.1-0.7c0,0,0,0,0-0.1
c0-0.2-0.1-0.4-0.3-0.4l-2.6-0.4H9.6c-0.2,0-0.4,0.1-0.4,0.3c0,0.2-0.1,0.3-0.1,0.7c-0.1,0.8-0.3,1.5-0.4,2.6
c-0.2,1.2-0.3,2.4-0.3,3.5c-0.1,0.8-0.1,1.6,0,2.5c0.1,2.2,0.4,3.9,1.1,5.2c0.7,1.3,1.9,2.2,3.5,2.8c1.6,0.6,3.9,0.9,6.9,0.8h0.4
c2.9,0,5.2-0.3,6.9-0.8c1.6-0.6,2.8-1.5,3.5-2.8c0.7-1.3,1.1-3.1,1.1-5.2c0.1-0.8,0.1-1.6,0-2.5c0-1.2-0.1-2.4-0.3-3.5
c-0.1-1.1-0.3-1.8-0.4-2.6c-0.1-0.4-0.1-0.5-0.1-0.7c0-0.2-0.2-0.3-0.4-0.3h-0.1l-2.6,0.4c-0.2,0-0.3,0.2-0.3,0.4c0,0,0,0,0,0.1
l0.1,0.7c0.1,0.7,0.3,1.6,0.4,2.7c0.1,1.1,0.2,2.3,0.2,3.4c0,2.2-0.2,3.8-0.7,4.8c-0.5,1-1.4,1.8-2.5,2c-1.5,0.3-3.1,0.5-4.6,0.4
L19.6,26.8z"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1180 316"><path d="M.2 157.8C.3 70.6 71.1-.1 158.3.1S316.2 71 316.1 158.2s-70.8 157.7-157.9 157.7C70.8 315.9.1 245.1.2 157.8zm154.7 54.1c-12.3.4-24.5-.7-36.5-3.3-8.8-1.8-16.3-7.8-19.9-16-3.6-8.2-5.3-20.9-5.2-38.1.1-9 .6-17.9 1.7-26.8 1-8.7 2.1-15.8 3.1-21.5l1.1-5.6v-.5c0-1.6-1.1-2.9-2.6-3.2l-20.4-3.2h-.4c-1.5 0-2.8 1-3.1 2.5-.3 1.3-.6 2.3-1.2 5.4-1.2 6-2.2 11.8-3.4 20.4-1.3 9.3-2 18.6-2.3 27.9-.4 6.5-.4 13 0 19.6.5 17.3 3.4 31.1 8.9 41.4 5.5 10.3 14.7 17.8 27.7 22.3s31.2 6.8 54.4 6.7h2.9c23.3.1 41.4-2.1 54.4-6.7 13-4.5 22.2-12 27.7-22.3s8.4-24.1 8.9-41.4c.4-6.5.4-13 0-19.6-.3-9.3-1-18.7-2.3-27.9-1.2-8.4-2.3-14.3-3.4-20.4-.6-3.1-.8-4.1-1.2-5.4-.3-1.4-1.6-2.5-3.1-2.5h-.5l-20.4 3.2c-1.6.3-2.7 1.6-2.7 3.2v.5l1.1 5.6c1 5.6 2.1 12.8 3.1 21.5 1 8.9 1.6 17.9 1.7 26.8.2 17.1-1.6 29.8-5.2 38.1-3.6 8.2-11 14.2-19.8 16.1-12 2.5-24.2 3.6-36.5 3.3l-6.6-.1zm932.3-43.9c0-30.4 8.6-51.7 43.8-51.7s43.8 21.3 43.8 51.7-8.6 51.7-43.8 51.7-43.8-21.3-43.8-51.7zm65.3 0c0-21.1-2.7-33.1-21.5-33.1s-21.5 12-21.5 33.1 2.8 33.1 21.5 33.1c18.8 0 21.5-12 21.5-33.1zm-672.1 47.8c.5.9 1.5 1.5 2.5 1.4h8.2c1.6 0 2.9-1.3 2.9-2.9v-92.7c0-1.6-1.3-2.9-2.9-2.9h-16.3c-1.6 0-2.9 1.3-2.9 2.9v73.6c-7 3.9-14.9 5.9-22.8 5.8-10.4 0-15.6-4.5-15.6-14.6v-64.8c0-1.6-1.3-2.9-2.9-2.9h-16.4c-1.6 0-2.9 1.3-2.9 2.9v66.7c0 18.9 8.9 31.3 33.9 31.3 11.4-.1 22.6-3.7 32-10.2l2.9 6.5.3-.1zm184.1-68.1c0-18.7-9.3-31.4-32.6-31.4-11.3 0-22.3 3.4-31.6 9.8-4.1-6.1-12-9.8-25.3-9.8-10.7.2-21.1 3.8-29.7 10.2l-2.9-6.5c-.5-.9-1.5-1.5-2.5-1.4h-8.3c-1.6 0-2.9 1.3-2.9 2.9v92.8c0 1.6 1.3 2.9 2.9 2.9h16.3c1.6 0 2.9-1.3 2.9-2.9v-73.5c6.2-3.8 13.4-5.8 20.7-5.8 8.9 0 14 3.3 14 12.6v66.7c0 1.6 1.3 2.9 2.9 2.9h16.3c1.6 0 2.9-1.3 2.9-2.9v-73.6c6.2-3.9 13.4-5.9 20.7-5.8 8.6 0 14 3.3 14 12.6v66.7c0 1.6 1.3 2.9 2.9 2.9h16.3c1.6 0 2.9-1.3 2.9-2.9l.1-66.5zm50.4 61.7c9.3 6.9 20.5 10.5 32 10.2 28.8 0 39.4-19.3 39.4-51.7s-10.7-51.7-39.4-51.7c-9.4 0-18.5 2.7-26.4 7.7V94.2c0-1.6-1.2-2.9-2.8-3h-16.6c-1.6 0-2.9 1.3-2.9 2.9v120.3c0 1.6 1.3 2.9 2.9 2.9h8.2c1 0 2-.5 2.5-1.4l3.1-6.5zm26.8-8.5c-7.5 0-14.8-2-21.3-5.8v-54.4c6.5-3.8 13.8-5.8 21.3-5.8 19.3 0 22.3 14.8 22.3 32.9s-2.8 33.1-22.3 33.1zM868 135.7c-2.5-.3-5.1-.5-7.7-.5-8.8-.4-17.5 1.7-25.3 5.9v73.2c0 1.6-1.3 2.9-2.9 2.9h-16.3c-1.6 0-2.9-1.3-2.9-2.9v-92.7c0-1.6 1.3-2.9 2.9-2.9h8.2c1 0 2 .5 2.5 1.4l2.9 6.5c8.9-6.8 19.9-10.4 31.2-10.2 2.6 0 5.2.2 7.7.6 1.4 0 2.7 2.4 2.7 4v11.8c0 1.6-1.3 2.9-2.9 2.9h-.2m56.7 36.1c-9.8 1.2-15.6 4.9-15.6 15.2 0 7.5 3.3 14.6 15.2 14.6 7.5.1 14.9-2.2 21.1-6.5v-25.5l-20.7 2.2zm26.1 37.6c-8.5 6.7-19 10.3-29.8 10.2-25.5 0-33.9-15.8-33.9-31.6 0-21.3 13.8-30.4 36.1-32.1l22.1-1.8v-4.9c0-10.1-4.7-14-19.3-14-9.2 0-18.3 1.5-26.9 4.5h-.9c-1.6 0-2.9-1.3-2.9-2.9v-13.1c0-1.2.7-2.4 1.9-2.8 9.8-3.3 20.1-5 30.5-4.9 32.3 0 39.8 14.2 39.8 35.1V214c0 1.6-1.3 2.9-2.9 2.9h-8.2c-1 0-2-.5-2.5-1.4l-3.1-6.1zM1063 197h.9c1.6 0 2.9 1.3 2.9 2.9V213c0 1.2-.7 2.3-1.8 2.7-8.1 2.9-16.7 4.3-25.4 4.1-34.9 0-45.7-20.9-45.7-51.7s10.7-51.7 45.7-51.7c8.6-.2 17.1 1.1 25.2 4 1.1.4 1.9 1.5 1.8 2.7v13.1c0 1.6-1.3 2.9-2.9 2.9h-.9c-7.1-2.2-14.6-3.3-22-3.1-19.1 0-24.7 13.1-24.7 32.2s5.5 32.1 24.7 32.1c7.5.1 14.9-1 22-3.3" fill="#fff"/></svg>

Before

Width:  |  Height:  |  Size: 3.1 KiB

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 315.89 315.89"><path fill="#fff" d="M0 157.74a157.95 157.95 0 11158 158.15A157.95 157.95 0 010 157.74zm154.74 54.09a155.41 155.41 0 01-36.5-3.29 27.92 27.92 0 01-19.94-16q-5.35-12.34-5.21-38.1a243 243 0 011.69-26.84q1.55-13 3.09-21.46l1.07-5.59a2 2 0 000-.49 3.2 3.2 0 00-2.65-3.17l-20.37-3.22h-.44a3.19 3.19 0 00-3.11 2.48c-.35 1.31-.56 2.27-1.17 5.38-1.16 6-2.24 11.85-3.43 20.38a264.17 264.17 0 00-2.3 27.94 145.24 145.24 0 000 19.57q.72 25.94 8.9 41.42t27.72 22.3q19.53 6.81 54.43 6.66h2.91q34.94.15 54.41-6.66t27.71-22.3q8.17-15.53 8.91-41.42a145.24 145.24 0 000-19.57 266.84 266.84 0 00-2.3-27.94c-1.2-8.44-2.27-14.26-3.44-20.38-.61-3.11-.81-4.07-1.16-5.38a3.21 3.21 0 00-3.12-2.48h-.52l-20.38 3.18a3.2 3.2 0 00-2.68 3.17 4 4 0 000 .49l1.08 5.59q1.55 8.48 3.12 21.46a245.68 245.68 0 011.65 26.84q.27 25.69-5.21 38.07a27.9 27.9 0 01-19.76 16.07 155.19 155.19 0 01-36.48 3.29z"/></svg>

Before

Width:  |  Height:  |  Size: 942 B

View File

@@ -1,72 +0,0 @@
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`
<div id="background"></div>
<div id="logo">
<img src="umbraco_logomark_white.svg" alt="Umbraco" />
</div>
<div id="container">
<uui-box id="box">
<slot></slot>
</uui-box>
</div>
`;
}
static styles: CSSResultGroup = [
css`
#background {
position: fixed;
overflow: hidden;
background-position: 50%;
background-repeat: no-repeat;
background-size: cover;
background-image: url('login.jpeg');
width: 100vw;
height: 100vh;
}
#logo {
position: fixed;
top: var(--uui-size-space-5);
left: var(--uui-size-space-5);
height: 30px;
}
#logo img {
height: 100%;
}
#container {
position: relative;
display: flex;
align-items: center;
justify-content: center;
width: 100vw;
height: 100vh;
}
#box {
width: 500px;
padding: var(--uui-size-space-6) var(--uui-size-space-5) var(--uui-size-space-5) var(--uui-size-space-5);
}
#email,
#password {
width: 100%;
}
`,
];
}
declare global {
interface HTMLElementTagNameMap {
'umb-auth-layout': UmbAuthLayoutElement;
}
}

View File

@@ -1,10 +0,0 @@
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<LoginResponse> {
throw new Error('Method not implemented.');
}
}

View File

@@ -1,13 +0,0 @@
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';
readonly supportsPersistLogin = false;
#authRepository = new UmbAuthRepository(this.#AUTH_URL);
public async login(data: LoginRequestModel) {
return this.#authRepository.login(data);
}
}

View File

@@ -1,44 +0,0 @@
import { LoginRequestModel } from './types.js';
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;
}
}
}

View File

@@ -1,40 +0,0 @@
import { css, html, LitElement } from 'lit';
import { UUITextStyles } from '@umbraco-cms/backoffice/external/uui';
import { customElement } from 'lit/decorators.js';
@customElement('umb-external-login-provider-test')
export class UmbExternalLoginProviderTestElement extends LitElement {
render() {
return html`
<b>Custom External Login Provider</b>
<p>This is an example of a custom external login provider using the external login provider extension point</p>
<uui-button label="My custom login provider" look="primary"></uui-button>
`;
}
static styles = [
UUITextStyles,
css`
:host {
display: flex;
flex-direction: column;
gap: var(--uui-size-space-4);
padding: var(--uui-size-space-5);
border: 1px solid var(--uui-color-border);
background: var(--uui-color-surface-alt);
border-radius: var(--uui-border-radius);
}
p {
margin: 0;
}
`,
];
}
export default UmbExternalLoginProviderTestElement;
declare global {
interface HTMLElementTagNameMap {
'umb-external-login-provider-test': UmbExternalLoginProviderTestElement;
}
}

View File

@@ -1,53 +0,0 @@
import { css, html, LitElement } from 'lit';
import { UUITextStyles } from '@umbraco-ui/uui-css';
import { customElement } from 'lit/decorators.js';
@customElement('umb-external-login-provider-test2')
export class UmbExternalLoginProviderTest2Element extends LitElement {
render() {
return html`
<b>Another Custom External Login Provider</b>
<p>This is an example of another custom external login provider</p>
<uui-form-layout-item>
<uui-label id="emailLabel" for="email" slot="label" required>Email</uui-label>
<uui-input
type="email"
id="email"
name="email"
placeholder="Enter your email..."
required
required-message="Email is required"></uui-input>
</uui-form-layout-item>
<uui-button label="Custom login" look="primary"></uui-button>
`;
}
static styles = [
UUITextStyles,
css`
:host {
display: flex;
flex-direction: column;
gap: var(--uui-size-space-4);
padding: var(--uui-size-space-5);
border: 1px solid var(--uui-color-border);
background: var(--uui-color-surface-alt);
border-radius: var(--uui-border-radius);
}
p {
margin: 0;
}
uui-input {
width: 100%;
}
`,
];
}
export default UmbExternalLoginProviderTest2Element;
declare global {
interface HTMLElementTagNameMap {
'umb-external-login-provider-test2': UmbExternalLoginProviderTest2Element;
}
}

View File

@@ -1,29 +0,0 @@
// TODO: could these be renamed as login providers?
import type { ManifestExternalLoginProvider } from '@umbraco-cms/backoffice/extension-registry';
export const manifests: Array<ManifestExternalLoginProvider> = [
{
type: 'externalLoginProvider',
alias: 'Umb.ExternalLoginProvider.Test',
name: 'Test External Login Provider',
elementName: 'umb-external-login-provider-test',
element: () => import('./external-login-provider-test.element.js'),
weight: 2,
meta: {
label: 'Test External Login Provider',
pathname: 'test/test/test',
},
},
{
type: 'externalLoginProvider',
alias: 'Umb.ExternalLoginProvider.Test2',
name: 'Test External Login Provider 2',
elementName: 'umb-external-login-provider-test2',
element: () => import('./external-login-provider-test2.element.js'),
weight: 1,
meta: {
label: 'Test External Login Provider 2',
pathname: 'test/test/test',
},
},
];

View File

@@ -1,7 +0,0 @@
import 'element-internals-polyfill';
import '@umbraco-ui/uui-css/dist/uui-css.css';
import '../../../src/css/umb-css.css';
import '@umbraco-ui/uui';
import './login.element.js';

View File

@@ -1,148 +0,0 @@
import { UUITextStyles } from '@umbraco-ui/uui-css';
import { css, CSSResultGroup, html, LitElement, nothing } from 'lit';
import { customElement, property, state } from 'lit/decorators.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';
import './auth-layout.element.js';
@customElement('umb-login')
export default class UmbLoginElement extends LitElement {
#authContext: IUmbAuthContext;
@property({ type: String, attribute: 'return-url' })
returnUrl = '';
@property({ type: Boolean })
isLegacy = false;
@state()
private _loginState: UUIButtonState = undefined;
@state()
private _loginError = '';
constructor() {
super();
if (this.isLegacy) {
this.#authContext = new UmbAuthLegacyContext();
} else {
this.#authContext = new UmbAuthContext();
}
}
#handleSubmit = async (e: SubmitEvent) => {
e.preventDefault();
const form = e.target as HTMLFormElement;
if (!form) return;
if (!form.checkValidity()) return;
const formData = new FormData(form);
const username = formData.get('email') as string;
const password = formData.get('password') as string;
const persist = formData.has('persist');
this._loginState = 'waiting';
const response = await this.#authContext.login({ username, password, persist });
this._loginError = response.error || '';
this._loginState = response.error ? 'failed' : 'success';
if (response.error) return;
location.href = this.returnUrl;
};
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`
<umb-auth-layout>
<div class="uui-text">
<h1 class="uui-h3">${this.#greeting}</h1>
<uui-form>
<form id="LoginForm" name="login" @submit="${this.#handleSubmit}">
<uui-form-layout-item>
<uui-label id="emailLabel" for="email" slot="label" required>Email</uui-label>
<uui-input
type="email"
id="email"
name="email"
label="Email"
required
required-message="Email is required"></uui-input>
</uui-form-layout-item>
<uui-form-layout-item>
<uui-label id="passwordLabel" for="password" slot="label" required>Password</uui-label>
<uui-input-password
id="password"
name="password"
label="Password"
required
required-message="Password is required"></uui-input-password>
</uui-form-layout-item>
${this.#authContext.supportsPersistLogin
? html`<uui-form-layout-item>
<uui-checkbox name="persist" label="Remember me">Remember me</uui-checkbox>
</uui-form-layout-item>`
: nothing}
<uui-form-layout-item>${this.#renderErrorMessage()}</uui-form-layout-item>
<uui-button
type="submit"
label="Login"
look="primary"
color="positive"
state=${this._loginState}></uui-button>
</form>
</uui-form>
</div>
</umb-auth-layout>
`;
}
#renderErrorMessage() {
if (!this._loginError || this._loginState !== 'failed') return nothing;
return html`<p class="text-danger">${this._loginError}</p>`;
}
static styles: CSSResultGroup = [
UUITextStyles,
css`
#email,
#password {
width: 100%;
}
.text-danger {
color: var(--uui-color-danger-standalone);
}
`,
];
}
declare global {
interface HTMLElementTagNameMap {
'umb-login': UmbLoginElement;
}
}

View File

@@ -1,21 +0,0 @@
import { expect, fixture, html } from '@open-wc/testing';
import { type UmbTestRunnerWindow, defaultA11yConfig } from '@umbraco-cms/internal/test-utils';
import UmbLoginElement from './login.element.js';
describe('UmbLogin', () => {
let element: UmbLoginElement;
beforeEach(async () => {
element = await fixture(html`<umb-login></umb-login>`);
});
it('is defined with its own instance', () => {
expect(element).to.be.instanceOf(UmbLoginElement);
});
if ((window as UmbTestRunnerWindow).__UMBRACO_TEST_RUN_A11Y_TEST) {
it('passes the a11y audit', async () => {
await expect(element).to.be.accessible(defaultA11yConfig);
});
}
});

View File

@@ -1,16 +0,0 @@
export type LoginRequestModel = {
username: string;
password: string;
persist: boolean;
};
export interface IUmbAuthContext {
login(data: LoginRequestModel): Promise<LoginResponse>;
supportsPersistLogin: boolean;
}
export type LoginResponse = {
data?: string;
error?: string;
status: number;
};

View File

@@ -1,6 +0,0 @@
/// <reference types="vite/client" />
/*
interface ImportMetaEnv {
}
*/

View File

@@ -1,12 +0,0 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"declaration": false
},
"include": ["src/**/*.ts"],
"references": [
{
"path": "./tsconfig.node.json"
}
]
}

View File

@@ -1,9 +0,0 @@
{
"compilerOptions": {
"composite": true,
"module": "esnext",
"moduleResolution": "node",
"allowSyntheticDefaultImports": true
},
"include": ["vite.config.ts"]
}

View File

@@ -1,32 +0,0 @@
import { defineConfig } from 'vite';
import viteTSConfigPaths from 'vite-tsconfig-paths';
// https://vitejs.dev/config/
export default defineConfig({
build: {
lib: {
entry: 'src/index.ts',
formats: ['es'],
fileName: 'main',
},
target: 'esnext',
sourcemap: true,
rollupOptions: {
external: [/^@umbraco-cms\/backoffice\//],
output: {
manualChunks: {
uui: ['@umbraco-ui/uui'],
},
},
},
outDir: '../../../Umbraco.Cms.StaticAssets/wwwroot/umbraco/auth',
emptyOutDir: true,
},
server: {
fs: {
// Allow serving files from the global node_modules folder
allow: ['.', '../../node_modules'],
},
},
plugins: [viteTSConfigPaths()],
});

View File

@@ -117,7 +117,6 @@
"url": "https://umbraco.com"
},
"scripts": {
"auth:test:e2e": "npx playwright test --config apps/auth/",
"backoffice:test:e2e": "npx playwright test",
"build-storybook": "npm run wc-analyze && storybook build",
"build:for:cms": "npm run build && node ./devops/build/copy-to-cms.js",
@@ -146,7 +145,7 @@
"preview": "vite preview --open",
"storybook:build": "npm run wc-analyze && storybook build",
"storybook": "npm run wc-analyze && storybook dev -p 6006",
"test:e2e": "npm run auth:test:e2e && npm run backoffice:test:e2e",
"test:e2e": "npm run backoffice:test:e2e",
"test:dev": "web-test-runner --config ./web-test-runner.dev.config.mjs",
"test:dev-watch": "web-test-runner --watch --config ./web-test-runner.dev.config.mjs",
"test:watch": "web-test-runner --watch",