@universis/candidates
Version:
Universis api server plugin for study program candidates, internship selection etc
155 lines (153 loc) • 7.37 kB
JavaScript
import { DataObjectState } from "@themost/data";
import { DataError, TraceUtils } from '@themost/common';
import { getMailer } from '@themost/mailer';
/**
* @param {DataEventArgs} event
*/
async function afterSaveAsync(event) {
const context = event.model.context;
const actionStatus = await context.model('CreateCandidateUserAction')
.where('id').equal(event.target.id).select('actionStatus/alternateName')
.silent().value();
let previousStatus = 'UnknownActionStatus';
if (event.state === DataObjectState.Insert) {
previousStatus = 'UnknownActionStatus'
} else if (event.state === DataObjectState.Update) {
if (event.previous) {
previousStatus = event.previous.actionStatus.alternateName;
} else {
throw new DataError('E_STATE', 'The previous state of an object cannot be determined', null, 'StudyProgramRegisterAction');
}
}
if (actionStatus === 'ActiveActionStatus' && previousStatus !== 'ActiveActionStatus') {
const service = context.getApplication().getService(function OAuth2ClientService() {});
if (typeof service.createUser !== 'function') {
throw new Error('The operation is not supported by a service.');
}
// get access token (for admin account)
const adminAccount = service.settings.adminAccount;
if (adminAccount == null) {
throw new Error('The operation cannot be completed due to invalid or missing configuration.');
}
const authorizeUser = await service.authorize(adminAccount);
// get user
TraceUtils.debug('CreateCandidateUserAction', 'get', JSON.stringify(event.target.object));
const object = await context.model('CreateCandidateUserAction')
.where('id').equal(event.target.id).select('object')
.silent().value();
const user = await context.model('User').where('id').equal(object).silent().getItem();
if (user == null) {
throw new DataError('E_NOENT', 'User cannot be found', null, 'CreateCandidateUserAction', 'object');
}
// check if user already exists and is disabled
const userExists = await service.getUser(user.name, authorizeUser);
if (userExists) {
const updateAction = {
id: event.target.id,
actionStatus: {
alternateName: 'CompletedActionStatus'
}
}
if (userExists.enabled === false) {
updateAction.description = 'User already exists at the OAuth2 server and is disabled.'
} else {
updateAction.description = 'User already exists at the OAuth2 server and is enabled.'
}
await event.model.silent().save(updateAction);
return;
}
// get candidate for extra data
const candidate = await context.model('CandidateStudent')
.where('user').equal(user).expand('person').silent().getItem();
// get activation code as new password
const newPassword = await context.model('CandidateUser')
.where('id').equal(object).select('activationCode')
.silent().value();
if (newPassword == null) {
throw new DataError('E_EMPTY','An error occurred while validating user data', null, 'CandidateUser', 'activationCode');
}
await service.createUser({
name: user.name,
description: `${candidate.person.givenName} ${candidate.person.familyName}`,
alternateName: candidate.person.email,
enabled: true,
familyName: candidate.person.familyName,
givenName: candidate.person.givenName,
userCredentials: {
userPassword: `{clear}${newPassword}`
}
}, authorizeUser);
try {
// send notification for the newly created user
const mailer = getMailer(context);
let mailTemplate = await context.model('MailConfiguration')
.where('target').equal('CreateCandidateUserAction')
.and('state').equal(DataObjectState.Update)
.silent().getItem();
// if mail template is null do nothing and exit
// otherwise send mail
if (mailTemplate != null) {
// get candidate
const candidateUser = await context.model('CandidateUser')
.where('id').equal(user).silent().getItem();
Object.assign(candidate, {
user: candidateUser
});
// get register application
const application = await context.model('WebApplication')
.where('alternateName').equal('register')
.and('applicationSuite').equal('universis')
.silent().getItem();
if (application == null) {
TraceUtils.warn('CreateCandidateUserAction', 'Universis register is missing from application collection. User notification for account activation cannot include information about this app.');
}
await new Promise((resolve) => {
mailer.template(mailTemplate.template)
.subject(mailTemplate.subject)
.to(candidate.person.email)
.send({
model: {
candidate,
application
}
}, (err) => {
if (err) {
try {
TraceUtils.error('CreateCandidateUserAction', 'An error occurred while trying to send an email notification for account activation.');
TraceUtils.error('CreateCandidateUserAction', 'Candidate' , `${candidate.id}`, 'Email Address', `${candidate.person.email || 'empty'}`);
TraceUtils.error(err);
} catch (err1) {
// do nothing
}
return resolve();
}
return resolve();
});
});
} else {
TraceUtils.warn('CreateCandidateUserAction', 'A mail template for account activation notification is missing. User cannot be notified for this action.')
}
} catch (err) {
TraceUtils.error('CreateCandidateUserAction', 'An error occurred while trying to send an email notification for account activation.');
TraceUtils.error(err);
}
// complete action
await context.model('CreateCandidateUserAction').silent().save({
id: event.target.id,
actionStatus: {
alternateName: 'CompletedActionStatus'
}
});
}
}
/**
* @param {DataEventArgs} event
* @param {Function} callback
*/
export function afterSave(event, callback) {
return afterSaveAsync(event).then(() => {
return callback();
}).catch((err) => {
return callback(err);
});
}