openhim-core
Version:
The OpenHIM core application that provides logging and routing of http requests
485 lines (427 loc) • 17.6 kB
text/coffeescript
should = require "should"
sinon = require "sinon"
authorisation = require "../../lib/middleware/authorisation"
Channel = require("../../lib/model/channels").Channel
describe "Authorisation middleware", ->
describe ".authorise(ctx, done)", ->
validTestBody = """
<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>
"""
invalidTestBody = """
<careServicesRequest>
<function uuid='invalid'>
<codedType code="2221" codingScheme="ISCO-08" />
<address>
<addressLine component='city'>Kigali</addressLine>
</address>
<max>5</max>
</function>
</careServicesRequest>
"""
addedChannelNames = []
afterEach ->
# remove test channels
for channelName in addedChannelNames
Channel.remove { name: channelName }, (err) ->
addedChannelNames = []
it "should allow a request if the client is authorised to use the channel by role", (done) ->
# Setup a channel for the mock endpoint
channel = new Channel
name: "Authorisation mock channel 1"
urlPattern: "test/authorisation"
allow: [ "PoC", "Test1", "Test2" ]
routes: [
name: "test route"
host: "localhost"
port: 9876
primary: true
]
addedChannelNames.push channel.name
channel.save (err) ->
if err
return done err
# Setup test data, will need authentication mechanisms to set ctx.authenticated
ctx = {}
ctx.authenticated =
clientID: "Musha_OpenMRS"
domain: "poc1.jembi.org"
name: "OpenMRS Musha instance"
roles: [ "OpenMRS_PoC", "PoC" ]
passwordHash: ""
cert: ""
ctx.request = {}
ctx.request.url = "test/authorisation"
ctx.request.path = "test/authorisation"
ctx.response = {}
authorisation.authorise ctx, ->
ctx.authorisedChannel.should.exist
done()
it "should deny a request if the client is NOT authorised to use the channel by role", (done) ->
# Setup a channel for the mock endpoint
channel = new Channel
name: "Authorisation mock channel 2"
urlPattern: "test/authorisation"
allow: [ "Something-else" ]
routes: [
name: "test route"
host: "localhost"
port: 9876
primary: true
]
addedChannelNames.push channel.name
channel.save (err) ->
if err
return done err
# Setup test data, will need authentication mechanisms to set ctx.authenticated
ctx = {}
ctx.authenticated =
clientID: "Musha_OpenMRS"
domain: "poc1.jembi.org"
name: "OpenMRS Musha instance"
roles: [ "OpenMRS_PoC", "PoC" ]
passwordHash: ""
cert: ""
ctx.request = {}
ctx.request.url = "test/authorisation"
ctx.request.path = "test/authorisation"
ctx.response = {}
ctx.set = ->
authorisation.authorise ctx, ->
(ctx.authorisedChannel == undefined).should.be.true
ctx.response.status.should.be.exactly 401
done()
it "should allow a request if the client is authorised to use the channel by clientID", (done) ->
# Setup a channel for the mock endpoint
channel = new Channel
name: "Authorisation mock channel 3"
urlPattern: "test/authorisation"
allow: [ "Test1", "Musha_OpenMRS", "Test2" ]
routes: [
name: "test route"
host: "localhost"
port: 9876
primary: true
]
addedChannelNames.push channel.name
channel.save (err) ->
if err
return done err
# Setup test data, will need authentication mechanisms to set ctx.authenticated
ctx = {}
ctx.authenticated =
clientID: "Musha_OpenMRS"
domain: "poc1.jembi.org"
name: "OpenMRS Musha instance"
roles: [ "OpenMRS_PoC", "PoC" ]
passwordHash: ""
cert: ""
ctx.request = {}
ctx.request.url = "test/authorisation"
ctx.request.path = "test/authorisation"
ctx.response = {}
authorisation.authorise ctx, ->
ctx.authorisedChannel.should.exist
done()
it 'should authorise if message content matches the channel rules', (done) ->
# Setup a channel for the mock endpoint
channel = new Channel
name: "Authorisation mock channel 4"
urlPattern: "test/authorisation"
allow: [ "Test1", "Musha_OpenMRS", "Test2" ]
routes: [
name: "test route"
host: "localhost"
port: 9876
primary: true
]
matchContentXpath: "string(/careServicesRequest/function/@uuid)"
matchContentValue: "4e8bbeb9-f5f5-11e2-b778-0800200c9a66"
addedChannelNames.push channel.name
channel.save (err) ->
if err
return done err
# Setup test data, will need authentication mechanisms to set ctx.authenticated
ctx = {}
ctx.body = validTestBody
ctx.authenticated =
clientID: "Musha_OpenMRS"
clientDomain: "poc1.jembi.org"
name: "OpenMRS Musha instance"
roles: [ "OpenMRS_PoC", "PoC" ]
passwordHash: ""
cert: ""
ctx.request = {}
ctx.request.url = "test/authorisation"
ctx.request.path = "test/authorisation"
ctx.response = {}
authorisation.authorise ctx, ->
ctx.authorisedChannel.should.exist
done()
it 'should NOT authorise if message content DOES NOT matches the channel rules', (done) ->
# Setup a channel for the mock endpoint
channel = new Channel
name: "Authorisation mock channel 4"
urlPattern: "test/authorisation"
allow: [ "Test1", "Musha_OpenMRS", "Test2" ]
routes: [
name: "test route"
host: "localhost"
port: 9876
primary: true
]
matchContentXpath: "string(/careServicesRequest/function/@uuid)"
matchContentValue: "4e8bbeb9-f5f5-11e2-b778-0800200c9a66"
addedChannelNames.push channel.name
channel.save (err) ->
if err
return done err
# Setup test data, will need authentication mechanisms to set ctx.authenticated
ctx = {}
ctx.body = invalidTestBody
ctx.authenticated =
clientID: "Musha_OpenMRS"
clientDomain: "poc1.jembi.org"
name: "OpenMRS Musha instance"
roles: [ "OpenMRS_PoC", "PoC" ]
passwordHash: ""
cert: ""
ctx.request = {}
ctx.request.url = "test/authorisation"
ctx.request.path = "test/authorisation"
ctx.response = {}
ctx.set = ->
authorisation.authorise ctx, ->
(ctx.authorisedChannel == undefined).should.be.true
done()
it 'should authorise if message content matches the content-type', (done) ->
# Setup a channel for the mock endpoint
channel = new Channel
name: "Authorisation mock channel 4"
urlPattern: "test/authorisation"
allow: [ "Test1", "Musha_OpenMRS", "Test2" ]
routes: [
name: "test route"
host: "localhost"
port: 9876
primary: true
]
matchContentTypes: [ "text/xml" ]
matchContentXpath: "string(/careServicesRequest/function/@uuid)"
matchContentValue: "4e8bbeb9-f5f5-11e2-b778-0800200c9a66"
addedChannelNames.push channel.name
channel.save (err) ->
if err
return done err
# Setup test data, will need authentication mechanisms to set ctx.authenticated
ctx = {}
ctx.body = validTestBody
ctx.authenticated =
clientID: "Musha_OpenMRS"
clientDomain: "poc1.jembi.org"
name: "OpenMRS Musha instance"
roles: [ "OpenMRS_PoC", "PoC" ]
passwordHash: ""
cert: ""
ctx.request = {}
ctx.request.url = "test/authorisation"
ctx.request.path = "test/authorisation"
ctx.request.header = {}
ctx.request.header['content-type'] = "text/xml; charset=utf-8"
ctx.response = {}
authorisation.authorise ctx, ->
ctx.authorisedChannel.should.exist
done()
it 'should NOT authorise if message content DOES NOT matches the channel rules', (done) ->
# Setup a channel for the mock endpoint
channel = new Channel
name: "Authorisation mock channel 4"
urlPattern: "test/authorisation"
allow: [ "Test1", "Musha_OpenMRS", "Test2" ]
routes: [
name: "test route"
host: "localhost"
port: 9876
primary: true
]
matchContentTypes: [ "text/xml" ]
matchContentXpath: "string(/careServicesRequest/function/@uuid)"
matchContentValue: "4e8bbeb9-f5f5-11e2-b778-0800200c9a66"
addedChannelNames.push channel.name
channel.save (err) ->
if err
return done err
# Setup test data, will need authentication mechanisms to set ctx.authenticated
ctx = {}
ctx.body = invalidTestBody
ctx.authenticated =
clientID: "Musha_OpenMRS"
clientDomain: "poc1.jembi.org"
name: "OpenMRS Musha instance"
roles: [ "OpenMRS_PoC", "PoC" ]
passwordHash: ""
cert: ""
ctx.request = {}
ctx.request.url = "test/authorisation"
ctx.request.path = "test/authorisation"
ctx.request.header = {}
ctx.request.header['content-type'] = "text/dodgy-xml; charset=utf-8"
ctx.response = {}
ctx.set = ->
authorisation.authorise ctx, ->
(ctx.authorisedChannel == undefined).should.be.true
done()
it "should allow a request if the client is authorised and the channel is enabled", (done) ->
# Setup a channel for the mock endpoint
channel = new Channel
name: "Mock for Channel Status Test (enabled)"
urlPattern: "test/status/enabled"
allow: [ "PoC", "Test1", "Test2" ]
routes: [
name: "test route"
host: "localhost"
port: 9876
primary: true
]
status: "enabled"
addedChannelNames.push channel.name
channel.save (err) ->
if err
return done err
# Setup test data, will need authentication mechanisms to set ctx.authenticated
ctx = {}
ctx.authenticated =
clientID: "Musha_OpenMRS"
domain: "poc1.jembi.org"
name: "OpenMRS Musha instance"
roles: [ "OpenMRS_PoC", "PoC" ]
passwordHash: ""
cert: ""
ctx.request = {}
ctx.request.url = "test/status/enabled"
ctx.request.path = "test/status/enabled"
ctx.response = {}
authorisation.authorise ctx, ->
ctx.authorisedChannel.should.exist
done()
it "should NOT allow a request if the client is authorised but the channel is disabled", (done) ->
# Setup a channel for the mock endpoint
channel = new Channel
name: "Mock for Channel Status Test (disabled)"
urlPattern: "test/status/disabled"
allow: [ "PoC", "Test1", "Test2" ]
routes: [
name: "test route"
host: "localhost"
port: 9876
primary: true
]
status: "disabled"
addedChannelNames.push channel.name
channel.save (err) ->
if err
return done err
# Setup test data, will need authentication mechanisms to set ctx.authenticated
ctx = {}
ctx.authenticated =
clientID: "Musha_OpenMRS"
domain: "poc1.jembi.org"
name: "OpenMRS Musha instance"
roles: [ "OpenMRS_PoC", "PoC" ]
passwordHash: ""
cert: ""
ctx.request = {}
ctx.request.url = "test/status/disabled"
ctx.request.path = "test/status/disabled"
ctx.response = {}
ctx.set = ->
authorisation.authorise ctx, ->
(ctx.authorisedChannel == undefined).should.be.true
done()
it "should NOT allow a request if the client is authorised but the channel is deleted", (done) ->
# Setup a channel for the mock endpoint
channel = new Channel
name: "Mock for Channel Status Test (deleted)"
urlPattern: "test/status/deleted"
allow: [ "PoC", "Test1", "Test2" ]
routes: [
name: "test route"
host: "localhost"
port: 9876
primary: true
]
status: "deleted"
addedChannelNames.push channel.name
channel.save (err) ->
if err
return done err
# Setup test data, will need authentication mechanisms to set ctx.authenticated
ctx = {}
ctx.authenticated =
clientID: "Musha_OpenMRS"
domain: "poc1.jembi.org"
name: "OpenMRS Musha instance"
roles: [ "OpenMRS_PoC", "PoC" ]
passwordHash: ""
cert: ""
ctx.request = {}
ctx.request.url = "test/status/deleted"
ctx.request.path = "test/status/deleted"
ctx.response = {}
ctx.set = ->
authorisation.authorise ctx, ->
(ctx.authorisedChannel == undefined).should.be.true
done()
describe '.matchReg(regexPat, body)', ->
it 'should return true if the regex pattern finds a match in the body', ->
(authorisation.matchRegex '123', new Buffer('aaa123aaa')).should.be.true
(authorisation.matchRegex 'functionId:\\s[a-z]{3}\\d{3}\\s', new Buffer('data: xyz\\nfunctionId: abc123\n')).should.be.true
it 'should return false if the regex pattern DOES NOT find a match in the body', ->
(authorisation.matchRegex '123', new Buffer('aaa124aaa')).should.be.false
(authorisation.matchRegex 'functionId:\\s[a-z]{3}\\d{3}\\s', new Buffer('data: xyz\\nfunctionId: somethingelse\n')).should.be.false
describe '.matchXpath(xpath, val, xml)', ->
it 'should return true if the xpath value matches', ->
(authorisation.matchXpath 'string(/root/function/@uuid)', 'da98db33-dd94-4e2a-ba6c-ac3f016dbdf1', new Buffer('<root><function uuid="da98db33-dd94-4e2a-ba6c-ac3f016dbdf1" /></root>')).should.be.true
it 'should return false if the xpath value DOES NOT match', ->
(authorisation.matchXpath 'string(/root/function/@uuid)', 'not-correct', new Buffer('<root><function uuid="da98db33-dd94-4e2a-ba6c-ac3f016dbdf1" /></root>')).should.be.false
describe '.matchJsonPath(xpath, val, xml)', ->
it 'should return true if the json path value matches', ->
(authorisation.matchJsonPath 'metadata.function.id', 'da98db33-dd94-4e2a-ba6c-ac3f016dbdf1', new Buffer('{"metadata": {"function": {"id": "da98db33-dd94-4e2a-ba6c-ac3f016dbdf1"}}}')).should.be.true
it 'should return false if the json path value DOES NOT match', ->
(authorisation.matchJsonPath 'metadata.function.id', 'not-correct', new Buffer('{"metadata": {"function": {"id": "da98db33-dd94-4e2a-ba6c-ac3f016dbdf1"}}}')).should.be.false
describe '.matchContent(channel, body)', ->
channelRegex =
matchContentRegex: /\d{6}/
channelXpath =
matchContentXpath: 'string(/function/uuid)'
matchContentValue: '123456789'
channelJson =
matchContentJson: 'function.uuid'
matchContentValue: '123456789'
noMatchChannel = {}
channelInvalid =
matchContentJson: 'function.uuid'
it 'should call the correct matcher', ->
authorisation.matchContent(channelRegex, new Buffer('--------123456------')).should.be.true
authorisation.matchContent(channelXpath, new Buffer('<function><uuid>123456789</uuid></function>')).should.be.true
authorisation.matchContent(channelJson, new Buffer('{"function": {"uuid": "123456789"}}')).should.be.true
authorisation.matchContent(channelRegex, new Buffer('--------1234aaa56------')).should.be.false
authorisation.matchContent(channelXpath, new Buffer('<function><uuid>1234aaa56789</uuid></function>')).should.be.false
authorisation.matchContent(channelJson, new Buffer('{"function": {"uuid": "1234aaa56789"}}')).should.be.false
it 'should return true if no matching properties are present', ->
authorisation.matchContent(noMatchChannel, new Buffer('someBody')).should.be.true
it 'should return false for invalid channel configs', ->
authorisation.matchContent(channelInvalid, new Buffer('someBody')).should.be.false
describe '.extractContentType', ->
it 'should extract a correct content-type', ->
authorisation.extractContentType('text/xml; charset=utf-8').should.be.exactly 'text/xml'
authorisation.extractContentType('text/xml').should.be.exactly 'text/xml'
authorisation.extractContentType(' text/xml ').should.be.exactly 'text/xml'
authorisation.extractContentType('text/xml;').should.be.exactly 'text/xml'