All files / src/api audits.coffee

25.33% Statements 19/75
0% Branches 0/14
0% Functions 0/7
25.33% Lines 19/75
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 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 1841x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x       1x                             1x                       1x                                                     1x                                                                                                                                     1x                                                                 1x                          
Audit = require('../model/audits').Audit
AuditMeta = require('../model/audits').AuditMeta
authorisation = require './authorisation'
Q = require 'q'
logger = require 'winston'
utils = require "../utils"
atna = require 'atna-audit'
auditing = require '../auditing'
os = require 'os'
config = require "../config/config"
config.router = config.get('router')
config.api = config.get('api')
himSourceID = config.get('auditing').auditEvents.auditSourceID
 
 
# function to construct projection object
getProjectionObject = (filterRepresentation) ->
  switch filterRepresentation
    when "simpledetails"
      # view minimum required data for audit details view
      return {}
    when "full"
      # view all audit data
      return {}
    else
      # no filterRepresentation supplied - simple view
      # view minimum required data for audits
      return { "participantObjectIdentification": 0, "activeParticipant": 0, "rawMessage": 0 }
 
 
# Audit the audit record retrieval
auditLogUsed = (auditId, outcome, user) ->
  groups = user.groups.join(',')
  uri = "https://#{config.router.externalHostname}:#{config.api.httpsPort}/audits/#{auditId}"
  audit = atna.auditLogUsedAudit outcome, himSourceID, os.hostname(), user.email, groups, groups, uri
  audit = atna.wrapInSyslog audit
  auditing.sendAuditEvent audit, ->
    logger.debug "Processed audit log used message for user '#{user.email}' and audit '#{auditId}'"
 
 
###
# Adds a Audit
###
exports.addAudit = ->
  # Test if the user is authorised
  if not authorisation.inGroup 'admin', this.authenticated
    utils.logAndSetResponse this, 403, "User #{this.authenticated.email} is not an admin, API access to addAudit denied.", 'info'
    return
 
  auditData = this.request.body
 
  try
    audit = new Audit auditData
    result = yield Q.ninvoke audit, 'save'
    yield Q.ninvoke auditing, 'processAuditMeta', audit
    
    logger.info "User #{this.authenticated.email} created audit with id #{audit.id}"
    this.body = 'Audit successfully created'
    this.status = 201
  catch e
    logger.error "Could not add a audit via the API: #{e.message}"
    this.body = e.message
    this.status = 400
 
 
 
 
###
# Retrieves the list of Audits
###
exports.getAudits = ->
  # 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 getAudits denied.", 'info'
    return
 
  try
 
    filtersObject = this.request.query
 
    #get limit and page values
    filterLimit = filtersObject.filterLimit ? 0
    filterPage = filtersObject.filterPage ? 0
    filterRepresentation = filtersObject.filterRepresentation
 
    #remove limit/page/filterRepresentation values from filtersObject (Not apart of filtering and will break filter if present)
    delete filtersObject.filterLimit
    delete filtersObject.filterPage
    delete filtersObject.filterRepresentation
 
    #determine skip amount
    filterSkip = filterPage*filterLimit
 
    # get projection object
    projectionFiltersObject = getProjectionObject filterRepresentation
 
    if filtersObject.filters?
      filters = JSON.parse filtersObject.filters
    else
      filters = {}
 
    # parse date to get it into the correct format for querying
    if filters['eventIdentification.eventDateTime']
      filters['eventIdentification.eventDateTime'] = JSON.parse filters['eventIdentification.eventDateTime']
 
    if filters['participantObjectIdentification.participantObjectID']
      # filter by AND on same property for patientID and objectID
      if filters['participantObjectIdentification.participantObjectID'].type
        patientID = new RegExp filters['participantObjectIdentification.participantObjectID'].patientID
        objectID = new RegExp filters['participantObjectIdentification.participantObjectID'].objectID
        filters['$and'] = [ { 'participantObjectIdentification.participantObjectID': patientID }, { 'participantObjectIdentification.participantObjectID': objectID } ]
        # remove participantObjectIdentification.participantObjectID property as we create a new '$and' operator
        delete filters['participantObjectIdentification.participantObjectID']
      else
        participantObjectID = JSON.parse filters['participantObjectIdentification.participantObjectID']
        filters['participantObjectIdentification.participantObjectID'] = new RegExp "#{participantObjectID}"
 
    # execute the query
    this.body = yield Audit
      .find filters, projectionFiltersObject
      .skip filterSkip
      .limit parseInt filterLimit
      .sort 'eventIdentification.eventDateTime': -1
      .exec()
 
    # audit each retrieved record, but only for non-basic representation requests
    if filterRepresentation is 'full' or filterRepresentation is 'simpledetails'
      for record in this.body
        auditLogUsed record._id, atna.OUTCOME_SUCCESS, this.authenticated
 
  catch e
    utils.logAndSetResponse this, 500, "Could not retrieve audits via the API: #{e}", 'error'
 
 
###
# Retrieves the details for a specific Audit Record
###
exports.getAuditById = (auditId) ->
  # 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 getAuditById denied.", 'info'
    return
 
  # Get the values to use
  auditId = unescape auditId
 
  try
    # get projection object
    projectionFiltersObject = getProjectionObject 'full'
 
    result = yield Audit.findById(auditId, projectionFiltersObject).exec()
 
    # Test if the result if valid
    if not result
      this.body = "Could not find audits record with ID: #{auditId}"
      this.status = 404
      auditLogUsed auditId, atna.OUTCOME_MINOR_FAILURE, this.authenticated
    else
      this.body = result
      auditLogUsed auditId, atna.OUTCOME_SUCCESS, this.authenticated
 
  catch e
    utils.logAndSetResponse this, 500, "Could not get audit by ID via the API: #{e}", 'error'
    auditLogUsed auditId, atna.OUTCOME_MAJOR_FAILURE, this.authenticated
 
 
 
###
# construct audit filtering dropdown options
###
exports.getAuditsFilterOptions = ->
 
  # 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 getAudits denied.", 'info'
    return
 
  try
    this.body = yield AuditMeta.findOne({}).exec()
  catch e
    utils.logAndSetResponse this, 500, "Could not retrieve audits filter options via the API: #{e}", 'error'