fix(core): Update dependencies and refactor registration process

This commit is contained in:
2024-10-04 15:43:36 +02:00
parent 629bf19845
commit 4deaafc3a2
18 changed files with 676 additions and 597 deletions
+8
View File
@@ -1,5 +1,13 @@
# Changelog # Changelog
## 2024-10-04 - 1.2.2 - fix(core)
Update dependencies and refactor registration process
- Updated @design.estate/dees-catalog, @design.estate/dees-domtools, and @design.estate/dees-element dependencies to their latest versions.
- Refactored registration process to improve validation flow.
- Improved user interface for login and registration prompts.
- Fixed issues with email and token validation during registration.
## 2024-10-04 - 1.2.1 - fix(core) ## 2024-10-04 - 1.2.1 - fix(core)
Added logging for user email login process and fixed client URL parsing Added logging for user email login process and fixed client URL parsing
+4 -4
View File
@@ -21,9 +21,9 @@
"@api.global/typedserver": "^3.0.51", "@api.global/typedserver": "^3.0.51",
"@api.global/typedsocket": "^3.0.1", "@api.global/typedsocket": "^3.0.1",
"@consentsoftware_private/catalog": "^1.0.73", "@consentsoftware_private/catalog": "^1.0.73",
"@design.estate/dees-catalog": "^1.1.8", "@design.estate/dees-catalog": "^1.1.10",
"@design.estate/dees-domtools": "^2.0.60", "@design.estate/dees-domtools": "^2.0.61",
"@design.estate/dees-element": "^2.0.38", "@design.estate/dees-element": "^2.0.39",
"@push.rocks/lik": "^6.0.15", "@push.rocks/lik": "^6.0.15",
"@push.rocks/qenv": "^6.0.5", "@push.rocks/qenv": "^6.0.5",
"@push.rocks/smartdata": "^5.2.10", "@push.rocks/smartdata": "^5.2.10",
@@ -44,7 +44,7 @@
"@push.rocks/webjwt": "^1.0.9", "@push.rocks/webjwt": "^1.0.9",
"@push.rocks/websetup": "^3.0.15", "@push.rocks/websetup": "^3.0.15",
"@push.rocks/webstore": "^2.0.20", "@push.rocks/webstore": "^2.0.20",
"@serve.zone/platformclient": "^1.0.11", "@serve.zone/platformclient": "^1.1.0",
"@tsclass/tsclass": "^4.1.2", "@tsclass/tsclass": "^4.1.2",
"@uptime.link/webwidget": "^1.1.2" "@uptime.link/webwidget": "^1.1.2"
}, },
+297 -294
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -3,6 +3,6 @@
*/ */
export const commitinfo = { export const commitinfo = {
name: '@idp.global/idp.global', name: '@idp.global/idp.global',
version: '1.2.1', version: '1.2.2',
description: 'An identity provider software managing user authentications, registrations, and sessions.' description: 'An identity provider software managing user authentications, registrations, and sessions.'
} }
+1
View File
@@ -20,6 +20,7 @@ export const runCli = async () => {
mongoDbUrl: await serviceQenv.getEnvVarOnDemand('MONGO_DB_URL'), mongoDbUrl: await serviceQenv.getEnvVarOnDemand('MONGO_DB_URL'),
}, },
websiteServer: websiteServer, websiteServer: websiteServer,
baseUrl: await serviceQenv.getEnvVarOnDemand('IDP_BASEURL'),
}); });
await reception.start(); await reception.start();
+2
View File
@@ -21,6 +21,7 @@ export interface IReceptionOptions {
name: string; name: string;
mongoDescriptor: plugins.smartdata.IMongoDescriptor; mongoDescriptor: plugins.smartdata.IMongoDescriptor;
websiteServer: plugins.typedserver.utilityservers.UtilityWebsiteServer; websiteServer: plugins.typedserver.utilityservers.UtilityWebsiteServer;
baseUrl: string;
} }
export class Reception { export class Reception {
@@ -55,6 +56,7 @@ export class Reception {
* starts the reception instance * starts the reception instance
*/ */
public async start() { public async start() {
await this.szPlatformClient.init(await this.serviceQenv.getEnvVarOnDemand('SERVEZONE_PLATFROM_AUTHORIZATION'));
logger.log('info', 'starting reception'); logger.log('info', 'starting reception');
logger.log('info', 'adding typedrouter to website server'); logger.log('info', 'adding typedrouter to website server');
this.options.websiteServer.typedrouter.addTypedRouter(this.typedrouter); this.options.websiteServer.typedrouter.addTypedRouter(this.typedrouter);
+3 -3
View File
@@ -152,9 +152,9 @@ export class ReceptionMailer {
</html> </html>
`; `;
public sendRegistrationEmail(signupSessionArg: RegistrationSession, validationTokenArg: string) { public async sendRegistrationEmail(signupSessionArg: RegistrationSession, validationTokenArg: string) {
this.receptionRef.szPlatformClient.emailConnector.sendEmail({ this.receptionRef.szPlatformClient.emailConnector.sendEmail({
from: 'workspace.global <noreply@mail.workspace.global>', from: `idp.global@${this.receptionRef.options.baseUrl} <noreply@mail.workspace.global>`,
title: 'Verify your Email Address!', title: 'Verify your Email Address!',
to: signupSessionArg.emailAddress, to: signupSessionArg.emailAddress,
body: this.createBodyString(` body: this.createBodyString(`
@@ -163,7 +163,7 @@ export class ReceptionMailer {
}">${signupSessionArg.emailAddress}</a></h1> }">${signupSessionArg.emailAddress}</a></h1>
<p>It looks like you requested to register an account with us. We just want to make sure it really was you.</p> <p>It looks like you requested to register an account with us. We just want to make sure it really was you.</p>
<p>In case it was you, <b>please continue with the registration process by clicking the button below</b>. Otherwise, please ignore this email.</p> <p>In case it was you, <b>please continue with the registration process by clicking the button below</b>. Otherwise, please ignore this email.</p>
<a href="https://registration.workspace.global/finishregistration?validationtoken=${encodeURI( <a href="${this.receptionRef.options.baseUrl}/finishregistration?validationtoken=${encodeURI(
validationTokenArg validationTokenArg
)}"><div class="button"> )}"><div class="button">
continue with registration continue with registration
@@ -63,6 +63,7 @@ export class RegistrationSessionManager {
new plugins.typedrequest.TypedHandler<plugins.lointReception.request.IReq_AfterRegistrationEmailClicked>( new plugins.typedrequest.TypedHandler<plugins.lointReception.request.IReq_AfterRegistrationEmailClicked>(
'afterRegistrationEmailClicked', 'afterRegistrationEmailClicked',
async (requestData) => { async (requestData) => {
console.log(requestData);
const signupSession = await this.registrationSessions.find(async (itemArg) => const signupSession = await this.registrationSessions.find(async (itemArg) =>
itemArg.validateEmailToken(requestData.token) itemArg.validateEmailToken(requestData.token)
); );
+1 -1
View File
@@ -3,6 +3,6 @@
*/ */
export const commitinfo = { export const commitinfo = {
name: '@idp.global/idp.global', name: '@idp.global/idp.global',
version: '1.2.1', version: '1.2.2',
description: 'An identity provider software managing user authentications, registrations, and sessions.' description: 'An identity provider software managing user authentications, registrations, and sessions.'
} }
@@ -16,13 +16,13 @@ import { IdpState } from '../idp.state.js';
declare global { declare global {
interface HTMLElementTagNameMap { interface HTMLElementTagNameMap {
'idp-logincontainer': IdpLogincontainer; 'idp-centercontainer': IdpCenterContainer;
} }
} }
@customElement('idp-logincontainer') @customElement('idp-centercontainer')
export class IdpLogincontainer extends DeesElement { export class IdpCenterContainer extends DeesElement {
public static demo = () => html`<idp-logincontainer></idp-logincontainer>`; public static demo = () => html`<idp-centercontainer></idp-centercontainer>`;
constructor() { constructor() {
super(); super();
@@ -47,9 +47,9 @@ export class IdpLogincontainer extends DeesElement {
justify-content: center; justify-content: center;
align-items: center; align-items: center;
opacity: 0; opacity: 0;
transition: all 0.2s; transition: all 0.1s;
transition-delay: 0.2s; transition-delay: 0.05s;
transform: translate3d(0px, 20px, 0px); transform: translate3d(0px, 8px, 0px);
pointer-events: none; pointer-events: none;
} }
@@ -107,23 +107,40 @@ export class IdpLogincontainer extends DeesElement {
<div class="loginblock"> <div class="loginblock">
<h1>idp.global</h1> <h1>idp.global</h1>
<div class="contentSpacer"> <div class="contentSpacer">
<idp-login></idp-login> <slot></slot>
</div> </div>
<div class="legalinfo"> <div class="legalinfo">
<a href="https://legal.task.vc/" target="_blank">Legal Info</a> <a href="https://legal.task.vc/" target="_blank">Legal Info</a>
| <a href="https://task.vc/" target="_blank">Company Website</a> | <a href="https://task.vc/" target="_blank">Company Website</a>
| <a href="https://support.task.vc/" target="_blank">Support</a> | <a href="https://support.task.vc/" target="_blank">Support</a>
| SSO v${commitinfo.version} | idp.global v${commitinfo.version}
</div> </div>
</div> </div>
</div> </div>
`; `;
} }
public async firstUpdated() { public async show() {
await this.updateComplete;
const domtoolsInstance = await this.domtoolsPromise;
const done = plugins.smartpromise.defer();
requestAnimationFrame(async () => { requestAnimationFrame(async () => {
this.shadowRoot.querySelector('.mainContainer').classList.add('show'); this.shadowRoot.querySelector('.mainContainer').classList.add('show');
this.shadowRoot.querySelector('idp-login').focus(); await domtoolsInstance.convenience.smartdelay.delayFor(200);
done.resolve();
}); });
return done.promise;
}
public async hide() {
await this.updateComplete;
const domtoolsInstance = await this.domtoolsPromise;
const done = plugins.smartpromise.defer();
requestAnimationFrame(async () => {
this.shadowRoot.querySelector('.mainContainer').classList.remove('show');
await domtoolsInstance.convenience.smartdelay.delayFor(200);
done.resolve();
});
return done.promise;
} }
} }
+51 -31
View File
@@ -17,16 +17,17 @@ import '@uptime.link/webwidget';
import '@design.estate/dees-catalog'; import '@design.estate/dees-catalog';
import { DeesForm, DeesFormSubmit, DeesInputText } from '@design.estate/dees-catalog'; import { DeesForm, DeesFormSubmit, DeesInputText } from '@design.estate/dees-catalog';
import { IdpState } from '../idp.state.js';
declare global { declare global {
interface HTMLElementTagNameMap { interface HTMLElementTagNameMap {
'idp-login': IdpLogin; 'idp-loginprompt': IdpLoginPrompt;
} }
} }
@customElement('idp-login') @customElement('idp-loginprompt')
export class IdpLogin extends DeesElement { export class IdpLoginPrompt extends DeesElement {
public static demo = () => html`<idp-login></idp-login>`; public static demo = () => html`<idp-loginprompt></idp-loginprompt>`;
@property() @property()
public productOfInterest: string; public productOfInterest: string;
@@ -68,32 +69,37 @@ export class IdpLogin extends DeesElement {
public render(): TemplateResult { public render(): TemplateResult {
return html` return html`
<div class="boxcontent"> <idp-centercontainer>
<dees-form <div class="boxcontent">
id="loginForm" <dees-form
@formData="${(eventArg) => { id="loginForm"
this.login({ @formData="${(eventArg) => {
emailAddress: eventArg.detail.data.emailAddress, this.login({
passwordArg: eventArg.detail.data.password, emailAddress: eventArg.detail.data.emailAddress,
}); passwordArg: eventArg.detail.data.password,
}}" });
> }}"
<dees-input-text >
id="loginEmailInput" <dees-input-text
.required=${true} id="loginEmailInput"
key="emailAddress" .required=${true}
label="Email-Address or Username" key="emailAddress"
></dees-input-text> label="Email-Address or Username"
<dees-input-text ></dees-input-text>
.id=${'loginPasswordInput'} <dees-input-text
.key=${'password'} .id=${'loginPasswordInput'}
.label=${'Password'} .key=${'password'}
.isPasswordBool=${true} .label=${'Password'}
></dees-input-text> .isPasswordBool=${true}
<dees-form-submit id="loginSubmitButton"></dees-form-submit> ></dees-input-text>
</dees-form> <dees-form-submit id="loginSubmitButton"></dees-form-submit>
<dees-button type="discreet" class="registerButton">Register instead</dees-button> </dees-form>
</div> <dees-button type="discreet" class="registerButton" @click=${async () => {
const idpState = await IdpState.getSingletonInstance();
idpState.domtools.router.pushUrl('/register');
}}>Register instead</dees-button>
</div>
</idp-centercontainer>
`; `;
} }
@@ -206,6 +212,20 @@ export class IdpLogin extends DeesElement {
} }
public async focus() { public async focus() {
(this.shadowRoot.querySelector('#loginEmailInput') as plugins.deesCatalog.DeesInputText).focus(); (
this.shadowRoot.querySelector('#loginEmailInput') as plugins.deesCatalog.DeesInputText
).focus();
}
public async show() {
await this.updateComplete;
const centerContainer = this.shadowRoot.querySelector('idp-centercontainer');
await centerContainer.show();
}
public async hide() {
await this.updateComplete;
const centerContainer = this.shadowRoot.querySelector('idp-centercontainer');
await centerContainer.hide();
} }
} }
+43 -28
View File
@@ -17,6 +17,7 @@ import '@uptime.link/webwidget';
import '@design.estate/dees-catalog'; import '@design.estate/dees-catalog';
import { DeesForm, DeesFormSubmit, DeesInputText } from '@design.estate/dees-catalog'; import { DeesForm, DeesFormSubmit, DeesInputText } from '@design.estate/dees-catalog';
import { IdpState } from '../idp.state.js';
declare global { declare global {
interface HTMLElementTagNameMap { interface HTMLElementTagNameMap {
@@ -56,14 +57,6 @@ export class IdpRegistrationPrompt extends DeesElement {
color: ${cssManager.bdTheme('#333333', '#ffffff')}; color: ${cssManager.bdTheme('#333333', '#ffffff')};
} }
.box {
opacity: 0;
cursor: pointer;
overflow: hidden;
transition: all 0.2s ease;
height: 0px;
}
.boxcontent { .boxcontent {
margin: 0px 20px; margin: 0px 20px;
} }
@@ -79,31 +72,41 @@ export class IdpRegistrationPrompt extends DeesElement {
color: #fff; color: #fff;
transform: scale(1.02); transform: scale(1.02);
} }
.loginButton {
margin-top: 16px;
}
`, `,
]; ];
public render(): TemplateResult { public render(): TemplateResult {
return html` return html`
<div class="boxcontent"> <idp-centercontainer>
<dees-form <div class="boxcontent">
id="registrationForm" <dees-form
@formData="${(eventArg) => { id="registrationForm"
this.register({ @formData="${(eventArg) => {
emailAddress: eventArg.detail.data.emailAddress, this.register({
}); emailAddress: eventArg.detail.data.emailAddress,
}}" });
> }}"
<dees-input-text >
.required=${true} <dees-input-text
key="emailAddress" .required=${true}
label="Email-Address" key="emailAddress"
></dees-input-text> label="Email-Address"
<dees-input-checkbox ></dees-input-text>
.label="${'Agree to the Terms and Conditions'}" <dees-input-checkbox
></dees-input-checkbox> .label="${'Agree to the Terms and Conditions'}"
<dees-form-submit>Send Verification Email</dees-form-submit> ></dees-input-checkbox>
</dees-form> <dees-form-submit>Send Verification Email</dees-form-submit>
</div> </dees-form>
<dees-button type="discreet" class="loginButton" @click=${async () => {
const idpState = await IdpState.getSingletonInstance();
idpState.domtools.router.pushUrl('/login');
}}>Login instead</dees-button>
</div>
</idp-centercontainer>
`; `;
} }
@@ -186,4 +189,16 @@ export class IdpRegistrationPrompt extends DeesElement {
return null; return null;
} }
} }
public async show() {
await this.updateComplete;
const centerContainer = this.shadowRoot.querySelector('idp-centercontainer');
await centerContainer.show();
}
public async hide() {
await this.updateComplete;
const centerContainer = this.shadowRoot.querySelector('idp-centercontainer');
await centerContainer.hide();
}
} }
+206 -215
View File
@@ -14,7 +14,6 @@ import {
@customElement('idp-registration-stepper') @customElement('idp-registration-stepper')
export class IdpRegistrationStepper extends DeesElement { export class IdpRegistrationStepper extends DeesElement {
@state() @state()
private usedSubTemplate: TemplateResult; private usedSubTemplate: TemplateResult;
@@ -67,230 +66,222 @@ export class IdpRegistrationStepper extends DeesElement {
public async firstUpdated() { public async firstUpdated() {
const idpState = await IdpState.getSingletonInstance(); const idpState = await IdpState.getSingletonInstance();
await this.domtoolsPromise; await this.domtoolsPromise;
this.domtools.router.on(`/finishregistration`, async (routeArg) => { const parsedUrl = plugins.smarturl.Smarturl.createFromUrl(window.location.href);
this.storedData.validationTokenUrlParam = routeArg.queryParams.validationtoken; this.storedData.validationTokenUrlParam = parsedUrl.searchParams['validationtoken'];
if (!this.storedData.validationTokenUrlParam) { console.log(`validationToken is ${this.storedData.validationTokenUrlParam}`);
this.usedSubTemplate = html` if (!this.storedData.validationTokenUrlParam) {
You need a validation token, but we couldn't find one. Please contact workspace.global support. this.usedSubTemplate = html`
`; You need a validation token, but we couldn't find one. Please contact workspace.global
await this.domtools.convenience.smartdelay.delayFor(5000); support.
this.usedSubTemplate = html` Redirecting you to workspace.global support... `; `;
await this.domtools.convenience.smartdelay.delayFor(2000); await this.domtools.convenience.smartdelay.delayFor(5000);
window.location.href = 'https://support.workspace.global'; window.location.href = '/';
return; return;
} }
// lets verify the info; // lets verify the info;
let tokenErrorMessage: string; let tokenErrorMessage: string;
const resAfterRegEmailClicked = const resAfterRegEmailClicked = await idpState.idpClient.requests.afterRegistrationEmailClicked
await idpState.idpClient.requests.afterRegistrationEmailClicked .fire({
.fire({ token: this.storedData.validationTokenUrlParam,
token: this.storedData.validationTokenUrlParam, })
}) .catch(
.catch( (
( err: (typeof DeesElement)['prototype']['domtools']['convenience']['typedrequest']['TypedResponseError']['prototype']
err: typeof DeesElement['prototype']['domtools']['convenience']['typedrequest']['TypedResponseError']['prototype'] ) => {
) => { tokenErrorMessage = err.errorText;
tokenErrorMessage = err.errorText; return;
return; }
} );
);
if (!resAfterRegEmailClicked || !resAfterRegEmailClicked.email) { console.log(resAfterRegEmailClicked);
this.usedSubTemplate = html`
the supplied validation token does not match any registration sessions.<br />
${tokenErrorMessage ? html`Reason: ${tokenErrorMessage}` : null}
`;
await this.domtools.convenience.smartdelay.delayFor(5000);
this.usedSubTemplate = html`redirecting you for further support... `;
await this.domtools.convenience.smartdelay.delayFor(1000);
window.location.href = 'https://support.workspace.global';
return;
} else {
this.storedData.email = resAfterRegEmailClicked.email;
}
// lets continue with UI if (!resAfterRegEmailClicked || !resAfterRegEmailClicked.email) {
this.usedSubTemplate = html`<dees-stepper this.usedSubTemplate = html`
.steps=${[ the supplied validation token does not match any registration sessions.<br />
{ ${tokenErrorMessage ? html`Reason: ${tokenErrorMessage}` : null}
title: 'What is your name?', `;
content: html` await this.domtools.convenience.smartdelay.delayFor(5000);
<dees-form> idpState.domtools.router.pushUrl('/');
<dees-input-text return;
key="email" } else {
label="Your Email" this.storedData.email = resAfterRegEmailClicked.email;
value="${this.storedData.email}" }
disabled
></dees-input-text>
<dees-input-text key="firstName" required label="First Name"></dees-input-text>
<dees-input-text key="lastName" required label="Last Name"></dees-input-text>
<dees-form-submit>Next</dees-form-submit>
</dees-form>
`,
validationFunc: async (stepperArg, elementArg) => {
const deesForm: plugins.deesCatalog.DeesForm = elementArg.querySelector('dees-form');
deesForm.addEventListener('formData', async (eventArg: CustomEvent) => {
const response = await idpState.idpClient.requests.setData
.fire({
token: this.storedData.validationTokenUrlParam,
userData: {
name: `${eventArg.detail.data.firstName} ${eventArg.detail.data.lastName}`,
connectedOrgs: null,
email: null,
status: null,
username: null,
},
})
.catch(
(
errArg: typeof DeesElement['prototype']['domtools']['convenience']['typedrequest']['TypedResponseError']['prototype']
) => {
deesForm.setStatus('error', errArg.errorText);
}
);
deesForm.setStatus('success', 'ok!');
stepperArg.goNext();
});
},
onReturnToStepFunc: async (stepperArg, stepElementArg) => {
const deesForm = stepElementArg.querySelector('dees-form');
deesForm.setStatus('normal', 'Edit and Next');
},
},
{
title: 'What is your mobile number?',
content: html`
<dees-form>
<dees-input-text
key="mobileNumber"
required
label="Your Mobile Number"
></dees-input-text>
<dees-form-submit>Next</dees-form-submit>
</dees-form>
`,
validationFunc: async (stepperArg, elementArg) => {
const deesForm: plugins.deesCatalog.DeesForm = elementArg.querySelector('dees-form');
deesForm.addEventListener('formData', async (eventArg: CustomEvent) => {
const response = await idpState.idpClient.requests.mobileNumberVerification
.fire({
token: this.storedData.validationTokenUrlParam,
mobileNumber: eventArg.detail.data.mobileNumber,
})
.catch(
(
errArg: typeof DeesElement['prototype']['domtools']['convenience']['typedrequest']['TypedResponseError']['prototype']
) => {
deesForm.setStatus('error', errArg.errorText);
}
);
deesForm.setStatus('success', 'ok!');
stepperArg.goNext();
});
},
onReturnToStepFunc: async (stepperArg, stepElementArg) => {
const deesForm = stepElementArg.querySelector('dees-form');
deesForm.setStatus('normal', 'Edit and Next');
},
},
{
title: 'What is the Verification Code?',
content: html`
<dees-form>
<dees-input-text
key="verificationCode"
required
label="Verification Code"
></dees-input-text>
<dees-form-submit>Next</dees-form-submit>
</dees-form>
`,
validationFunc: async (stepperArg, elementArg) => {
const deesForm: plugins.deesCatalog.DeesForm = elementArg.querySelector('dees-form');
deesForm.addEventListener('formData', async (eventArg: CustomEvent) => {
const response = await idpState.idpClient.requests.mobileNumberVerification.fire({
token: this.storedData.validationTokenUrlParam,
verificationCode: eventArg.detail.data.verificationCode,
});
if (response.verficationCodeOk) { // lets continue with UI
deesForm.setStatus('success', 'ok!'); this.usedSubTemplate = html`<dees-stepper
stepperArg.goNext(); .steps=${[
} else { {
deesForm.setStatus('error', 'wrong code!'); title: 'What is your name?',
await this.domtools.convenience.smartdelay.delayFor(3000); content: html`
deesForm.setStatus('normal', 'Retry And Next!'); <dees-form>
} <dees-input-text
}); key="email"
}, label="Your Email"
onReturnToStepFunc: async (stepperArg, stepElementArg) => { value="${this.storedData.email}"
stepperArg.goBack(); disabled
const deesForm = stepElementArg.querySelector('dees-form'); ></dees-input-text>
deesForm.setStatus('normal', 'Next'); <dees-input-text key="firstName" required label="First Name"></dees-input-text>
}, <dees-input-text key="lastName" required label="Last Name"></dees-input-text>
}, <dees-form-submit>Next</dees-form-submit>
{ </dees-form>
title: 'Create a secure password:', `,
content: html` validationFunc: async (stepperArg, elementArg) => {
<dees-form> const deesForm: plugins.deesCatalog.DeesForm = elementArg.querySelector('dees-form');
<dees-input-text deesForm.addEventListener('formData', async (eventArg: CustomEvent) => {
key="password" const response = await idpState.idpClient.requests.setData
required .fire({
label="Your New Secure Password"
></dees-input-text>
<dees-form-submit>Next</dees-form-submit>
</dees-form>
`,
validationFunc: async (stepperArg, elementArg) => {
const deesForm: plugins.deesCatalog.DeesForm = elementArg.querySelector('dees-form');
deesForm.addEventListener('formData', async (eventArg: CustomEvent) => {
const response = await idpState.idpClient.requests.setData.fire({
token: this.storedData.validationTokenUrlParam, token: this.storedData.validationTokenUrlParam,
userData: { userData: {
username: null, name: `${eventArg.detail.data.firstName} ${eventArg.detail.data.lastName}`,
email: null,
name: null,
connectedOrgs: null, connectedOrgs: null,
email: null,
status: null, status: null,
password: eventArg.detail.data.password, username: null,
}, },
}); })
const finishRegistrationResponse = .catch(
await idpState.idpClient.requests.finishRegistration.fire({ (
token: this.storedData.validationTokenUrlParam, errArg: (typeof DeesElement)['prototype']['domtools']['convenience']['typedrequest']['TypedResponseError']['prototype']
}); ) => {
deesForm.setStatus('pending', 'User created!'); deesForm.setStatus('error', errArg.errorText);
await this.domtools.convenience.smartdelay.delayFor(500);
deesForm.setStatus('pending', 'Obtaining Refresh Token...');
const loginResponse = await idpState.idpClient.requests.loginWithUserNameAndPassword.fire(
{
username: this.storedData.email,
password: eventArg.detail.data.password,
} }
); );
this.storedData.refreshToken = loginResponse.refreshToken; deesForm.setStatus('success', 'ok!');
stepperArg.goNext();
deesForm.setStatus('pending', 'Obtaining JWT...'); });
const jwtResponse = await idpState.idpClient.requests.obtainJwt.fire({
refreshToken: this.storedData.refreshToken,
});
deesForm.setStatus('pending', 'Obtaining Transfer Token...');
await idpState.idpClient.setJwt(jwtResponse.jwt);
await idpState.idpClient.getTransferTokenAndSwitchToLocation('https://sso.workspace.global/afterregistration');
});
},
}, },
] as plugins.deesCatalog.IStep[]} onReturnToStepFunc: async (stepperArg, stepElementArg) => {
></dees-stepper>`; const deesForm = stepElementArg.querySelector('dees-form');
await this.domtools.convenience.smartdelay.delayFor(100); deesForm.setStatus('normal', 'Edit and Next');
}); },
this.domtools.router.on('/', async () => { },
this.usedSubTemplate = html`Hm, this is app is not meant for what you are trying to do :) `; {
await this.domtools.convenience.smartdelay.delayFor(2000); title: 'What is your mobile number?',
this.usedSubTemplate = html`Redirecting you now...`; content: html`
window.location.href = `https://workspace.global`; <dees-form>
}); <dees-input-text
this.domtools.router._handleRouteState(); key="mobileNumber"
required
label="Your Mobile Number"
></dees-input-text>
<dees-form-submit>Next</dees-form-submit>
</dees-form>
`,
validationFunc: async (stepperArg, elementArg) => {
const deesForm: plugins.deesCatalog.DeesForm = elementArg.querySelector('dees-form');
deesForm.addEventListener('formData', async (eventArg: CustomEvent) => {
const response = await idpState.idpClient.requests.mobileNumberVerification
.fire({
token: this.storedData.validationTokenUrlParam,
mobileNumber: eventArg.detail.data.mobileNumber,
})
.catch(
(
errArg: (typeof DeesElement)['prototype']['domtools']['convenience']['typedrequest']['TypedResponseError']['prototype']
) => {
deesForm.setStatus('error', errArg.errorText);
}
);
deesForm.setStatus('success', 'ok!');
stepperArg.goNext();
});
},
onReturnToStepFunc: async (stepperArg, stepElementArg) => {
const deesForm = stepElementArg.querySelector('dees-form');
deesForm.setStatus('normal', 'Edit and Next');
},
},
{
title: 'What is the Verification Code?',
content: html`
<dees-form>
<dees-input-text
key="verificationCode"
required
label="Verification Code"
></dees-input-text>
<dees-form-submit>Next</dees-form-submit>
</dees-form>
`,
validationFunc: async (stepperArg, elementArg) => {
const deesForm: plugins.deesCatalog.DeesForm = elementArg.querySelector('dees-form');
deesForm.addEventListener('formData', async (eventArg: CustomEvent) => {
const response = await idpState.idpClient.requests.mobileNumberVerification.fire({
token: this.storedData.validationTokenUrlParam,
verificationCode: eventArg.detail.data.verificationCode,
});
if (response.verficationCodeOk) {
deesForm.setStatus('success', 'ok!');
stepperArg.goNext();
} else {
deesForm.setStatus('error', 'wrong code!');
await this.domtools.convenience.smartdelay.delayFor(3000);
deesForm.setStatus('normal', 'Retry And Next!');
}
});
},
onReturnToStepFunc: async (stepperArg, stepElementArg) => {
stepperArg.goBack();
const deesForm = stepElementArg.querySelector('dees-form');
deesForm.setStatus('normal', 'Next');
},
},
{
title: 'Create a secure password:',
content: html`
<dees-form>
<dees-input-text
key="password"
required
label="Your New Secure Password"
></dees-input-text>
<dees-form-submit>Next</dees-form-submit>
</dees-form>
`,
validationFunc: async (stepperArg, elementArg) => {
const deesForm: plugins.deesCatalog.DeesForm = elementArg.querySelector('dees-form');
deesForm.addEventListener('formData', async (eventArg: CustomEvent) => {
const response = await idpState.idpClient.requests.setData.fire({
token: this.storedData.validationTokenUrlParam,
userData: {
username: null,
email: null,
name: null,
connectedOrgs: null,
status: null,
password: eventArg.detail.data.password,
},
});
const finishRegistrationResponse =
await idpState.idpClient.requests.finishRegistration.fire({
token: this.storedData.validationTokenUrlParam,
});
deesForm.setStatus('pending', 'User created!');
await this.domtools.convenience.smartdelay.delayFor(500);
deesForm.setStatus('pending', 'Obtaining Refresh Token...');
const loginResponse =
await idpState.idpClient.requests.loginWithUserNameAndPassword.fire({
username: this.storedData.email,
password: eventArg.detail.data.password,
});
this.storedData.refreshToken = loginResponse.refreshToken;
deesForm.setStatus('pending', 'Obtaining JWT...');
const jwtResponse = await idpState.idpClient.requests.obtainJwt.fire({
refreshToken: this.storedData.refreshToken,
});
deesForm.setStatus('pending', 'Obtaining Transfer Token...');
await idpState.idpClient.setJwt(jwtResponse.jwt);
await idpState.idpClient.getTransferTokenAndSwitchToLocation(
'https://sso.workspace.global/afterregistration'
);
});
},
},
] as plugins.deesCatalog.IStep[]}
></dees-stepper>`;
await this.domtools.convenience.smartdelay.delayFor(100);
} }
} }
+6 -3
View File
@@ -38,8 +38,8 @@ export class IdpWelcome extends DeesElement {
font-family: 'Cal Sans'; font-family: 'Cal Sans';
text-align: center; text-align: center;
font-size: 24px; font-size: 24px;
margin: 24px auto; margin: 0px auto;
padding: 0px 24px; padding: 24px 24px 0px 24px;
width: 500px; width: 500px;
letter-spacing:0.0125em; letter-spacing:0.0125em;
} }
@@ -70,7 +70,10 @@ export class IdpWelcome extends DeesElement {
const idpState = await IdpState.getSingletonInstance(); const idpState = await IdpState.getSingletonInstance();
idpState.domtools.router.pushUrl('/login'); idpState.domtools.router.pushUrl('/login');
}}>Sign In</dees-button> }}>Sign In</dees-button>
<dees-button @click=${() => {}}>Register</dees-button> <dees-button @click=${async () => {
const idpState = await IdpState.getSingletonInstance();
idpState.domtools.router.pushUrl('/register');
}}>Register</dees-button>
</div> </div>
<div class="textbox"> <div class="textbox">
+1 -1
View File
@@ -1,5 +1,5 @@
export * from './idp-registration-stepper.js'; export * from './idp-registration-stepper.js';
export * from './idp-logincontainer.js'; export * from './idp-centercontainer.js';
export * from './idp-loginprompt.js'; export * from './idp-loginprompt.js';
export * from './idp-registerprompt.js'; export * from './idp-registerprompt.js';
export * from './idp-transfermanager.js'; export * from './idp-transfermanager.js';
+9 -2
View File
@@ -15,11 +15,11 @@ export class IdpState {
} }
// INSTANCE // INSTANCE
public receptionUrl = 'https://reception.lossless.one/typedrequest'; public receptionUrl = window.location.origin;
public idpClient = new plugins.idpClient.IdpClient(this.receptionUrl); public idpClient = new plugins.idpClient.IdpClient(this.receptionUrl);
public domtools: domtools.DomTools; public domtools: domtools.DomTools;
public mainStatePart: plugins.deesDomtools.plugins.smartstate.StatePart<'main', { public mainStatePart: plugins.deesDomtools.plugins.smartstate.StatePart<'main', {
view: 'welcome' | 'login' | 'register'; view: 'welcome' | 'login' | 'register' | 'finishregistration';
}> }>
public async init() { public async init() {
@@ -49,6 +49,13 @@ export class IdpState {
view: 'register', view: 'register',
}) })
}); });
this.domtools.router.on('/finishregistration', async () => {
await this.mainStatePart.setState({
...this.mainStatePart.getState(),
view: 'finishregistration',
})
});
this.domtools.router._handleRouteState(); this.domtools.router._handleRouteState();
} }
} }
+1 -1
View File
@@ -44,7 +44,7 @@ const run = async () => {
}, },
}); });
const serviceWorker = await serviceworker.getServiceworkerClient(); // const serviceWorker = await serviceworker.getServiceworkerClient();
const mainTemplate = html` const mainTemplate = html`
<style> <style>
+13 -2
View File
@@ -61,14 +61,23 @@ export class IdpViewcontainer extends DeesElement {
// Remove the current element if it exists // Remove the current element if it exists
if (this.currentElement) { if (this.currentElement) {
const currentElement = this.currentElement as any;
if (currentElement.hide) {
await currentElement.hide();
}
viewContainer.removeChild(this.currentElement); viewContainer.removeChild(this.currentElement);
} }
// Create a new instance of the viewElement // Create a new instance of the viewElement
const newElement = new viewElement(); const newElement = new viewElement() as any;
(newElement as any).viewContainer = this; (newElement as any).viewContainer = this;
viewContainer.appendChild(newElement); viewContainer.appendChild(newElement);
if (newElement.show) {
await newElement.show();
}
// Wait until the new element is fully rendered // Wait until the new element is fully rendered
await newElement.updateComplete; await newElement.updateComplete;
@@ -87,11 +96,13 @@ export class IdpViewcontainer extends DeesElement {
break; break;
case 'login': case 'login':
console.log('now on /login'); console.log('now on /login');
await this.loadElement(elements.IdpLogincontainer); await this.loadElement(elements.IdpLoginPrompt);
break; break;
case 'register': case 'register':
await this.loadElement(elements.IdpRegistrationPrompt); await this.loadElement(elements.IdpRegistrationPrompt);
break; break;
case 'finishregistration':
await this.loadElement(elements.IdpRegistrationStepper);
} }
}); });
} }