UNPKG

@universis/candidates

Version:

Universis api server plugin for study program candidates, internship selection etc

181 lines (173 loc) 4.84 kB
import { EdmMapping, EdmType } from '@themost/data'; import EnableAttachmentModel from './EnableAttachmentModel'; import unirest from 'unirest'; import { DataError, HttpError, DataNotFoundError, TraceUtils, } from '@themost/common'; import { toXlsx } from '../middlewares'; function tryCloseStream(stream) { if (stream && typeof stream.close === 'function') { try { stream.close(); } catch (error) { TraceUtils.warn( `(tryCloseStream) An error occurred while trying to close a stream.` ); TraceUtils.warn(error); } } } @EdmMapping.entityType('CandidateSource') class CandidateSource extends EnableAttachmentModel { constructor() { super(); } @EdmMapping.param('file', EdmType.EdmStream, false) @EdmMapping.action('attachConfigurationSchema', 'Attachment') async attachConfigurationSchema(file) { try { const context = this.context; // validate self const self = await context .model('CandidateSource') .where('id') .equal(this.getId()) .getItem(); if (self == null) { throw new DataNotFoundError(); } const attachment = Object.assign( { name: file.contentFileName, }, file ); // try to add attachment const result = await super.addAttachment(attachment); // close stream tryCloseStream(file); // define schemaURL based on added attachment's url self.schemaURL = result.url; // update (do not use silent) await context.model('CandidateSource').save(self); // and return the attachment return result; } catch (err) { // try to close stream tryCloseStream(file); // and throw error throw err; } } @EdmMapping.func('exportCandidates', EdmType.EdmStream) async exportFromSource() { const context = this.context; // fetch and validate self const self = await context .model('CandidateSource') .where('id') .equal(this.getId()) .getItem(); if (self == null) { throw new DataNotFoundError( 'The specified candidate source cannot be found or is inaccessible.' ); } // validate source url if (!(self.externalSource && self.sourceURL)) { throw new DataError( 'E_EXT_SOURCE_URL', 'The external source url cannot be empty while exporting students.', null, 'CandidateSource', 'sourceURL' ); } let keychainItem = null; // check if the source has some keychain identifier if (self.keychainIdentifier) { // and validate it const keychain = context .getConfiguration() .getSourceAt('settings/universis/keychain'); // first of all, validate keychain existance if (!(Array.isArray(keychain) && keychain.length)) { throw new DataError( 'E_KEYCHAIN_CONFIG', 'The process cannot continue due to invalid keychain configuration.' ); } // then try to find the specified identifier keychainItem = keychain.find( (item) => item.identifier === self.keychainIdentifier ); if (keychainItem == null) { throw new DataError( 'E_KEYCHAIN_ITEM', 'The specified keychain identifier cannot be found inside the keychain configuration', null, 'CandidateSource', 'keychainIdentifier' ); } } // prepare request const CandidatesDataRequest = unirest .get(new URL(self.sourceURL)) .header('Accept', 'application/json') .header('Content-Type', 'application/json'); // if keychain item requires auth if (keychainItem && keychainItem.authorizationType) { switch (keychainItem.authorizationType) { case 'Basic': // validate username and password if (!(keychainItem.username && keychainItem.password)) { throw new DataError( 'E_CREDENTIALS', 'The username and/or password is/are missing from the keychain configuration. The process cannot continue.' ); } // apply basic auth header to request CandidatesDataRequest.header( 'Authorization', 'Basic ' + Buffer.from( `${keychainItem.username}:${keychainItem.password}` ).toString('base64') ); break; default: // throw error for not yet implemented auth type throw new DataError( 'E_AUTH_TYPE', 'The specified authorization type is not yet implemented.' ); } } // and send the request return await new Promise((resolve, reject) => { return CandidatesDataRequest.end(function (response) { // handle errors first if (response.error) { if (response.clientError) { return reject(new HttpError(response.error.status)); } return reject(response.error); } // convert response body (json) to xlsx return toXlsx(response.body) .then((buffer) => { // and resolve the buffer return resolve(buffer); }) .catch((err) => { return reject(err); }); }); }); } } module.exports = CandidateSource;