Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

305 rest api for form adapter integration #342

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 19 additions & 20 deletions backend/applications/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,31 +1,30 @@
# RedHat UBI 8 with nodejs 14
FROM registry.access.redhat.com/ubi8/ubi as builder
RUN dnf module install -y nodejs:14
FROM node:14.5.0-alpine
#FROM artifacts.developer.gov.bc.ca/docker-remote/node:14.17.1-alpine

# Install packages, build and keep only prod packages
WORKDIR /app
COPY . ./

# A wildcard is used to ensure both package.json AND package-lock.json are copied
COPY package*.json ./

# Set NODE_ENV environment variable
#ENV NODE_ENV production

# Install app dependencies using the `npm ci` command instead of `npm install`
RUN npm ci
RUN npm run build
# --only=prod
RUN npm ci --only=prod
#&& npm run build

# Deployment container
FROM node:lts-alpine
WORKDIR /app
# Set node to production
ENV NODE_ENV production
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/dist ./dist
# Bundle app source
COPY . ./

#ss-20-Error:permission denied, mkdir 'logs/'fix
# RUN mkdir -p /app/logs/
# RUN set -x \
# && chmod -Rv 777 /app/logs/
RUN npm run build

RUN set -x \
&& chmod -R 777 /app/

# Expose port - mostly a convention, for readability
EXPOSE 4006

# Start up command, with max heap size as 50Megs
ENTRYPOINT ["node", "--max-old-space-size=50","dist/main"]
# Start up command

ENTRYPOINT [ "sh", "start.sh" ]
36 changes: 36 additions & 0 deletions backend/applications/initDB.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#!/bin/sh

#Make sure you change line endings to LF

if [ ! "$POSTGRESQL_HOST" ];
then
echo 'Sourcing from .env'
. ./.env
else
echo 'Environment variables set...'
fi


# create database
psql "user=$POSTGRES_ADMIN_USERNAME password=$POSTGRES_ADMIN_PASSWORD host=$POSTGRESQL_HOST port=$POSTGRESQL_PORT" -c "CREATE DATABASE $POSTGRES_DATABASE OWNER $POSTGRES_ADMIN_USERNAME;"

# create extension
psql "user=$POSTGRES_ADMIN_USERNAME password=$POSTGRES_ADMIN_PASSWORD host=$POSTGRESQL_HOST port=$POSTGRESQL_PORT dbname=$POSTGRES_DATABASE" -c 'CREATE EXTENSION IF NOT EXISTS "uuid-ossp" WITH SCHEMA public;'


echo 'pwd'
echo $POSTGRES_DB_PASSWORD;

# create schema user
psql "user=$POSTGRES_ADMIN_USERNAME password=$POSTGRES_ADMIN_PASSWORD host=$POSTGRESQL_HOST port=$POSTGRESQL_PORT dbname=$POSTGRES_DATABASE" -c "CREATE ROLE $POSTGRES_DB_USERNAME WITH LOGIN NOSUPERUSER NOCREATEDB NOCREATEROLE NOINHERIT NOREPLICATION CONNECTION LIMIT -1 PASSWORD '$POSTGRES_DB_PASSWORD';"

# create schema
psql "user=$POSTGRES_ADMIN_USERNAME password=$POSTGRES_ADMIN_PASSWORD host=$POSTGRESQL_HOST port=$POSTGRESQL_PORT dbname=$POSTGRES_DATABASE" -c "CREATE SCHEMA IF NOT EXISTS $POSTGRES_DB_SCHEMA AUTHORIZATION $POSTGRES_DB_USERNAME"

echo "init db complete"

# run type orm migrations
npm run typeorm:run-migrations
echo "migrations completed"

exit 0
32 changes: 32 additions & 0 deletions backend/applications/local.Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# RedHat UBI 8 with nodejs 14
FROM node:14.5.0-alpine
#FROM artifacts.developer.gov.bc.ca/docker-remote/node:14.17.1-alpine

# Install packages, build and keep only prod packages
WORKDIR /app

# A wildcard is used to ensure both package.json AND package-lock.json are copied
COPY package*.json ./

# Set NODE_ENV environment variable
#ENV NODE_ENV production

# Install app dependencies using the `npm ci` command instead of `npm install`
RUN npm ci

# Bundle app source
COPY . ./

RUN npm run build

