Skip to content

Commit

Permalink
BHBC-914: Save drafts (#211)
Browse files Browse the repository at this point in the history
* BHBC-914: Save drafts

* Reduce duplication

* Code review updates

* Fix merge issue

Co-authored-by: Shreyas Devalapurkar <[email protected]>
  • Loading branch information
NickPhura and sdevalapurkar authored Apr 9, 2021
1 parent 0be01d5 commit 7e3f5b3
Show file tree
Hide file tree
Showing 26 changed files with 6,893 additions and 169 deletions.
88 changes: 75 additions & 13 deletions api/src/database/db.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,52 @@ try {
}

export interface IDBConnection {
/**
* Opens a new connection, begins a transaction, and sets the user context.
*
* Note: Does nothing if the connection is already open.
* @memberof IDBConnection
*/
open: () => Promise<void>;
/**
* Releases (closes) the connection.
*
* Note: Does nothing if the connection is already released.
* @memberof IDBConnection
*/
release: () => void;
/**
* Commits the transaction that was opened by calling `.open()`.
*
* Note: Does nothing if the connection is not open, or was released.
* @memberof IDBConnection
*/
commit: () => Promise<void>;
/**
* Rollsback the transaction, undoing any queries performed by this connection.
*
* Note: Does nothing if the connection is not open, or was released.
* @memberof IDBConnection
*/
rollback: () => Promise<void>;
/**
* Performs a query against this connection, returning the results.
*
* Note: Does nothing if the connection is not open, or was released.
*
* @param {string} text SQL text
* @param {any[]} [values] SQL values array (optional)
* @return {*} {(Promise<QueryResult<any> | void>)}
* @memberof IDBConnection
*/
query: (text: string, values?: any[]) => Promise<QueryResult<any> | void>;
/**
* Get the ID of the system user in context.
*
* Note: will always return `null` if the connection is not open.
* @memberof IDBConnection
*/
systemUserId: () => number | null;
}

/**
Expand All @@ -64,21 +105,24 @@ export interface IDBConnection {
* connection.release();
* }
*
* @returns {IDBConnection}
* @param {object} keycloakToken
* @return {*} {IDBConnection}
*/
export const getDBConnection = function (keycloakToken: string): IDBConnection {
export const getDBConnection = function (keycloakToken: object): IDBConnection {
let _client: PoolClient;

let _isOpen = false;

let _systemUserId: number | null = null;

const _token = keycloakToken;

/**
* Opens a new connection, begins a transaction, and sets the user context.
*
* Note: Does nothing if the connection is already open.
*/
const open = async () => {
const _open = async () => {
if (_client || _isOpen) {
return;
}
Expand All @@ -97,7 +141,7 @@ export const getDBConnection = function (keycloakToken: string): IDBConnection {
*
* Note: Does nothing if the connection is already released.
*/
const release = () => {
const _release = () => {
if (!_client || !_isOpen) {
return;
}
Expand All @@ -112,7 +156,7 @@ export const getDBConnection = function (keycloakToken: string): IDBConnection {
*
* Note: Does nothing if the connection is not open, or was released.
*/
const commit = async () => {
const _commit = async () => {
if (!_client || !_isOpen) {
return;
}
Expand All @@ -125,7 +169,7 @@ export const getDBConnection = function (keycloakToken: string): IDBConnection {
*
* Note: Does nothing if the connection is not open, or was released.
*/
const rollback = async () => {
const _rollback = async () => {
if (!_client || !_isOpen) {
return;
}
Expand All @@ -134,29 +178,35 @@ export const getDBConnection = function (keycloakToken: string): IDBConnection {
};

/**
* Performs a query agaisnt this connection, returning the results.
* Performs a query against this connection, returning the results.
*
* Note: Does nothing if the connection is not open, or was released.
*
* @param {string} text SQL text
* @param {any[]} [values] SQL values array (optional)
* @return {*} {(Promise<QueryResult<any> | void>)}
*/
const query = async (text: string, values?: any[]): Promise<QueryResult<any> | void> => {
const _query = async (text: string, values?: any[]): Promise<QueryResult<any> | void> => {
if (!_client || !_isOpen) {
return;
}

return _client.query(text, values || []);
};

const _getSystemUserID = () => {
return _systemUserId;
};

/**
* Internal function to set the user context.
* Set the user context.
*
* Sets the _systemUserId if successful.
*/
const _setUserContext = async () => {
// Strip the `@<alias>` from the end of the username, which is added in keycloak to IDIR and BCeID usernames
const idir = _token['preferred_username']?.split('@')[0];
const bceid = _token['preferred_username']?.split('@')[0];
const idir = _token?.['preferred_username']?.split('@')[0];
const bceid = _token?.['preferred_username']?.split('@')[0];

if (!idir && !bceid) {
throw new HTTP400('Failed to identify user ID');
Expand All @@ -173,11 +223,23 @@ export const getDBConnection = function (keycloakToken: string): IDBConnection {
}

try {
await _client.query(setSystemUserContextSQLStatement.text, setSystemUserContextSQLStatement.values);
const response = await _client.query(
setSystemUserContextSQLStatement.text,
setSystemUserContextSQLStatement.values
);

_systemUserId = response?.rows?.[0].api_set_context;
} catch (error) {
throw new HTTP500('Failed to set user context', [error]);
}
};

return { open: open, query: query, release: release, commit: commit, rollback: rollback };
return {
open: _open,
query: _query,
release: _release,
commit: _commit,
rollback: _rollback,
systemUserId: _getSystemUserID
};
};
2 changes: 1 addition & 1 deletion api/src/models/project-create.ts
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ export class PostFundingData {
defaultLog.debug({ label: 'PostFundingData', message: 'params', obj });

this.funding_sources =
(obj?.funding_sources.length && obj.funding_sources.map((item: any) => new PostFundingSource(item))) || [];
(obj?.funding_sources?.length && obj.funding_sources.map((item: any) => new PostFundingSource(item))) || [];
}
}

Expand Down
12 changes: 12 additions & 0 deletions api/src/openapi/schemas/draft.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import Ajv from 'ajv';
import { expect } from 'chai';
import { describe } from 'mocha';
import { draftResponseObject } from './draft';

describe('draftResponseObject', () => {
const ajv = new Ajv();

it('is valid openapi v3 schema', () => {
expect(ajv.validateSchema(draftResponseObject)).to.be.true;
});
});
17 changes: 17 additions & 0 deletions api/src/openapi/schemas/draft.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/**
* Response object for creating/updating a draft
*/
export const draftResponseObject = {
title: 'Draft Response Object',
type: 'object',
required: ['id', 'date'],
properties: {
id: {
type: 'number'
},
date: {
type: 'string',
description: 'The date this draft was last updated or created'
}
}
};
Loading

0 comments on commit 7e3f5b3

Please sign in to comment.