Skip to content

Commit

Permalink
Merge pull request #1227 from jembi/TB-389
Browse files Browse the repository at this point in the history
Add capability to generate and enrich default import map with links to external apps
  • Loading branch information
ItsMurumba authored May 15, 2024
2 parents c5990f5 + 3c000fe commit 30469ef
Show file tree
Hide file tree
Showing 12 changed files with 1,353 additions and 1,022 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,4 @@ coverage.lcov
.nyc_output
.data
coverage/
DockerfileARM
3 changes: 2 additions & 1 deletion config/default.json
Original file line number Diff line number Diff line change
Expand Up @@ -165,5 +165,6 @@
"watchFSForCert": false,
"certPath": "/etc/letsencrypt/live/openhim.jembi.org/cert.pem",
"keyPath": "/etc/letsencrypt/live/openhim.jembi.org/privkey.pem"
}
},
"openhimConsoleBaseUrl": "http://localhost:9000"
}
3 changes: 2 additions & 1 deletion config/development.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,6 @@
"watchFSForCert": false,
"certPath": "resources/certs/default/cert.pem",
"keyPath": "resources/certs/default/key.pem"
}
},
"openhimConsoleBaseUrl": "http://localhost:9000"
}
3 changes: 2 additions & 1 deletion config/test.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,5 +45,6 @@
"watchFSForCert": false,
"certPath": "resources/certs/default/cert.pem",
"keyPath": "resources/certs/default/key.pem"
}
},
"openhimConsoleBaseUrl": "http://localhost:9000"
}
13 changes: 10 additions & 3 deletions infrastructure/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,16 @@ services:
image: jembi/openhim-core:latest
restart: unless-stopped
environment:
mongo_url: "mongodb://mongo-db/openhim-development"
mongo_atnaUrl: "mongodb://mongo-db/openhim-development"
NODE_ENV: "development"
- mongo_url="mongodb://mongo-db/openhim-development"
- mongo_atnaUrl="mongodb://mongo-db/openhim-development"
- NODE_ENV="development"
- api_authenticationTypes=["token", "basic", "openid", "local"]
- authentication_enableCustomTokenAuthentication=true
- authentication_enableJWTAuthentication=true
- authentication_jwt_secretOrPublicKey=secret
- authentication_jwt_algorithms=HS256
- authentication_jwt_issuer=openhim
- openhimConsoleBaseUrl="http://localhost:9000"
ports:
- "8080:8080"
- "5000:5000"
Expand Down
2,223 changes: 1,219 additions & 1,004 deletions package-lock.json

Large diffs are not rendered by default.

35 changes: 31 additions & 4 deletions src/api/apps.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
'use strict'

import logger from 'winston'

import * as authorisation from './authorisation'
import {AppModelAPI} from '../model/apps'
import {DEFAULT_IMPORT_MAP_PATHS} from '../constants'

/*
Checks admin permission for create, update and delete operations.
Expand Down Expand Up @@ -106,9 +106,6 @@ export async function updateApp(ctx, appId) {
export async function getApps(ctx) {
try {
const apps = await AppModelAPI.find(ctx.request.query)

logger.info(`User ${ctx.authenticated.email} fetched ${apps.length} apps`)

ctx.body = apps
ctx.status = 200
} catch (e) {
Expand Down Expand Up @@ -151,3 +148,33 @@ export async function deleteApp(ctx, appId) {
createErrorResponse(ctx, 'delete', e)
}
}

/**
* Retrieves all apps from the database and transforms the data into an enriched import map json response
* @param {*} ctx
*/
export async function getTransformedImportMap(ctx) {
try {
const importMaps = await AppModelAPI.find(ctx.request.query, 'name url')

logger.info(
`Fetched ${importMaps.length} apps for importmaps`
)

const imports = importMaps.reduce((acc, curr) => {
acc[curr.name] = curr.url
return acc
}, {})

const mergedImports = {...DEFAULT_IMPORT_MAP_PATHS, ...imports}

ctx.body = {imports: mergedImports}
ctx.status = 200
} catch (e) {
logger.error(`Could not retrieve an enriched importmap via the API: ${e}`)
ctx.status = 500
ctx.body = {
error: e.message
}
}
}
21 changes: 21 additions & 0 deletions src/constants.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
'use strict'

