196 lines
6.0 KiB
TypeScript
196 lines
6.0 KiB
TypeScript
import * as plugins from '../plugins.js';
|
|
|
|
import { RegistrationSessionManager } from './classes.registrationsessionmanager.js';
|
|
import { logger } from './logging.js';
|
|
import { User } from './classes.user.js';
|
|
|
|
/**
|
|
* a RegistrationSession is a in memory session for signing up
|
|
*/
|
|
export class RegistrationSession {
|
|
// ======
|
|
// STATIC
|
|
// ======
|
|
public static async createRegistrationSessionForEmail(
|
|
registrationSessionManageremailArg: RegistrationSessionManager,
|
|
emailArg: string
|
|
) {
|
|
const newRegistrationSession = new RegistrationSession(
|
|
registrationSessionManageremailArg,
|
|
emailArg
|
|
);
|
|
const emailValidationResult = await newRegistrationSession
|
|
.validateEMailAddress()
|
|
.catch((error) => {
|
|
throw new plugins.typedrequest.TypedResponseError(
|
|
'Error occured during email provider & dns validation'
|
|
);
|
|
});
|
|
if (!emailValidationResult?.valid) {
|
|
newRegistrationSession.destroy();
|
|
throw new plugins.typedrequest.TypedResponseError(
|
|
'Email Address is not valid. Please use a correctly formated email address'
|
|
);
|
|
}
|
|
if (emailValidationResult.disposable) {
|
|
newRegistrationSession.destroy();
|
|
throw new plugins.typedrequest.TypedResponseError(
|
|
'Email is disposable. Please use a non disposable email address.'
|
|
);
|
|
}
|
|
console.log(
|
|
`${newRegistrationSession.emailAddress} is valid. Continuing registration process!`
|
|
);
|
|
await newRegistrationSession.sendTokenValidationEmail();
|
|
console.log(`Successfully sent email validation email`);
|
|
return newRegistrationSession;
|
|
}
|
|
|
|
// ========
|
|
// INSTANCE
|
|
// ========
|
|
public registrationSessionManagerRef: RegistrationSessionManager;
|
|
|
|
public emailAddress: string;
|
|
|
|
/**
|
|
* only used during testing
|
|
*/
|
|
public unhashedEmailToken?: string;
|
|
public hashedEmailToken: string;
|
|
private smsvalidationCounter = 0;
|
|
public smsCode: string;
|
|
|
|
/**
|
|
* the status of the registration. should progress in a linear fashion.
|
|
*/
|
|
public status: 'announced' | 'emailValidated' | 'mobileVerified' | 'registered' | 'failed' =
|
|
'announced';
|
|
|
|
public collectedData: {
|
|
userData: plugins.idpInterfaces.data.IUser['data'];
|
|
} = {
|
|
userData: {
|
|
username: null,
|
|
connectedOrgs: [],
|
|
email: null,
|
|
name: null,
|
|
status: null,
|
|
mobileNumber: null,
|
|
password: null,
|
|
passwordHash: null,
|
|
},
|
|
};
|
|
|
|
constructor(
|
|
registrationSessionManagerRefArg: RegistrationSessionManager,
|
|
emailAddressArg: string
|
|
) {
|
|
this.registrationSessionManagerRef = registrationSessionManagerRefArg;
|
|
this.emailAddress = emailAddressArg;
|
|
this.registrationSessionManagerRef.registrationSessions.addToMap(this.emailAddress, this);
|
|
|
|
// lets destroy this after 10 minutes,
|
|
// works in unrefed mode so not blocking node exiting.
|
|
plugins.smartdelay.delayFor(600000, null, true).then(() => this.destroy());
|
|
}
|
|
|
|
/**
|
|
* validates a token by comparing its hash against the stored hashed token
|
|
* @param tokenArg
|
|
*/
|
|
public validateEmailToken(tokenArg: string): boolean {
|
|
const result = this.hashedEmailToken === plugins.smarthash.sha256FromStringSync(tokenArg);
|
|
if (result && this.status === 'announced') {
|
|
this.status = 'emailValidated';
|
|
this.collectedData.userData.email = this.emailAddress;
|
|
}
|
|
if (!result && this.status === 'announced') {
|
|
this.status = 'failed';
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/** validates the sms code */
|
|
public validateSmsCode(smsCodeArg: string) {
|
|
this.smsvalidationCounter++;
|
|
const result = this.smsCode === smsCodeArg;
|
|
if (this.status === 'emailValidated' && result) {
|
|
this.status = 'mobileVerified';
|
|
return result;
|
|
} else {
|
|
if (this.smsvalidationCounter === 5) {
|
|
this.destroy();
|
|
throw new plugins.typedrequest.TypedResponseError(
|
|
'Registration cancelled due to repeated wrong verification code submission'
|
|
);
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* validate the email address with provider and dns sanity checks
|
|
* @returns
|
|
*/
|
|
public async validateEMailAddress(): Promise<plugins.smartmail.IEmailValidationResult> {
|
|
console.log(`validating email ${this.emailAddress}`);
|
|
const result = await new plugins.smartmail.EmailAddressValidator().validate(this.emailAddress);
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* send the validation email
|
|
*/
|
|
public async sendTokenValidationEmail() {
|
|
const uuidToSend = plugins.smartunique.uuid4();
|
|
this.unhashedEmailToken = uuidToSend;
|
|
this.hashedEmailToken = plugins.smarthash.sha256FromStringSync(uuidToSend);
|
|
this.registrationSessionManagerRef.receptionRef.receptionMailer.sendRegistrationEmail(
|
|
this,
|
|
uuidToSend
|
|
);
|
|
logger.log('info', `sent a validation email with a verification code to ${this.emailAddress}`);
|
|
}
|
|
|
|
/**
|
|
* validate the mobile number of someone
|
|
*/
|
|
public async sendValidationSms() {
|
|
this.smsCode =
|
|
await this.registrationSessionManagerRef.receptionRef.szPlatformClient.smsConnector.sendSmsVerifcation(
|
|
{
|
|
fromName: this.registrationSessionManagerRef.receptionRef.options.name,
|
|
toNumber: parseInt(this.collectedData.userData.mobileNumber),
|
|
}
|
|
);
|
|
}
|
|
|
|
/**
|
|
* this method can be called when this registrationsession is validated
|
|
* and all data has been set
|
|
*/
|
|
public async manifestUserWithAccountData(): Promise<User> {
|
|
if (this.status !== 'mobileVerified') {
|
|
throw new plugins.typedrequest.TypedResponseError(
|
|
'You can only manifest user that have a validated email Address and Mobile Number'
|
|
);
|
|
}
|
|
if (!this.collectedData) {
|
|
throw new Error('You have to set the accountdata first');
|
|
}
|
|
const manifestedUser =
|
|
await this.registrationSessionManagerRef.receptionRef.userManager.CUser.createNewUserForUserData(
|
|
this.collectedData.userData
|
|
);
|
|
return manifestedUser;
|
|
}
|
|
|
|
/**
|
|
* destroys the registrationsession
|
|
*/
|
|
public destroy() {
|
|
this.registrationSessionManagerRef.registrationSessions.removeFromMap(this.emailAddress);
|
|
}
|
|
}
|