All files / src/api metadata.coffee

22.99% Statements 20/87
0% Branches 0/19
0% Functions 0/7
25.64% Lines 20/78
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 1551x 1x 1x 1x 1x 1x   1x 1x 1x 1x                         1x                         1x                         1x                     1x                                             1x                                                                                                                       1x       1x       1x 1x 1x  
Channel = require('../model/channels').Channel
Client = require('../model/clients').Client
Mediator = require('../model/mediators').Mediator
User = require('../model/users').User
ContactGroup = require('../model/contactGroups').ContactGroup
Keystore = require('../model/keystore').Keystore
 
Q = require 'q'
logger = require 'winston'
authorisation = require './authorisation'
utils = require "../utils"
 
# Map string parameters to collections
collections =
  Channels: Channel
  Clients: Client
  Mediators: Mediator
  Users: User
  ContactGroups: ContactGroup
  Keystore: Keystore
 
 
#Function to remove properties from export object
removeProperties = (obj) ->
  propertyID = '_id'
  propertyV = '__v'
 
  for prop of obj
    if (prop == propertyID || prop == propertyV)
      delete obj[prop]
    else if ( typeof obj[prop] == 'object' || obj[prop] instanceof Array )
      removeProperties(obj[prop])
  return obj
 
 
# Function to return unique identifier key and value for a collection
getUniqueIdentifierForCollection = (collection, doc) ->
  switch collection
    when 'Channels' then uidKey = 'name'; uid = doc.name
    when 'Clients' then uidKey = 'clientID'; uid = doc.clientID
    when 'Mediators' then uidKey = 'urn'; uid = doc.urn
    when 'Users' then uidKey = 'email'; uid = doc.email
    when 'ContactGroups' then uidKey = 'groups'; uid = doc.groups
  returnObj = {}
  returnObj[uidKey] = uid
  return returnObj
 
 
# Build response object
buildResponseObject = (model, doc, status, message, uid) ->
  return {
    model: model
    record: doc
    status: status
    message: message
    uid: uid
  }
  
 
# API endpoint that returns metadata for export
exports.getMetadata = () ->
  # Test if the user is authorised
  if not authorisation.inGroup 'admin', this.authenticated
    return utils.logAndSetResponse this, 403, "User #{this.authenticated.email} is not an admin, API access to getMetadata denied.", 'info'
 
  try
    exportObject = {}
    params = this.request.query
    
    # Return all documents from all collections for export
    for col of collections
      exportObject[col] = yield collections[col].find().lean().exec()
      for doc in exportObject[col]
        if doc._id
          doc = removeProperties doc
 
    this.body = [exportObject]
    this.status = 200
  catch e
    this.body = e.message
    utils.logAndSetResponse this, 500, "Could not fetch specified metadata via the API #{e}", 'error'
 
 
handleMetadataPost = (action, that) ->
  # Test if the user is authorised
  if not authorisation.inGroup 'admin', that.authenticated
    return utils.logAndSetResponse that, 403, "User #{that.authenticated.email} is not an admin, API access to importMetadata denied.", 'info'
 
  try
    returnObject = []
    insertObject = that.request.body
    
    for key of insertObject
      insertDocuments = insertObject[key]
      for doc in insertDocuments
        try
          if key not of collections
            throw new Error "Invalid Collection in Import Object"
          
          # Keystore model does not have a uid other than _id and may not contain more than one entry
          if key is 'Keystore'
            result = yield collections[key].find().exec()
            uid = ''
          else
            uidObj = getUniqueIdentifierForCollection key, doc
            uid = uidObj[Object.keys(uidObj)[0]]
            result = yield collections[key].find(uidObj).exec()
          
          if action is 'import'
            if result and result.length > 0 and result[0]._id
              delete doc._id if doc._id
              yield collections[key].findByIdAndUpdate(result[0]._id, doc).exec()
              status = 'Updated'
            else
              doc = new collections[key] doc
              result = yield Q.ninvoke doc, 'save'
              status = 'Inserted'
          
          if action is 'validate'
            if result and result.length > 0 and result[0]._id
              status = 'Conflict'
            else
              doc = new collections[key] doc
              error = doc.validateSync()
              if error
                throw new Error "Document Validation failed: #{error}"
              status = 'Valid'
          
          logger.info "User #{that.authenticated.email} performed #{action} action on #{key}, got #{status}"
          returnObject.push buildResponseObject key, doc, status, '', uid
          
        catch e
          logger.error "Failed to #{action} #{key} with unique identifier #{uid}. #{e.message}"
          returnObject.push buildResponseObject key, doc, 'Error', e.message, uid
        
    that.body = returnObject
    that.status = 201
  catch e
    that.body = e.message
    utils.logAndSetResponse that, 500, "Could not import metadata via the API #{e}", 'error'
 
 
# API endpoint that upserts metadata
exports.importMetadata = () ->
  handleMetadataPost 'import', this
  
# API endpoint that checks for conflicts between import object and database
exports.validateMetadata = () ->
  handleMetadataPost 'validate', this
 
if process.env.NODE_ENV == "test"
  exports.buildResponseObject = buildResponseObject
  exports.getUniqueIdentifierForCollection = getUniqueIdentifierForCollection
  exports.removeProperties = removeProperties