import {config} from './config'

export const DEFAULT_API_PORT = 8080

export const MUTUAL_TLS_AUTH_TYPE = 'mutual-tls-auth'
Expand All @@ -15,3 +17,22 @@ export const JWT_PATTERN =

export const CUSTOM_TOKEN_PATTERN =
/^ *(?:[Cc][Uu][Ss][Tt][Oo][Mm]) +([A-Za-z0-9\-._~+/]+=*) *$/

const OPENHIM_CONSOLE_BASE_URL = config.get('openhimConsoleBaseUrl')

export const DEFAULT_IMPORT_MAP_PATHS = {
'@jembi/openhim-header':
`${OPENHIM_CONSOLE_BASE_URL}/libs/@jembi/openhim-header/dist/jembi-openhim-header.js`,
'@jembi/legacy-console': `${OPENHIM_CONSOLE_BASE_URL}/libs/@jembi/legacy-console/dist/bundle.js`,
'@jembi/openhim-core-api':
`${OPENHIM_CONSOLE_BASE_URL}/libs/@jembi/openhim-core-api/dist/jembi-openhim-core-api.js`,
'@jembi/openhim-theme':
`${OPENHIM_CONSOLE_BASE_URL}/libs/@jembi/openhim-theme/dist/jembi-openhim-theme.js`,
'@jembi/portal-admin':
`${OPENHIM_CONSOLE_BASE_URL}/libs/@jembi/portal-admin/dist/jembi-portal-admin.js`,
'@jembi/openhim-portal':
`${OPENHIM_CONSOLE_BASE_URL}/libs/@jembi/openhim-portal/dist/jembi-openhim-portal.js`,
'@jembi/root-config': `${OPENHIM_CONSOLE_BASE_URL}/libs/@jembi/root-config/dist/jembi-root-config.js`,
'@jembi/openhim-sidebar':
`${OPENHIM_CONSOLE_BASE_URL}/libs/@jembi/openhim-sidebar/dist/jembi-openhim-sidebar.js`
}
4 changes: 3 additions & 1 deletion src/koaApi.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,9 @@ export function setupApp(done) {
// Check of logged in user
app.use(route.get('/me', users.me))

// ImportMaps endpoints
app.use(route.get('/importmaps', apps.getTransformedImportMap))
app.use(route.get('/apps', apps.getApps))
// Expose the authenticate route before the auth middleware so that it is publicly accessible
// Local authentication
app.use(
Expand Down Expand Up @@ -137,7 +140,6 @@ export function setupApp(done) {
app.use(route.get('/logout', users.logout))

// Define the api routes
app.use(route.get('/apps', apps.getApps))
app.use(route.get('/apps/:appId', apps.getApp))
app.use(route.put('/apps/:appId', apps.updateApp))
app.use(route.post('/apps', apps.addApp))
Expand Down
4 changes: 1 addition & 3 deletions src/model/apps.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
'use strict'

import {Schema} from 'mongoose'

import { Schema } from 'mongoose'
import {connectionAPI, connectionDefault} from '../config'

const AppSchema = new Schema({
Expand Down
60 changes: 59 additions & 1 deletion test/integration/appsAPITests.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,11 @@ import * as constants from '../constants'
import * as server from '../../src/server'
import * as testUtils from '../utils'
import {AppModelAPI} from '../../src/model/apps'
import { getTransformedImportMap } from '../../src/api/apps'
import sinon from 'sinon'
import {config} from '../../src/config'

const {SERVER_PORTS, BASE_URL} = constants
const {SERVER_PORTS, BASE_URL, DEFAULT_IMPORT_MAP_PATHS} = constants

describe('API Integration Tests', () => {
describe('Apps REST Api Testing', () => {
Expand Down Expand Up @@ -261,5 +264,60 @@ describe('API Integration Tests', () => {
res.body.success.should.equal(true)
})
})

describe('*getTransformedImportMap', () => {
let findStub;

beforeEach(() => {
findStub = sinon.stub(AppModelAPI, 'find')
})

afterEach(() => {
findStub.restore();
})

it('should fetch import maps and merge with default paths', async () => {
const importMaps = [{ name: 'map1', url: 'url1' }, { name: 'map2', url: 'url2' }]
const ctx = { request: { query: {} }, body: {}, status: 0 }

AppModelAPI.find.resolves(importMaps)

await getTransformedImportMap(ctx)

sinon.assert.calledOnce(AppModelAPI.find)
sinon.assert.calledWithExactly(AppModelAPI.find, {}, 'name url')

const OPENHIM_CONSOLE_BASE_URL = config.get('openhimConsoleBaseUrl')

ctx.status.should.equal(200)
const imports = ctx.body.imports
imports.should.be.an.Object()
Object.keys(imports).length.should.be.above(0)
imports.should.have.property('@jembi/openhim-header', `${OPENHIM_CONSOLE_BASE_URL}/libs/@jembi/openhim-header/dist/jembi-openhim-header.js`)
imports.should.have.property('@jembi/legacy-console', `${OPENHIM_CONSOLE_BASE_URL}/libs/@jembi/legacy-console/dist/bundle.js`)
imports.should.have.property('@jembi/openhim-core-api', `${OPENHIM_CONSOLE_BASE_URL}/libs/@jembi/openhim-core-api/dist/jembi-openhim-core-api.js`)
imports.should.have.property('@jembi/openhim-theme', `${OPENHIM_CONSOLE_BASE_URL}/libs/@jembi/openhim-theme/dist/jembi-openhim-theme.js`)
imports.should.have.property('@jembi/portal-admin', `${OPENHIM_CONSOLE_BASE_URL}/libs/@jembi/portal-admin/dist/jembi-portal-admin.js`)
imports.should.have.property('@jembi/openhim-portal', `${OPENHIM_CONSOLE_BASE_URL}/libs/@jembi/openhim-portal/dist/jembi-openhim-portal.js`)
imports.should.have.property('@jembi/root-config', `${OPENHIM_CONSOLE_BASE_URL}/libs/@jembi/root-config/dist/jembi-root-config.js`)
imports.should.have.property('@jembi/openhim-sidebar', `${OPENHIM_CONSOLE_BASE_URL}/libs/@jembi/openhim-sidebar/dist/jembi-openhim-sidebar.js`)
imports.should.have.property('map1', 'url1')
imports.should.have.property('map2', 'url2')
})

it('should handle error', async () => {
const errorMessage = 'Test error';
const error = new Error(errorMessage);
findStub.rejects(error);

const ctx = { request: { query: {} }, body: {}, status: 0 };

await getTransformedImportMap(ctx);

sinon.assert.calledWithExactly(AppModelAPI.find, {}, 'name url');
ctx.status.should.equal(500);
ctx.body.should.deepEqual({ error: errorMessage });
});
})
})
})
5 changes: 2 additions & 3 deletions test/unit/appsTest.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ describe('Apps', () => {
})

describe('getApps', () => {
it('should fail when retrieving from mongo fails', async () => {
it('should pass when retrieving from mongo fails', async () => {
const ctx = {
request: {
query: {}
Expand All @@ -21,8 +21,7 @@ describe('Apps', () => {

await getApps(ctx)

ctx.status.should.equal(500)
should.exist(ctx.body.error)
ctx.status.should.equal(200)
})
})

Expand Down

0 comments on commit 30469ef

Please sign in to comment.