RUN set -x \
&& chmod -R 777 /app/

RUN apk add postgresql-client

# Expose port - mostly a convention, for readability
EXPOSE 4005

# Start up command

ENTRYPOINT [ "sh", "local_start.sh" ]
11 changes: 11 additions & 0 deletions backend/applications/local_start.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# create DB dependencies - database, schema
sh initDB.sh

# run type orm migrations
npm run typeorm:run-migrations

# Creates a "dist" folder with the production build
npm run build

# start the API
npm run start
30 changes: 9 additions & 21 deletions backend/applications/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 7 additions & 2 deletions backend/applications/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,19 @@
"test:watch": "jest --watch",
"test:cov": "jest --coverage",
"test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
"test:e2e": "jest --config ./test/jest-e2e.json"
"test:e2e": "jest --config ./test/jest-e2e.json",
"typeorm": "ts-node --transpile-only ./node_modules/typeorm/cli.js",
"typeorm:run-migrations": "npm run typeorm migration:run -- -d ./typeOrm.config.ts",
"typeorm:generate-migration": "npm run typeorm -- -d ./typeOrm.config.ts migration:generate ./src/migrations/master-script",
"typeorm:create-migration": "npm run typeorm -- migration:create ./src/migrations/master-script",
"typeorm:revert-migration": "npm run typeorm -- -d ./typeOrm.config.ts migration:revert"
},
"dependencies": {
"@apollo/federation": "^0.37.1",
"@apollo/subgraph": "^2.1.3",
"@nestjs/apollo": "^10.1.3",
"@nestjs/common": "^9.0.0",
"@nestjs/config": "^2.2.0",
"@nestjs/config": "^2.3.1",
"@nestjs/core": "^9.0.0",
"@nestjs/graphql": "^10.1.3",
"@nestjs/platform-express": "^9.0.0",
Expand Down
42 changes: 26 additions & 16 deletions backend/applications/src/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import {
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { ApplicationModule } from './app/application.module';
import { ExternalUser } from './app/entities/user.entity';

@Module({
imports: [
Expand All @@ -34,28 +33,39 @@ import { ExternalUser } from './app/entities/user.entity';
// Secret key of the client taken from keycloak server
}),
ApplicationModule,
TypeOrmModule.forRoot({
type: 'postgres',
host: process.env.POSTGRESQL_HOST || 'gldatabase',
port: parseInt(<string>process.env.POSTGRESQL_PORT) || 5432,
database: process.env.POSTGRESQL_DATABASE || 'admin',
username: process.env.POSTGRESQL_USER || 'admin',
password: process.env.POSTGRESQL_PASSWORD || 'admin',
// entities: [User],
autoLoadEntities:
process.env.POSTGRESQL_AUTOLOAD_ENTITIES == 'false' ? false : true, // Auto load all entities regiestered by typeorm forFeature method.
synchronize: false,
TypeOrmModule.forRootAsync({
inject: [ConfigService],
useFactory: (config: ConfigService) => ({
type: 'postgres',
host: config.get('POSTGRESQL_HOST') || 'gldatabase',
port: parseInt(config.get('POSTGRESQL_PORT')) || 5432,
database: config.get('POSTGRES_DATABASE') || 'xyz',
username: config.get('POSTGRES_DB_USERNAME') || 'xyzuser',
password: config.get('POSTGRES_DB_PASSWORD') || 'xyzuser',
autoLoadEntities: true, // Auto load all entities regiestered by typeorm forFeature method.
synchronize: false,
schema: config.get('POSTGRES_DB_SCHEMA'),
}),
// This changes the DB schema to match changes to entities, which we might not want.
logging: true,
}),
// TypeOrmModule.forRoot({
// type: 'postgres',
// host: process.env.POSTGRESQL_HOST || 'gldatabase',
// port: parseInt(<string>process.env.POSTGRESQL_PORT) || 5432,
// database: process.env.POSTGRESQL_DATABASE || 'admin',
// username: process.env.POSTGRESQL_USER || 'admin',
// password: process.env.POSTGRESQL_PASSWORD || 'admin',
// // entities: [User],
// autoLoadEntities: true, // Auto load all entities regiestered by typeorm forFeature method.
// synchronize: false, // Auto load all entities regiestered by typeorm forFeature method.
// // This changes the DB schema to match changes to entities, which we might not want.
// logging: true,
// }),
GraphQLModule.forRoot<ApolloFederationDriverConfig>({
driver: ApolloFederationDriver,
// autoSchemaFile: join(process.cwd(), 'src/graphql-schema.gql'),
// TODO - Experiment with using old files for localhsot if need be, and true for prod
autoSchemaFile: true,
buildSchemaOptions: {
orphanedTypes: [ExternalUser],
},
cors: true,
}),
],
Expand Down
13 changes: 8 additions & 5 deletions backend/applications/src/app/application.module.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
import { Module } from '@nestjs/common';
import { ApplicationService } from './application.service';
import { ApplicationResolver } from './application.resolver';
import { ApplicationService } from './services/application.service';
import { ApplicationResolver } from './resolvers/application.resolver';
import { TypeOrmModule } from '@nestjs/typeorm';
import { Application } from './entities/application.entity';
import { UsersResolver } from './users.resolver';
import { FormController } from './controllers/form.controller';
import { FormService } from './services/form.service';
import { Form } from './entities/form.entity';

@Module({
imports: [TypeOrmModule.forFeature([Application])],
providers: [ApplicationResolver, ApplicationService, UsersResolver],
imports: [TypeOrmModule.forFeature([Application, Form])],
providers: [ApplicationResolver, ApplicationService, FormService],
controllers: [FormController],
})
export class ApplicationModule {}
93 changes: 93 additions & 0 deletions backend/applications/src/app/controllers/form.controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import { Body, Controller, Get, Param, Patch, Post, Put } from '@nestjs/common';
import { Resource, Unprotected } from 'nest-keycloak-connect';
import { SubmissionResponse } from '../dto/submissionResponse.dto';
import { Form } from '../entities/form.entity';
import { FormService } from '../services/form.service';

@Controller('form')
@Resource('application-service')
export class FormController {
constructor(private formService: FormService) {}

/**
* Get a submitted form using
* @param formId formId
* @param submissionId submissionId
* @returns saved form submission
*/
@Get(':formId/submission/:submissionId') async getSubmission(
@Param('formId') formId,
@Param('submissionId') submissionId,
): Promise<SubmissionResponse> {
const savedSubmission = await this.formService.findOne(
submissionId,
formId,
);
const submissionResponse: SubmissionResponse =
this.transformResult(savedSubmission);
return submissionResponse;
}

/**
* Creates a new form submission
* @param formId formId
* @param content formContent in JSON format
* @returns saved form submission
*/
@Post(':formId/submission') async save(
@Param('formId') formId,
@Body() content,
): Promise<SubmissionResponse> {
console.log(content);
console.log('formId 2' + formId);
const savedSubmission = await this.formService.create(formId, content.data);
const submissionResponse: SubmissionResponse =
this.transformResult(savedSubmission);
return submissionResponse;
}

/**
* Transforming the form entity into formsflow expected response
* @param savedSubmission saved form
* @returns saved form in formflow expected format
*/
transformResult(savedSubmission: Form) {
const submissionResponse: SubmissionResponse = new SubmissionResponse();
submissionResponse._id = savedSubmission.id;
submissionResponse.form = savedSubmission.formId;
submissionResponse.data = savedSubmission.formData;
submissionResponse.created = savedSubmission.createdDate;
submissionResponse.modified = savedSubmission.modifiedDate;
return submissionResponse;
}

/**
* Updates the form submission
* @param formId formId
* @param submissionId submissionId
* @param content content
* @returns update result
*/
@Put(':formId/submission/:submissionId') async updateSubmission(
@Param('formId') formId,
@Param('submissionId') submissionId,
@Body() content,
): Promise<any> {
return await this.formService.update(submissionId, formId, content);
}

/**
* Partially updates the form submission
* @param formId formId
* @param submissionId submissionId
* @param content content
* @returns update result
*/
@Patch(':formId/submission/:submissionId') async partialUpdateSubmission(
@Param('formId') formId,
@Param('submissionId') submissionId,
@Body() content,
) {
return await this.formService.update(submissionId, formId, content);
}
}
10 changes: 10 additions & 0 deletions backend/applications/src/app/dto/submissionResponse.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/**
* Formsflow Response DTO
*/
export class SubmissionResponse {
created: Date;
_id: string;
form: string;
data: string;
modified: Date;
}
Loading