UNPKG

openhim-core

Version:

The OpenHIM core application that provides logging and routing of http requests

202 lines (166 loc) 7.47 kB
Channel = require('../model/channels').Channel Mediator = require('../model/mediators').Mediator Q = require 'q' logger = require 'winston' authorisation = require './authorisation' semver = require 'semver' utils = require "../utils" exports.getAllMediators = -> # Must be admin if not authorisation.inGroup 'admin', this.authenticated utils.logAndSetResponse this, 403, "User #{this.authenticated.email} is not an admin, API access to getAllMediators denied.", 'info' return try this.body = yield Mediator.find().exec() catch err logAndSetResponse this, 500, "Could not fetch mediators via the API: #{err}", 'error' exports.getMediator = (mediatorURN) -> # Must be admin if not authorisation.inGroup 'admin', this.authenticated utils.logAndSetResponse this, 403, "User #{this.authenticated.email} is not an admin, API access to getMediator denied.", 'info' return urn = unescape mediatorURN try result = yield Mediator.findOne({ "urn": urn }).exec() if result == null this.status = 404 else this.body = result catch err logAndSetResponse this, 500, "Could not fetch mediator using UUID #{urn} via the API: #{err}", 'error' saveDefaultChannelConfig = (config) -> new Channel(channel).save() for channel in config constructError = (message, name) -> err = new Error message err.name = name return err exports.addMediator = -> # Must be admin if not authorisation.inGroup 'admin', this.authenticated utils.logAndSetResponse this, 403, "User #{this.authenticated.email} is not an admin, API access to addMediator denied.", 'info' return try mediator = this.request.body if not mediator.urn throw constructError 'URN is required', 'ValidationError' if not mediator.version or not semver.valid(mediator.version) throw constructError 'Version is required. Must be in SemVer form x.y.z', 'ValidationError' if mediator.config? validateConfig mediator.configDefs, mediator.config existing = yield Mediator.findOne({urn: mediator.urn}).exec() if typeof existing != 'undefined' and existing != null if semver.gt(mediator.version, existing.version) # update the mediator if mediator.config? and existing.config? # if some config already exists, add only config that didn't exist previously for param, val of mediator.config if existing.config[param]? mediator.config[param] = existing.config[param] yield Mediator.findByIdAndUpdate(existing._id, mediator).exec() else # this is a new mediator validate and save it if not mediator.endpoints or mediator.endpoints.length < 1 throw constructError 'At least 1 endpoint is required', 'ValidationError' yield Q.ninvoke(new Mediator(mediator), 'save') if mediator.defaultChannelConfig yield saveDefaultChannelConfig(mediator.defaultChannelConfig) this.status = 201 logger.info "User #{this.authenticated.email} created mediator with urn #{mediator.urn}" catch err if err.name is 'ValidationError' utils.logAndSetResponse this, 400, "Could not add Mediator via the API: #{err}", 'error' else utils.logAndSetResponse this, 500, "Could not add Mediator via the API: #{err}", 'error' exports.removeMediator = (urn) -> # Must be admin if not authorisation.inGroup 'admin', this.authenticated utils.logAndSetResponse this, 403, "User #{this.authenticated.email} is not an admin, API access to removeMediator denied.", 'info' return urn = unescape urn try yield Mediator.findOneAndRemove({ urn: urn }).exec() this.body = "Mediator with urn #{urn} has been successfully removed by #{this.authenticated.email}" logger.info "Mediator with urn #{urn} has been successfully removed by #{this.authenticated.email}" catch err utils.logAndSetResponse this, 500, "Could not remove Mediator by urn #{urn} via the API: #{err}", 'error' exports.heartbeat = (urn) -> # Must be admin if not authorisation.inGroup 'admin', this.authenticated utils.logAndSetResponse this, 403, "User #{this.authenticated.email} is not an admin, API access to removeMediator denied.", 'info' return urn = unescape urn try mediator = yield Mediator.findOne({ urn: urn }).exec() if not mediator? this.status = 404 return heartbeat = this.request.body if not heartbeat?.uptime? this.status = 400 return if mediator._configModifiedTS > mediator._lastHeartbeat or heartbeat?.config is true # Return config if it has changed since last heartbeat this.body = mediator.config else this.body = "" # set internal properties if heartbeat? update = _lastHeartbeat: new Date() _uptime: heartbeat.uptime yield Mediator.findByIdAndUpdate(mediator._id, update).exec() this.status = 200 catch err utils.logAndSetResponse this, 500, "Could not process mediator heartbeat (urn: #{urn}): #{err}", 'error' validateConfig = (configDef, config) -> # reduce to a single true or false value, start assuming valid return Object.keys(config).every (param) -> # find the matching def is there is one matchingDefs = configDef.filter (def) -> return def.param is param # fail if there isn't a matching def if matchingDefs.length is 0 throw constructError "No config definition found for parameter #{param}", 'ValidationError' # validate the param against the defs matchingDefs.map (def) -> switch def.type when 'string' if typeof config[param] isnt 'string' throw constructError "Expected config param #{param} to be a string.", 'ValidationError' when 'bigstring' if typeof config[param] isnt 'string' throw constructError "Expected config param #{param} to be a large string.", 'ValidationError' when 'number' if typeof config[param] isnt 'number' throw constructError "Expected config param #{param} to be a number.", 'ValidationError' when 'bool' if typeof config[param] isnt 'boolean' throw constructError "Expected config param #{param} to be a boolean.", 'ValidationError' when 'option' if (def.values.indexOf config[param]) is -1 throw constructError "Expected config param #{param} to be one of #{def.values}", 'ValidationError' # reduce array of results to a single value if process.env.NODE_ENV == "test" exports.validateConfig = validateConfig exports.setConfig = (urn) -> # Must be admin if not authorisation.inGroup 'admin', this.authenticated utils.logAndSetResponse this, 403, "User #{this.authenticated.email} is not an admin, API access to removeMediator denied.", 'info' return urn = unescape urn config = this.request.body try mediator = yield Mediator.findOne({ urn: urn }).exec() if not mediator? this.status = 404 this.body = 'No mediator found for this urn.' return try validateConfig mediator.configDefs, config catch err this.status = 400 this.body = err.message return yield Mediator.findOneAndUpdate({ urn: urn }, { config: this.request.body, _configModifiedTS: new Date() }).exec() this.status = 200 catch err utils.logAndSetResponse this, 500, "Could not set mediator config (urn: #{urn}): #{err}", 'error'