To learn more about the Common Services available visit the Common Services Showcase page.
GETOK is a web-based tool for development teams to manage their application's secure access to Common Services. Users can create and deploy Keycloak service clients instantly to gain access to common service APIs like email notifications, document management, or document generation.
This application is a node server which serves two roles. Anything under the HTTP /app
path (or whatever is configured) will contain resources needed for the frontend to render on the browser, while anything under HTTP /api
responds to keycloak authenticated requests. It uses the following dependencies from NPM:
Authentication & Password Management
cryptico-js
- Asymmetric key encryptiongenerate-password
- Password generatorjsonwebtoken
- JWT parsing librarykeycloak-connect
- Keycloak authentication middleware
Database Management
pg
- Postgres librarysequelize
- Promise-based ORMsequelize-cli
- DB Migration manager
Networking
api-problem
- RFC 7807 response handleraxios
- Standard network callerexpress
- Server middlewareexpress-validator
- Call validationjs-yaml
- YAML parser and serializer
Logging
morgan
- HTTP request loggernpmlog
- General log framework
The codebase is separated into a few discrete layers:
components
- Business logic layer - the majority of useful functionality resides heredocs
- Contains OpenAPI 3.0 Yaml specification and ReDoc renderermigrations
- Database migration scriptsmodels
- Database ORM modelsroutes
- Express middleware routingservices
- Database Access Object layer
In order for the application to run correctly, you will need to ensure that the following have been addressed:
- All node dependencies have been installed and resolved
- Environment configurations have been set up
- A Postgres database instance that is reachable
- The database has been initialized with the correct migrations
- (Optional) The database has been seeded with dev data
As this is a Node application, please ensure that you have all dependencies installed as needed. This can be done by running npm install
.
Configuration management is done using the config library. There are two ways to configure:
- Look at custom-environment-variables.json and ensure you have the environment variables locally set.
- Create a
local.json
file in the config folder. This file should never be added to source control. - Consider creating a
local-test.json
file in the config folder if you want to use different configurations while running unit tests.
For more details, please consult the config library documentation.
Environment Variable | Description |
---|---|
DB_DATABASE |
Name of the database |
DB_HOST |
Location the database is hosted at |
DB_USERNAME |
Database username |
DB_PASSWORD |
Database password |
FRONTEND_APIPATH |
Relative API path |
FRONTEND_BASEPATH |
Base subpath for all access |
FRONTEND_KC_CLIENTID |
Keycloak Client Name |
FRONTEND_KC_REALM |
Keycloak Client Realm |
FRONTEND_KC_SERVERURL |
Keycloak Authentication URL |
SERVER_APIPATH |
Relative API path |
SERVER_BASEPATH |
Base subpath for all access |
SERVER_BODYLIMIT |
Maximum acceptable request body length |
SERVER_KC_CLIENTID |
Keycloak Client Name |
SERVER_KC_CLIENTSECRET |
Keycloak Client Secret |
SERVER_KC_REALM |
Keycloak Client Realm |
SERVER_KC_SERVERURL |
Keycloak Authentication URL |
SERVER_LOGLEVEL |
Server log verbosity. Options: silly , verbose , debug , info , warn , error |
SERVER_MORGANFORMAT |
Morgan format style. Options: dev , combined |
SERVER_PORT |
Port server is listening to |
The following variables are not re-implemented yet
| Environment Variable | Description |
| CHES_TOKEN_ENDPOINT
| Keycloak token endpoint (YAMS Realm) for common service token fetching |
| CHES_EMAIL_ENDPOINT
| CHES endpoint for sending email |
| CHES_HEALTH_ENDPOINT
| CHES health check endpoint |
| CHES_SC_USERNAME
| YAMS service client username |
| CHES_SC_PASSWORD
| YAMS service client password |
The backend requires a valid Postgres database to connect to in order to function. Please ensure you have either installed a Postgres server on your local development machine OR have an equivalent Postgres database available to connect to BEFORE attempting to start up the application.
You will need to ensure that your Postgres database has an empty database initialized that the backend can utilize. We suggest naming the database getok
to minimize naming impact on other potentially existing databases. There are many ways of ensuring that a viable user can access the postgres server depending on which type of operating system being used. Below is an example of what needs to be executed in SQL to achieve the equivalent of making a new user and database.
CREATE USER username WITH ENCRYPTED PASSWORD 'password';
CREATE DATABASE getok;
GRANT ALL PRIVILEGES ON DATABASE getok TO username;
Assuming you have a database ready to go, you will still require the database schema to be populated. This can be achieved by executing the following in the root backend directory:
npm run migrate
If you need the database pre-populated with some data, you can run the following:
npm run seed:dev
If you have to remove the seed data, or need to reapply it, you will want to undo the seed with:
npm run seed:dev:undo
Once the migration and optional seeding steps are done, you should be able to start up the backend application.
After addressing the prerequisites, the following are common commands that are used for this application. In the event you want to do the same action for both this app and the frontend, you can prepend an all:
to the command (where it makes sense).
npm run build
npm run serve
npm run start
npm run migrate
npm run test
npm run lint
npm run lint-fix
In order to handle changes to our code-first database, we need to periodically write in Sequelize compatible database migration scripts. You will likely require the QueryInterface
API of Sequelize in order to achieve a proper up and down migration which can be found on Sequelize documentation. You may also look at previously implemented migrations as a design guide.
When creating a new migration, it is suggested to run the following to generate a new migration script scaffold to work with:
npx sequelize-cli migration:generate --name yourmigrationname
This tool will generate a new file with a verbose timestamp and the specified name appended (i.e. 20190812183401-yourmigrationname.js
). Please preserve this naming convention as that Sequelize appears to determine migration order alphanumerically.
The following is a simple migration script example which renames an existing column. Note that the transformation is specified on both the forwards up direction as well as the reverse down direction.
20190812183401-yourmigrationname.js
module.exports = {
up: queryInterface => {
return queryInterface.renameColumn('lifecycle_history', 'previousEnv', 'env');
},
down: queryInterface => {
return queryInterface.renameColumn('lifecycle_history', 'env', 'previousEnv');
}
};
When creating a migration, you MUST ensure that the migrations can work on a properly functioning database before even considering making a PR as that any migration that doesn't work correctly can risk damaging the production database contents.
Once you have a migration written, you may apply the migration by running
npm run migrate
while the backend is not running. In the event a migration must be undone, you can revert to the last migration by running
npx sequelize-cli db:migrate:undo
Should the database need to be nuked and rebuilt from scratch, you can do so by undoing all migrations and reapplying them as follows:
npx sequelize-cli db:migrate:undo:all
npm run migrate
For more details on how to leverage Sequelize CLI, refer to the Sequelize Documentation.