openhim-core
Version:
The OpenHIM core application that provides logging and routing of http requests
1,372 lines (1,221 loc) • 44 kB
text/coffeescript
should = require "should"
http = require "http"
https = require "https"
fs = require "fs"
request = require "supertest"
config = require "../../lib/config/config"
config.authentication = config.get('authentication')
config.tlsClientLookup = config.get('tlsClientLookup')
Channel = require("../../lib/model/channels").Channel
Client = require("../../lib/model/clients").Client
Transaction = require("../../lib/model/transactions").Transaction
Keystore = require("../../lib/model/keystore").Keystore
testUtils = require "../testUtils"
server = require "../../lib/server"
FormData = require 'form-data'
describe "e2e Integration Tests", ->
describe "Authentication and authorisation tests", ->
describe "Mutual TLS", ->
mockServer = null
before (done) ->
config.authentication.enableMutualTLSAuthentication = true
config.authentication.enableBasicAuthentication = false
#Setup some test data
channel1 = new Channel
name: "TEST DATA - Mock endpoint"
urlPattern: "test/mock"
allow: [ "PoC" ]
routes: [
name: "test route"
host: "localhost"
port: 1232
primary: true
]
channel1.save (err) ->
testClientDoc1 =
clientID: "testApp"
clientDomain: "test-client.jembi.org"
name: "TEST Client"
roles:
[
"OpenMRS_PoC"
"PoC"
]
passwordHash: ""
certFingerprint: "6D:BF:A5:BE:D7:F5:01:C2:EC:D0:BC:74:A4:12:5A:6F:36:C4:77:5C"
testClientDoc2 =
clientID: "testApp2"
clientDomain: "ca.openhim.org"
name: "TEST Client 2"
roles:
[
"OpenMRS_PoC"
"PoC"
]
passwordHash: ""
certFingerprint: "18:B7:F9:52:FA:37:86:C5:F5:63:DA:8B:FA:E6:6B:4D:FB:A0:27:ED"
client1 = new Client testClientDoc1
client2 = new Client testClientDoc2
Client.remove {}, -> client1.save -> client2.save ->
# remove default keystore
Keystore.remove {}, ->
keystore = new Keystore
key: fs.readFileSync 'test/resources/server-tls/key.pem'
cert:
data: fs.readFileSync 'test/resources/server-tls/cert.pem'
fingerprint: '23:37:6A:5E:A9:13:A4:8C:66:C5:BB:9F:0E:0D:68:9B:99:80:10:FC'
ca: [
data: fs.readFileSync 'test/resources/client-tls/cert.pem'
fingerprint: '6D:BF:A5:BE:D7:F5:01:C2:EC:D0:BC:74:A4:12:5A:6F:36:C4:77:5C'
,
data: fs.readFileSync 'test/resources/trust-tls/chain/intermediate.cert.pem'
fingerprint: '3B:21:0A:F1:D2:ED:4F:9B:9C:02:71:DF:4E:14:1B:3E:32:F5:B9:BB'
,
data: fs.readFileSync 'test/resources/trust-tls/chain/ca.cert.pem'
fingerprint: '18:B7:F9:52:FA:37:86:C5:F5:63:DA:8B:FA:E6:6B:4D:FB:A0:27:ED'
]
keystore.save (err) ->
done err if err
mockServer = testUtils.createMockServer 201, "Mock response body\n", 1232, ->
done()
after (done) ->
Channel.remove { name: "TEST DATA - Mock endpoint" }, ->
Client.remove { clientID: "testApp" }, ->
Client.remove { clientID: "testApp2" }, ->
mockServer.close ->
done()
afterEach (done) ->
server.stop ->
done()
it "should forward a request to the configured routes if the client is authenticated and authorised", (done) ->
server.start httpPort: 5001, httpsPort: 5000, ->
options =
host: "localhost"
path: "/test/mock"
port: 5000
cert: fs.readFileSync "test/resources/client-tls/cert.pem"
key: fs.readFileSync "test/resources/client-tls/key.pem"
ca: [ fs.readFileSync "test/resources/server-tls/cert.pem" ]
req = https.request options, (res) ->
res.statusCode.should.be.exactly 201
done()
req.end()
it "should reject a request when using an invalid cert", (done) ->
server.start httpPort: 5001, httpsPort: 5000, ->
options =
host: "localhost"
path: "/test/mock"
port: 5000
cert: fs.readFileSync "test/resources/client-tls/invalid-cert.pem"
key: fs.readFileSync "test/resources/client-tls/invalid-key.pem"
ca: [ fs.readFileSync "test/resources/server-tls/cert.pem" ]
req = https.request options, (res) ->
res.statusCode.should.be.exactly 401
done()
req.end()
it "should authenticate a client further up the chain if 'in-chain' config is set", (done) ->
config.tlsClientLookup.type = "in-chain"
server.start httpPort: 5001, httpsPort: 5000, ->
options =
host: "localhost"
path: "/test/mock"
port: 5000
cert: fs.readFileSync "test/resources/trust-tls/chain/test.openhim.org.cert.pem"
key: fs.readFileSync "test/resources/trust-tls/chain/test.openhim.org.key.pem"
ca: [ fs.readFileSync "test/resources/server-tls/cert.pem" ]
req = https.request options, (res) ->
res.statusCode.should.be.exactly 201
done()
req.end()
it "should reject a request with an invalid cert if 'in-chain' config is set", (done) ->
config.tlsClientLookup.type = "in-chain"
server.start httpPort: 5001, httpsPort: 5000, ->
options =
host: "localhost"
path: "/test/mock"
port: 5000
cert: fs.readFileSync "test/resources/client-tls/invalid-cert.pem"
key: fs.readFileSync "test/resources/client-tls/invalid-key.pem"
ca: [ fs.readFileSync "test/resources/server-tls/cert.pem" ]
req = https.request options, (res) ->
res.statusCode.should.be.exactly 401
done()
req.end()
it "should NOT authenticate a client further up the chain if 'strict' config is set", (done) ->
config.tlsClientLookup.type = "strict"
server.start httpPort: 5001, httpsPort: 5000, ->
options =
host: "localhost"
path: "/test/mock"
port: 5000
cert: fs.readFileSync "test/resources/trust-tls/chain/test.openhim.org.cert.pem"
key: fs.readFileSync "test/resources/trust-tls/chain/test.openhim.org.key.pem"
ca: [ fs.readFileSync "test/resources/server-tls/cert.pem" ]
req = https.request options, (res) ->
res.statusCode.should.be.exactly 401
done()
req.end()
describe "Basic Authentication", ->
mockServer = null
before (done) ->
config.authentication.enableMutualTLSAuthentication = false
config.authentication.enableBasicAuthentication = true
#Setup some test data
channel1 = new Channel
name: "TEST DATA - Mock endpoint"
urlPattern: "test/mock"
allow: [ "PoC" ]
routes: [
name: "test route"
host: "localhost"
port: 1232
primary: true
]
channel1.save (err) ->
testAppDoc =
clientID: "testApp"
clientDomain: "openhim.jembi.org"
name: "TEST Client"
roles:
[
"OpenMRS_PoC"
"PoC"
]
passwordAlgorithm: "bcrypt"
passwordHash: "$2a$10$w8GyqInkl72LMIQNpMM/fenF6VsVukyya.c6fh/GRtrKq05C2.Zgy"
cert: ""
client = new Client testAppDoc
client.save (error, newAppDoc) ->
mockServer = testUtils.createMockServer 200, "Mock response body 1\n", 1232, ->
done()
after (done) ->
Channel.remove { name: "TEST DATA - Mock endpoint" }, ->
Client.remove { clientID: "testApp" }, ->
mockServer.close ->
done()
afterEach (done) ->
server.stop ->
done()
describe "with no credentials", ->
it "should `throw` 401", (done) ->
server.start httpPort: 5001, ->
request("http://localhost:5001")
.get("/test/mock")
.expect(401)
.end (err, res) ->
if err
done err
else
done()
describe "with incorrect credentials", ->
it "should `throw` 401", (done) ->
server.start httpPort: 5001, ->
request("http://localhost:5001")
.get("/test/mock")
.auth("incorrect_user", "incorrect_password")
.expect(401)
.expect('WWW-Authenticate', 'Basic')
.end (err, res) ->
if err
done err
else
done()
describe "with correct credentials", ->
it "should return 200 OK", (done) ->
server.start httpPort: 5001, ->
request("http://localhost:5001")
.get("/test/mock")
.auth("testApp", "password")
.expect(200)
.end (err, res) ->
if err
done err
else
done()
describe "POST and PUT tests", ->
mockServer = null
mockServerWithReturn = null
testDoc = "<test>test message</test>"
before (done) ->
config.authentication.enableMutualTLSAuthentication = false
config.authentication.enableBasicAuthentication = true
#Setup some test data
channel1 = new Channel
name: "TEST DATA - Mock endpoint"
urlPattern: "/test/mock"
allow: [ "PoC" ]
routes: [
name: "test route"
host: "localhost"
port: 1232
primary: true
]
channel2 = new Channel
name: "TEST DATA - Mock With Return endpoint"
urlPattern: "/gmo"
allow: [ "PoC" ]
routes: [
name: "test route return"
host: "localhost"
port: 1499
primary: true
]
channel3 = new Channel
name: "TEST DATA - Mock With Return endpoint public"
urlPattern: "/public"
allow: [ ]
authType: "public"
routes: [
name: "test route"
host: "localhost"
port: 1232
primary: true
]
channel4 = new Channel
name: "TEST DATA - Mock With Return endpoint private - whitelist"
urlPattern: "/private"
allow: [ ]
whitelist: ['::ffff:127.0.0.1', '127.0.0.1'] #localhost in IPV6
authType: "public"
routes: [
name: "test route"
host: "localhost"
port: 1232
primary: true
]
channel5 = new Channel
name: "TEST DATA - whitelist but un-authorised"
urlPattern: "/un-auth"
allow: [ 'private' ]
whitelist: ['::ffff:127.0.0.1', '127.0.0.1'] #localhost in IPV6
authType: "private"
routes: [
name: "test route"
host: "localhost"
port: 1232
primary: true
]
channel6 = new Channel
name: "TEST DATA - whitelist but authorised"
urlPattern: "/auth"
allow: [ 'PoC' ]
whitelist: ['::ffff:127.0.0.1', '127.0.0.1'] #localhost in IPV6
authType: "private"
routes: [
name: "test route"
host: "localhost"
port: 1232
primary: true
]
channel1.save (err) ->
channel2.save (err)->
channel3.save (err) ->
channel4.save (err) ->
channel5.save (err) ->
channel6.save (err) ->
testAppDoc =
clientID: "testApp"
clientDomain: "test-client.jembi.org"
name: "TEST Client"
roles:
[
"OpenMRS_PoC"
"PoC"
]
passwordAlgorithm: "sha512"
passwordHash: "28dce3506eca8bb3d9d5a9390135236e8746f15ca2d8c86b8d8e653da954e9e3632bf9d85484ee6e9b28a3ada30eec89add42012b185bd9a4a36a07ce08ce2ea"
passwordSalt: "1234567890"
cert: ""
client = new Client testAppDoc
client.save (error, newAppDoc) ->
# Create mock endpoint to forward requests to
mockServer = testUtils.createMockServerForPost(201, 400, testDoc)
mockServerWithReturn = testUtils.createMockServerForPostWithReturn(201, 400, testDoc)
mockServer.listen 1232, () ->
mockServerWithReturn.listen 1499, done
after (done) ->
Channel.remove {}, ->
Client.remove { clientID: "testApp" }, ->
mockServer.close ->
mockServerWithReturn.close ->
done()
afterEach (done) ->
server.stop ->
done()
it "should return 201 CREATED on POST", (done) ->
server.start httpPort: 5001, ->
request("http://localhost:5001")
.post("/test/mock")
.send(testDoc)
.auth("testApp", "password")
.expect(201)
.end (err, res) ->
if err
done err
else
done()
it "should return 201 CREATED on POST - Public Channel", (done) ->
server.start httpPort: 5001, ->
request("http://localhost:5001")
.post("/public")
.send(testDoc)
.expect(201)
.end (err, res) ->
if err
done err
else
done()
it "should return 201 CREATED on POST - Public Channel with whitelisted ip", (done) ->
server.start httpPort: 5001, ->
request("http://localhost:5001")
.post("/private")
.send(testDoc)
.expect(201)
.end (err, res) ->
if err
done err
else
done()
it "should deny access on POST - Private Channel with whitelisted IP but incorrect client role", (done) ->
server.start httpPort: 5001, ->
request("http://localhost:5001")
.post("/un-auth")
.send(testDoc)
.auth("testApp", "password")
.expect(401)
.end (err, res) ->
if err
done err
else
done()
it "should return 201 CREATED on POST - Private Channel with whitelisted IP and correct client role", (done) ->
server.start httpPort: 5001, ->
request("http://localhost:5001")
.post("/auth")
.send(testDoc)
.auth("testApp", "password")
.expect(201)
.end (err, res) ->
if err
done err
else
done()
it "should return 201 CREATED on PUT", (done) ->
server.start httpPort: 5001, ->
request("http://localhost:5001")
.put("/test/mock")
.send(testDoc)
.auth("testApp", "password")
.expect(201)
.end (err, res) ->
if err
done err
else
done()
it "should decompress gzip", (done) ->
server.start httpPort: 5001, ->
request("http://localhost:5001")
.put("/gmo")
.set('Accept-Encoding', '') #Unset encoding, because supertest defaults to gzip,deflate
.send(testDoc)
.auth("testApp", "password")
.expect(201)
.expect(testDoc, done)
it "should returned gzipped response", (done) ->
server.start httpPort: 5001, ->
request("http://localhost:5001")
.put("/gmo")
.set('Accept-Encoding', 'gzip')
.send(testDoc)
.auth("testApp", "password")
.expect(201)
.expect("content-encoding", "gzip")
.expect(testDoc)
.end (err, res) ->
if err
done err
else
done()
describe "HTTP header tests", ->
mockServer = null
testDoc = "<test>test message</test>"
before (done) ->
config.authentication.enableMutualTLSAuthentication = false
config.authentication.enableBasicAuthentication = true
#Setup some test data
channel1 = new Channel
name: "TEST DATA - Mock endpoint"
urlPattern: "test/mock"
allow: [ "PoC" ]
routes: [
name: "test route"
host: "localhost"
port: 6262
primary: true
]
channel1.save (err) ->
testAppDoc =
clientID: "testApp"
clientDomain: "test-client.jembi.org"
name: "TEST Client"
roles:
[
"OpenMRS_PoC"
"PoC"
]
passwordAlgorithm: "sha512"
passwordHash: "28dce3506eca8bb3d9d5a9390135236e8746f15ca2d8c86b8d8e653da954e9e3632bf9d85484ee6e9b28a3ada30eec89add42012b185bd9a4a36a07ce08ce2ea"
passwordSalt: "1234567890"
cert: ""
client = new Client testAppDoc
client.save (error, newAppDoc) ->
# Create mock endpoint to forward requests to
mockServer = testUtils.createMockServer 201, testDoc, 6262, ->
done()
after (done) ->
Channel.remove { name: "TEST DATA - Mock endpoint" }, ->
Client.remove { clientID: "testApp" }, ->
mockServer.close ->
done()
afterEach (done) ->
server.stop ->
done()
it "should keep HTTP headers of the response intact", (done) ->
server.start httpPort: 5001, ->
request("http://localhost:5001")
.get("/test/mock")
.send(testDoc)
.auth("testApp", "password")
.expect(201)
.expect('Content-Type', 'text/plain; charset=utf-8')
.end (err, res) ->
if err
done err
else
done()
describe "HTTP body content matching - XML", ->
mockServer = null
testXMLDoc = """
<careServicesRequest>
<function uuid='4e8bbeb9-f5f5-11e2-b778-0800200c9a66'>
<codedType code="2221" codingScheme="ISCO-08" />
<address>
<addressLine component='city'>Kigali</addressLine>
</address>
<max>5</max>
</function>
</careServicesRequest>
"""
before (done) ->
config.authentication.enableMutualTLSAuthentication = false
config.authentication.enableBasicAuthentication = true
#Setup some test data
channel1 = new Channel
name: "TEST DATA - Mock endpoint"
urlPattern: "test/mock"
allow: [ "PoC" ]
routes: [
name: "test route"
host: "localhost"
port: 1232
primary: true
]
matchContentTypes: [ "text/xml" ]
matchContentXpath: "string(/careServicesRequest/function/@uuid)"
matchContentValue: "4e8bbeb9-f5f5-11e2-b778-0800200c9a66"
channel1.save (err) ->
testAppDoc =
clientID: "testApp"
clientDomain: "test-client.jembi.org"
name: "TEST Client"
roles:
[
"OpenMRS_PoC"
"PoC"
]
passwordAlgorithm: "sha512"
passwordHash: "28dce3506eca8bb3d9d5a9390135236e8746f15ca2d8c86b8d8e653da954e9e3632bf9d85484ee6e9b28a3ada30eec89add42012b185bd9a4a36a07ce08ce2ea"
passwordSalt: "1234567890"
cert: ""
client = new Client testAppDoc
client.save (error, newAppDoc) ->
# Create mock endpoint to forward requests to
mockServer = testUtils.createMockServerForPost(201, 400, testXMLDoc)
mockServer.listen 1232, done
after (done) ->
Channel.remove { name: "TEST DATA - Mock endpoint" }, ->
Client.remove { clientID: "testApp" }, ->
mockServer.close ->
done()
afterEach (done) ->
server.stop ->
done()
it "should return 201 CREATED on POST", (done) ->
server.start httpPort: 5001, ->
request("http://localhost:5001")
.post("/test/mock")
.set("Content-Type", "text/xml")
.send(testXMLDoc)
.auth("testApp", "password")
.expect(201)
.end (err, res) ->
if err
done err
else
done()
it "should return 201 CREATED on PUT", (done) ->
server.start httpPort: 5001, ->
request("http://localhost:5001")
.put("/test/mock")
.set("Content-Type", "text/xml")
.send(testXMLDoc)
.auth("testApp", "password")
.expect(201)
.end (err, res) ->
if err
done err
else
done()
describe "HTTP body content matching - JSON", ->
mockServer = null
testJSONDoc = '''
{
"functionId": 1234,
"personId": "987",
"name": "John Smith"
}
'''
before (done) ->
config.authentication.enableMutualTLSAuthentication = false
config.authentication.enableBasicAuthentication = true
#Setup some test data
channel1 = new Channel
name: "TEST DATA - Mock endpoint"
urlPattern: "test/mock"
allow: [ "PoC" ]
routes: [
name: "test route"
host: "localhost"
port: 1232
primary: true
]
matchContentTypes: [ "text/x-json", "application/json" ]
matchContentJson: "functionId"
matchContentValue: "1234"
channel1.save (err) ->
testAppDoc =
clientID: "testApp"
clientDomain: "test-client.jembi.org"
name: "TEST Client"
roles:
[
"OpenMRS_PoC"
"PoC"
]
passwordAlgorithm: "sha512"
passwordHash: "28dce3506eca8bb3d9d5a9390135236e8746f15ca2d8c86b8d8e653da954e9e3632bf9d85484ee6e9b28a3ada30eec89add42012b185bd9a4a36a07ce08ce2ea"
passwordSalt: "1234567890"
cert: ""
client = new Client testAppDoc
client.save (error, newAppDoc) ->
# Create mock endpoint to forward requests to
mockServer = testUtils.createMockServerForPost(201, 400, testJSONDoc)
mockServer.listen 1232, done
after (done) ->
Channel.remove { name: "TEST DATA - Mock endpoint" }, ->
Client.remove { clientID: "testApp" }, ->
mockServer.close ->
done()
afterEach (done) ->
server.stop ->
done()
it "should return 201 CREATED on POST", (done) ->
server.start httpPort: 5001, ->
request("http://localhost:5001")
.post("/test/mock")
.set("Content-Type", "application/json")
.send(testJSONDoc)
.auth("testApp", "password")
.expect(201)
.end (err, res) ->
if err
done err
else
done()
it "should return 201 CREATED on PUT", (done) ->
server.start httpPort: 5001, ->
request("http://localhost:5001")
.put("/test/mock")
.set("Content-Type", "application/json")
.send(testJSONDoc)
.auth("testApp", "password")
.expect(201)
.end (err, res) ->
if err
done err
else
done()
describe "HTTP body content matching - RegEx", ->
mockServer = null
testRegExDoc = "facility: OMRS123"
before (done) ->
config.authentication.enableMutualTLSAuthentication = false
config.authentication.enableBasicAuthentication = true
#Setup some test data
channel1 = new Channel
name: "TEST DATA - Mock endpoint"
urlPattern: "test/mock"
allow: [ "PoC" ]
routes: [
name: "test route"
host: "localhost"
port: 1232
primary: true
]
matchContentRegex: "\\s[A-Z]{4}\\d{3}"
channel1.save (err) ->
testAppDoc =
clientID: "testApp"
clientDomain: "test-client.jembi.org"
name: "TEST Client"
roles:
[
"OpenMRS_PoC"
"PoC"
]
passwordAlgorithm: "sha512"
passwordHash: "28dce3506eca8bb3d9d5a9390135236e8746f15ca2d8c86b8d8e653da954e9e3632bf9d85484ee6e9b28a3ada30eec89add42012b185bd9a4a36a07ce08ce2ea"
passwordSalt: "1234567890"
cert: ""
client = new Client testAppDoc
client.save (error, newAppDoc) ->
# Create mock endpoint to forward requests to
mockServer = testUtils.createMockServerForPost(201, 400, testRegExDoc)
mockServer.listen 1232, done
after (done) ->
Channel.remove { name: "TEST DATA - Mock endpoint" }, ->
Client.remove { clientID: "testApp" }, ->
mockServer.close ->
done()
afterEach (done) ->
server.stop ->
done()
it "should return 201 CREATED on POST", (done) ->
server.start httpPort: 5001, ->
request("http://localhost:5001")
.post("/test/mock")
.send(testRegExDoc)
.auth("testApp", "password")
.expect(201)
.end (err, res) ->
if err
done err
else
done()
it "should return 201 CREATED on PUT", (done) ->
server.start httpPort: 5001, ->
request("http://localhost:5001")
.put("/test/mock")
.send(testRegExDoc)
.auth("testApp", "password")
.expect(201)
.end (err, res) ->
if err
done err
else
done()
describe "mediator tests", ->
mockServer = null
mediatorResponse =
status: "Successful"
response:
status: 200
headers: {}
body: "<transaction response>"
timestamp: new Date
orchestrations: [
name: "Lab API"
request:
path: "api/patient/lab"
headers:
"Content-Type": "text/plain"
body: "<route request>"
method: "POST"
timestamp: new Date
response:
status: 200
headers: {}
body: "<route response>"
timestamp: new Date
]
properties:
orderId: "TEST00001"
documentId: "1f49c3e0-3cec-4292-b495-5bd41433a048"
before (done) ->
config.authentication.enableMutualTLSAuthentication = false
config.authentication.enableBasicAuthentication = true
mediatorChannel = new Channel
name: "TEST DATA - Mock mediator endpoint"
urlPattern: "test/mediator"
allow: [ "PoC" ]
routes: [
name: "mediator route"
host: "localhost"
port: 1244
primary: true
]
mediatorChannel.save (err) ->
testAppDoc =
clientID: "mediatorTestApp"
clientDomain: "test-client.jembi.org"
name: "TEST Client"
roles:
[
"OpenMRS_PoC"
"PoC"
]
passwordAlgorithm: "sha512"
passwordHash: "28dce3506eca8bb3d9d5a9390135236e8746f15ca2d8c86b8d8e653da954e9e3632bf9d85484ee6e9b28a3ada30eec89add42012b185bd9a4a36a07ce08ce2ea"
passwordSalt: "1234567890"
cert: ""
client = new Client testAppDoc
client.save (error, newAppDoc) ->
mockServer = testUtils.createMockMediatorServer 200, mediatorResponse, 1244, -> done()
beforeEach (done) -> Transaction.remove {}, done
after (done) ->
Channel.remove { name: "TEST DATA - Mock mediator endpoint" }, ->
Client.remove { clientID: "mediatorTestApp" }, ->
mockServer.close ->
done()
afterEach (done) ->
server.stop ->
Transaction.remove {}, ->
done()
describe "mediator response processing", ->
it "should return the specified mediator response element as the actual response", (done) ->
server.start httpPort: 5001, ->
request("http://localhost:5001")
.get("/test/mediator")
.auth("mediatorTestApp", "password")
.expect(200)
.expect(mediatorResponse.response.body, done)
it "should setup the correct metadata on the transaction as specified by the mediator response", (done) ->
server.start httpPort: 5001, ->
request("http://localhost:5001")
.get("/test/mediator")
.auth("mediatorTestApp", "password")
.expect(200)
.end (err, res) ->
if err
done err
else
setTimeout ( ->
Transaction.findOne {}, (err, res) ->
res.status.should.be.equal mediatorResponse.status
res.orchestrations.length.should.be.exactly 1
res.orchestrations[0].name.should.be.equal mediatorResponse.orchestrations[0].name
should.exist res.properties
res.properties.orderId.should.be.equal mediatorResponse.properties.orderId
done()
), 150 * global.testTimeoutFactor
describe "Multipart form data tests", ->
mockServer = null
before (done) ->
config.authentication.enableMutualTLSAuthentication = false
config.authentication.enableBasicAuthentication = true
mediatorResponse =
status: "Successful"
response:
status: 200
headers: {}
body: "<transaction response>"
timestamp: new Date
orchestrations: [
name: "Lab API"
request:
path: "api/patient/lab"
headers:
"Content-Type": "text/plain"
body: "<route request>"
method: "POST"
timestamp: new Date
response:
status: 200
headers: {}
body: "<route response>"
timestamp: new Date
]
#Setup some test data
channel1 = new Channel
name: "TEST DATA - Mock endpoint - multipart"
urlPattern: "/test/multipart"
allow: [ "PoC" ]
routes: [
name: "test route"
host: "localhost"
port: 1276
primary: true
]
channel1.save (err) ->
testAppDoc =
clientID: "testAppMultipart"
clientDomain: "test-client.jembi.org"
name: "TEST Client"
roles: [
"OpenMRS_PoC"
"PoC"
]
passwordAlgorithm: "sha512"
passwordHash: "28dce3506eca8bb3d9d5a9390135236e8746f15ca2d8c86b8d8e653da954e9e3632bf9d85484ee6e9b28a3ada30eec89add42012b185bd9a4a36a07ce08ce2ea"
passwordSalt: "1234567890"
cert: ""
client = new Client testAppDoc
client.save (error, newAppDoc) ->
mockServer = testUtils.createMockMediatorServer 200, mediatorResponse, 1276, ->
done()
after (done) ->
Channel.remove { name: "TEST DATA - Mock endpoint - multipart" }, ->
Client.remove { clientID: "testAppMultipart" }, ->
done()
afterEach (done) ->
server.stop ->
done()
it "should return 201 CREATED on POST", (done) ->
server.start httpPort: 5001, ->
form = new FormData()
form.append('my_field', 'my value')
form.append('unix', fs.readFileSync "test/resources/files/unix.txt")
form.append('mac', fs.readFileSync "test/resources/files/mac.txt")
form.append('msdos', fs.readFileSync "test/resources/files/msdos.txt")
form.submit
host: "localhost"
port: 5001
path: "/test/multipart"
auth: "testAppMultipart:password"
method: "post"
, (err, res) ->
res.statusCode.should.equal 200
res.on "data", (chunk) ->
# chunk.should.be.ok
if err
done err
else
done()
describe "URL rewriting e2e test", ->
mockServer = null
jsonResponse =
href: 'http://localhost:1232/test/mock'
before (done) ->
config.authentication.enableMutualTLSAuthentication = false
config.authentication.enableBasicAuthentication = true
# Setup some test data
channel1 = new Channel
name: "TEST DATA - Mock endpoint"
urlPattern: "test/mock"
allow: [ "PoC" ]
routes: [
name: "test route"
host: "localhost"
port: 1232
primary: true
]
rewriteUrls: true
channel1.save (err) ->
testAppDoc =
clientID: "testApp"
clientDomain: "test-client.jembi.org"
name: "TEST Client"
roles:
[
"OpenMRS_PoC"
"PoC"
]
passwordAlgorithm: "sha512"
passwordHash: "28dce3506eca8bb3d9d5a9390135236e8746f15ca2d8c86b8d8e653da954e9e3632bf9d85484ee6e9b28a3ada30eec89add42012b185bd9a4a36a07ce08ce2ea"
passwordSalt: "1234567890"
cert: ""
client = new Client testAppDoc
client.save (error, newAppDoc) ->
# Create mock endpoint to forward requests to
mockServer = testUtils.createMockServer 201, JSON.stringify(jsonResponse), 1232, -> done()
after (done) ->
Channel.remove { name: "TEST DATA - Mock endpoint" }, ->
Client.remove { clientID: "testApp" }, ->
mockServer.close ->
done()
afterEach (done) ->
server.stop ->
done()
it "should rewrite response urls", (done) ->
server.start httpPort: 5001, ->
request("http://localhost:5001")
.get("/test/mock")
.auth("testApp", "password")
.expect(201)
.end (err, res) ->
if err
done err
else
response = JSON.parse res.text
response.href.should.be.exactly 'http://localhost:5001/test/mock'
done()
describe "Routes enabled/disabled tests", ->
mockServer1 = null
mockServer2 = null
channel1 = new Channel
name: "TEST DATA - Mock endpoint 1"
urlPattern: "^/test/channel1$"
allow: [ "PoC" ]
routes: [
{
name: "test route"
host: "localhost"
port: 1233
primary: true
}, {
name: "test route 2"
host: "localhost"
port: 1234
}
]
channel2 = new Channel
name: "TEST DATA - Mock endpoint 2"
urlPattern: "^/test/channel2$"
allow: [ "PoC" ]
routes: [
{
name: "test route"
host: "localhost"
port: 1233
status: 'disabled'
}, {
name: "test route 2"
host: "localhost"
port: 1234
primary: true
status: 'enabled'
}
]
channel3 = new Channel
name: "TEST DATA - Mock endpoint 3"
urlPattern: "^/test/channel3$"
allow: [ "PoC" ]
routes: [
{
name: "test route"
host: "localhost"
port: 1233
primary: true
status: 'enabled'
}, {
name: "test route 2"
host: "localhost"
port: 1234
primary: true
status: 'disabled'
}
]
before (done) ->
config.authentication.enableMutualTLSAuthentication = false
config.authentication.enableBasicAuthentication = true
channel1.save (err) -> channel2.save (err) -> channel3.save (err) ->
testAppDoc =
clientID: "testApp"
clientDomain: "test-client.jembi.org"
name: "TEST Client"
roles:
[
"OpenMRS_PoC"
"PoC"
]
passwordAlgorithm: "sha512"
passwordHash: "28dce3506eca8bb3d9d5a9390135236e8746f15ca2d8c86b8d8e653da954e9e3632bf9d85484ee6e9b28a3ada30eec89add42012b185bd9a4a36a07ce08ce2ea"
passwordSalt: "1234567890"
cert: ""
client = new Client testAppDoc
client.save (error, newAppDoc) ->
# Create mock endpoint to forward requests to
mockServer1 = testUtils.createMockServer 200, 'target1', 1233, ->
mockServer2 = testUtils.createMockServer 200, 'target2', 1234, -> done()
after (done) ->
Channel.remove { name: "TEST DATA - Mock endpoint 1" }, ->
Channel.remove { name: "TEST DATA - Mock endpoint 2" }, ->
Channel.remove { name: "TEST DATA - Mock endpoint 3" }, ->
Client.remove { clientID: "testApp" }, ->
mockServer1.close ->
mockServer2.close ->
done()
afterEach (done) -> server.stop -> Transaction.remove {}, done
beforeEach (done) -> Transaction.remove {}, done
it "should route transactions to routes that have no status specified (default: enabled)", (done) ->
server.start httpPort: 5001, ->
request("http://localhost:5001")
.get("/test/channel1")
.auth("testApp", "password")
.expect(200)
.end (err, res) ->
if err
done err
else
res.text.should.be.exactly 'target1'
# routes are async
setTimeout ( ->
Transaction.findOne {}, (err, trx) ->
return done err if err
trx.routes.length.should.be.exactly 1
trx.routes[0].should.have.property 'name', 'test route 2'
trx.routes[0].response.body.should.be.exactly 'target2'
done()
), 150 * global.testTimeoutFactor
it "should NOT route transactions to disabled routes", (done) ->
server.start httpPort: 5001, ->
request("http://localhost:5001")
.get("/test/channel2")
.auth("testApp", "password")
.expect(200)
.end (err, res) ->
if err
done err
else
res.text.should.be.exactly 'target2'
# routes are async
setTimeout ( ->
Transaction.findOne {}, (err, trx) ->
return done err if err
trx.routes.length.should.be.exactly 0
done()
), 150 * global.testTimeoutFactor
it "should ignore disabled primary routes (multiple primary routes)", (done) ->
server.start httpPort: 5001, ->
request("http://localhost:5001")
.get("/test/channel3")
.auth("testApp", "password")
.expect(200)
.end (err, res) ->
if err
done err
else
res.text.should.be.exactly 'target1'
# routes are async
setTimeout ( ->
Transaction.findOne {}, (err, trx) ->
return done err if err
trx.routes.length.should.be.exactly 0
done()
), 150 * global.testTimeoutFactor
describe "Channel priority tests", ->
mockServer1 = null
mockServer2 = null
channel1 = new Channel
name: "TEST DATA - Mock endpoint 1"
urlPattern: "^/test/undefined/priority$"
allow: [ "PoC" ]
routes: [
name: "test route"
host: "localhost"
port: 1234
primary: true
]
channel2 = new Channel
name: "TEST DATA - Mock endpoint 2"
urlPattern: "^/.*$"
priority: 3
allow: [ "PoC" ]
routes: [
name: "test route"
host: "localhost"
port: 1233
primary: true
]
channel3 = new Channel
name: "TEST DATA - Mock endpoint 3"
urlPattern: "^/test/mock$"
priority: 2
allow: [ "PoC" ]
routes: [
name: "test route"
host: "localhost"
port: 1234
primary: true
]
before (done) ->
config.authentication.enableMutualTLSAuthentication = false
config.authentication.enableBasicAuthentication = true
channel1.save (err) -> channel2.save (err) -> channel3.save (err) ->
testAppDoc =
clientID: "testApp"
clientDomain: "test-client.jembi.org"
name: "TEST Client"
roles:
[
"OpenMRS_PoC"
"PoC"
]
passwordAlgorithm: "sha512"
passwordHash: "28dce3506eca8bb3d9d5a9390135236e8746f15ca2d8c86b8d8e653da954e9e3632bf9d85484ee6e9b28a3ada30eec89add42012b185bd9a4a36a07ce08ce2ea"
passwordSalt: "1234567890"
cert: ""
client = new Client testAppDoc
client.save (error, newAppDoc) ->
# Create mock endpoint to forward requests to
mockServer1 = testUtils.createMockServer 200, 'target1', 1233, ->
mockServer2 = testUtils.createMockServer 200, 'target2', 1234, -> done()
after (done) ->
Channel.remove { name: "TEST DATA - Mock endpoint 1" }, ->
Channel.remove { name: "TEST DATA - Mock endpoint 2" }, ->
Channel.remove { name: "TEST DATA - Mock endpoint 3" }, ->
Channel.remove { name: "TEST DATA - Mock endpoint 4" }, ->
Client.remove { clientID: "testApp" }, ->
mockServer1.close ->
mockServer2.close ->
done()
afterEach (done) ->
server.stop ->
done()
it "should route to the channel with higher priority if multiple channels match a request", (done) ->
server.start httpPort: 5001, ->
request("http://localhost:5001")
.get("/test/mock")
.auth("testApp", "password")
.expect(200)
.end (err, res) ->
if err
done err
else
res.text.should.be.exactly 'target2' #should route to target2 via channel3
done()
it "should treat a channel with an undefined priority with lowest priority", (done) ->
server.start httpPort: 5001, ->
request("http://localhost:5001")
.get("/test/undefined/priority")
.auth("testApp", "password")
.expect(200)
.end (err, res) ->
if err
done err
else
res.text.should.be.exactly 'target1' #should route to target1 via channel2
done()
it "should deny access if multiple channels match but the top priority channel denies access", (done) ->
channel4 = new Channel
name: "TEST DATA - Mock endpoint 4"
urlPattern: "^/test/mock$"
priority: 1
allow: [ "something else" ]
routes: [
name: "test route"
host: "localhost"
port: 1234
primary: true
]
channel4.save () ->
server.start httpPort: 5001, ->
request("http://localhost:5001")
.get("/test/mock")
.auth("testApp", "password")
.expect(401)
.end (err, res) ->
if err
done err
else
done()