openhim-core
Version:
The OpenHIM core application that provides logging and routing of http requests
528 lines (517 loc) • 20.2 kB
HTML
<html lang="en">
<head>
<title>Code coverage report for src/api/metadata.coffee</title>
<meta charset="utf-8" />
<link rel="stylesheet" href="../../prettify.css" />
<link rel="stylesheet" href="../../base.css" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<style type='text/css'>
.coverage-summary .sorter {
background-image: url(../../sort-arrow-sprite.png);
}
</style>
</head>
<body>
<div class='wrapper'>
<div class='pad1'>
<h1>
<a href="../../index.html">All files</a> / <a href="index.html">src/api</a> metadata.coffee
</h1>
<div class='clearfix'>
<div class='fl pad1y space-right2'>
<span class="strong">22.99% </span>
<span class="quiet">Statements</span>
<span class='fraction'>20/87</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Branches</span>
<span class='fraction'>0/19</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Functions</span>
<span class='fraction'>0/7</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">25.64% </span>
<span class="quiet">Lines</span>
<span class='fraction'>20/78</span>
</div>
</div>
</div>
<div class='status-line low'></div>
<pre><table class="coverage">
<tr><td class="line-count quiet">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</td><td class="line-coverage quiet"><span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-neutral"> </span></td><td class="text"><pre class="prettyprint lang-js">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 = <span class="fstat-no" title="function not covered" >(</span>obj) ->
<span class="cstat-no" title="statement not covered" > propertyID = '</span>_id'
<span class="cstat-no" title="statement not covered" > propertyV = '</span>__v'
<span class="cstat-no" title="statement not covered" > for prop of obj</span>
if (prop == propertyID || prop == propertyV)
<span class="cstat-no" title="statement not covered" > delete obj[prop]</span>
else if ( typeof obj[prop] == 'object' || obj[prop] instanceof Array )
<span class="cstat-no" title="statement not covered" > removeProperties(obj[prop])</span>
<span class="cstat-no" title="statement not covered" > return o</span>bj
# Function to return unique identifier key and value for a collection
getUniqueIdentifierForCollection = <span class="fstat-no" title="function not covered" >(</span>collection, doc) ->
<span class="cstat-no" title="statement not covered" > switch collection</span>
when <span class="cstat-no" title="statement not covered" >'Channels' then <span class="cstat-no" title="statement not covered" >uidKey = '</span>name'; <span class="cstat-no" title="statement not covered" >uid = doc.n</span>ame</span>
when <span class="cstat-no" title="statement not covered" >'Clients' then <span class="cstat-no" title="statement not covered" >uidKey = '</span>clientID'; <span class="cstat-no" title="statement not covered" >uid = doc.c</span>lientID</span>
when <span class="cstat-no" title="statement not covered" >'Mediators' then <span class="cstat-no" title="statement not covered" >uidKey = '</span>urn'; <span class="cstat-no" title="statement not covered" >uid = doc.u</span>rn</span>
when <span class="cstat-no" title="statement not covered" >'Users' then <span class="cstat-no" title="statement not covered" >uidKey = '</span>email'; <span class="cstat-no" title="statement not covered" >uid = doc.e</span>mail</span>
when 'ContactGroups' then <span class="cstat-no" title="statement not covered" >uidKey = '</span>groups'; <span class="cstat-no" title="statement not covered" >uid = doc.g</span>roups
<span class="cstat-no" title="statement not covered" > returnObj = {</span>}
<span class="cstat-no" title="statement not covered" > returnObj[uidKey] = u</span>id
<span class="cstat-no" title="statement not covered" > return r</span>eturnObj
# Build response object
buildResponseObject = <span class="fstat-no" title="function not covered" >(</span>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 = <span class="fstat-no" title="function not covered" ></span>() ->
# Test if the user is authorised
if not authorisation.inGroup 'admin', this.authenticated
<span class="cstat-no" title="statement not covered" > return utils.logAndSetResponse this, 403, "User #{this.authenticated.email} is not an admin, API access to getMetadata denied.", 'info'</span>
try
<span class="cstat-no" title="statement not covered" > exportObject = {</span>}
<span class="cstat-no" title="statement not covered" > params = this.request.q</span>uery
# Return all documents from all collections for export
<span class="cstat-no" title="statement not covered" > for col of collections</span>
<span class="cstat-no" title="statement not covered" > exportObject[col] = y</span>ield collections[col].find().lean().exec()
<span class="cstat-no" title="statement not covered" > for doc in exportObject[col]</span>
if doc._id
<span class="cstat-no" title="statement not covered" > doc = removeProperties doc</span>
<span class="cstat-no" title="statement not covered" > this.body = [</span>exportObject]
this.status = 200
catch <span class="cstat-no" title="statement not covered" >e</span>
<span class="cstat-no" title="statement not covered" > this.body = e.m</span>essage
utils.logAndSetResponse this, 500, "Could not fetch specified metadata via the API #{e}", 'error'
handleMetadataPost = <span class="fstat-no" title="function not covered" >(</span>action, that) ->
# Test if the user is authorised
if not authorisation.inGroup 'admin', that.authenticated
<span class="cstat-no" title="statement not covered" > return utils.logAndSetResponse that, 403, "User #{that.authenticated.email} is not an admin, API access to importMetadata denied.", 'info'</span>
try
<span class="cstat-no" title="statement not covered" > returnObject = [</span>]
<span class="cstat-no" title="statement not covered" > insertObject = that.request.b</span>ody
<span class="cstat-no" title="statement not covered" > for key of insertObject</span>
<span class="cstat-no" title="statement not covered" > insertDocuments = insertObject[k</span>ey]
<span class="cstat-no" title="statement not covered" > for doc in insertDocuments</span>
try
if key not of collections
<span class="cstat-no" title="statement not covered" > throw new Error "Invalid Collection in Import Object"</span>
# Keystore model does not have a uid other than _id and may not contain more than one entry
if key is 'Keystore'
<span class="cstat-no" title="statement not covered" > result = y</span>ield collections[key].find().exec()
<span class="cstat-no" title="statement not covered" > uid = ''</span>
else
<span class="cstat-no" title="statement not covered" > uidObj = g</span>etUniqueIdentifierForCollection key, doc
<span class="cstat-no" title="statement not covered" > uid = uidObj[O</span>bject.keys(uidObj)[0]]
<span class="cstat-no" title="statement not covered" > result = yield collections[key].find(uidObj).exec()</span>
if action is 'import'
<span class="cstat-no" title="statement not covered" > if result and result.length > 0 and result[0]._id</span>
<span class="cstat-no" title="statement not covered" ></span> delete doc._id if doc._id
<span class="cstat-no" title="statement not covered" > yield collections[key].findByIdAndUpdate(result[0]._id, doc).exec()</span>
<span class="cstat-no" title="statement not covered" > status = 'Updated'</span>
else
<span class="cstat-no" title="statement not covered" > doc = new c</span>ollections[key] doc
<span class="cstat-no" title="statement not covered" > result = y</span>ield Q.ninvoke doc, 'save'
<span class="cstat-no" title="statement not covered" > status = 'Inserted'</span>
if action is 'validate'
<span class="cstat-no" title="statement not covered" > if result and result.length > 0 and result[0]._id</span>
<span class="cstat-no" title="statement not covered" > status = 'Conflict'</span>
else
<span class="cstat-no" title="statement not covered" > doc = new c</span>ollections[key] doc
<span class="cstat-no" title="statement not covered" > error = d</span>oc.validateSync()
if error
<span class="cstat-no" title="statement not covered" > throw new Error "Document Validation failed: #{error}"</span>
<span class="cstat-no" title="statement not covered" > status = 'Valid'</span>
<span class="cstat-no" title="statement not covered" > logger.info "User #{that.authenticated.email} performed #{action} action on #{key}, got #{status}"</span>
<span class="cstat-no" title="statement not covered" > returnObject.push buildResponseObject key, doc, status, '', uid</span>
catch <span class="cstat-no" title="statement not covered" >e</span>
<span class="cstat-no" title="statement not covered" > logger.error "Failed to #{action} #{key} with unique identifier #{uid}. #{e.message}"</span>
<span class="cstat-no" title="statement not covered" > returnObject.push buildResponseObject key, doc, 'Error', e.message, uid</span>
<span class="cstat-no" title="statement not covered" > that.body = r</span>eturnObject
that.status = 201
catch <span class="cstat-no" title="statement not covered" >e</span>
<span class="cstat-no" title="statement not covered" > that.body = e.m</span>essage
utils.logAndSetResponse that, 500, "Could not import metadata via the API #{e}", 'error'
# API endpoint that upserts metadata
exports.importMetadata = <span class="fstat-no" title="function not covered" ></span>() ->
handleMetadataPost 'import', this
# API endpoint that checks for conflicts between import object and database
exports.validateMetadata = <span class="fstat-no" title="function not covered" ></span>() ->
handleMetadataPost 'validate', this
if process.env.NODE_ENV == "test"
exports.buildResponseObject = buildResponseObject
exports.getUniqueIdentifierForCollection = getUniqueIdentifierForCollection
exports.removeProperties = removeProperties
</pre></td></tr>
</table></pre>
<div class='push'></div><!-- for sticky footer -->
</div><!-- /wrapper -->
<div class='footer quiet pad2 space-top1 center small'>
Code coverage
generated by <a href="http://istanbul-js.org/" target="_blank">istanbul</a> at Mon Oct 10 2016 13:39:22 GMT+0200 (SAST)
</div>
</div>
<script src="../../prettify.js"></script>
<script>
window.onload = function () {
if (typeof prettyPrint === 'function') {
prettyPrint();
}
};
</script>
<script src="../../sorter.js"></script>
</body>
</html>