chore: added docker files for bringing the container up

This commit is contained in:
ankitsridhar16
2022-12-06 13:18:02 +05:30
parent 1dc804a2b9
commit 333dbba393
10 changed files with 980 additions and 19 deletions

View File

@@ -0,0 +1 @@
./node_modules

View File

@@ -0,0 +1,30 @@
FROM node:lts
WORKDIR /usr/src/app
# Install pnpm
RUN npm i -g pnpm
# NPM package install
COPY package*.json ./
RUN pnpm install
# Prisma bits
#COPY prisma ./
#RUN pnpx prisma generate
COPY . .
RUN pnpm run build
EXPOSE 3170
EXPOSE 9229
ENV APP_PORT=${PORT}
ENV DB_URL=${DATABASE_URL}
ENV PRODUCTION=true
#ENV FB_SERVICE_KEY_PATH="secrets/fb-service-key.json"
CMD ["pnpm", "run", "start:dev"]
#CMD ["./run.sh", "start:dev"]

View File

@@ -0,0 +1,25 @@
version: '3.0'
services:
local:
build: ./Dockerfile
environment:
- PRODUCTION=false
- DATABASE_URL=postgresql://postgres:testpass@dev-db:5432/hoppscotch
- PORT=3000
# volumes:
# - .:/usr/src/app
depends_on:
- dev-db
ports:
- "3170:3000"
- "9229:9229"
dev-db:
image: postgres
ports:
- "5432:5432"
environment:
POSTGRES_PASSWORD: testpass
POSTGRES_DB: hoppscotch

View File

@@ -21,9 +21,13 @@
"test:e2e": "jest --config ./test/jest-e2e.json"
},
"dependencies": {
"@nestjs/apollo": "^10.1.6",
"@nestjs/common": "^9.2.1",
"@nestjs/core": "^9.2.1",
"@nestjs/graphql": "^10.1.6",
"@nestjs/platform-express": "^9.2.1",
"apollo-server-express": "^3.11.1",
"graphql": "^15.5.0",
"reflect-metadata": "^0.1.13",
"rimraf": "^3.0.2",
"rxjs": "^7.6.0"

View File

@@ -0,0 +1,85 @@
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
generator client {
provider = "prisma-client-js"
binaryTargets = ["native", "debian-openssl-1.1.x"]
}
model Team {
id String @id @default(cuid())
name String
members TeamMember[]
TeamInvitation TeamInvitation[]
TeamCollection TeamCollection[]
TeamRequest TeamRequest[]
TeamEnvironment TeamEnvironment[]
}
model TeamMember {
id String @id @default(uuid()) // Membership ID
role TeamMemberRole
userUid String
teamID String
team Team @relation(fields: [teamID], references: [id], onDelete: Cascade)
@@unique([teamID, userUid])
}
model TeamInvitation {
id String @id @default(cuid())
teamID String
team Team @relation(fields: [teamID], references: [id], onDelete: Cascade)
creatorUid String
inviteeEmail String
inviteeRole TeamMemberRole
@@unique([teamID, inviteeEmail])
@@index([teamID])
}
model TeamCollection {
id String @id @default(cuid())
parentID String?
parent TeamCollection? @relation("TeamCollectionChildParent", fields: [parentID], references: [id])
children TeamCollection[] @relation("TeamCollectionChildParent")
requests TeamRequest[]
teamID String
team Team @relation(fields: [teamID], references: [id], onDelete: Cascade)
title String
}
model TeamRequest {
id String @id @default(cuid())
collectionID String
collection TeamCollection @relation(fields: [collectionID], references: [id], onDelete: Cascade)
teamID String
team Team @relation(fields: [teamID], references: [id], onDelete: Cascade)
title String
request Json
}
model Shortcode {
id String @id
request Json
creatorUid String?
createdOn DateTime @default(now())
@@unique(fields: [id, creatorUid], name: "creator_uid_shortcode_unique")
}
model TeamEnvironment {
id String @id @default(cuid())
teamID String
team Team @relation(fields: [teamID], references: [id], onDelete: Cascade)
name String
variables Json
}
enum TeamMemberRole {
OWNER
VIEWER
EDITOR
}

View File

@@ -1,10 +1,51 @@
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { GraphQLModule } from '@nestjs/graphql';
import { ApolloDriver, ApolloDriverConfig } from '@nestjs/apollo';
import { AppResolver } from './app.resolver';
@Module({
imports: [],
imports: [
GraphQLModule.forRoot<ApolloDriverConfig>({
playground: process.env.PRODUCTION !== 'true',
debug: process.env.PRODUCTION !== 'true',
autoSchemaFile: true,
installSubscriptionHandlers: true,
subscriptions: {
'subscriptions-transport-ws': {
path: '/graphql',
onConnect: (connectionParams: any) => {
return {
reqHeaders: Object.fromEntries(
Object.entries(connectionParams).map(([k, v]) => [
k.toLowerCase(),
v,
]),
),
};
},
},
},
context: async ({ req, connection }) => {
if (req) {
return { reqHeaders: req.headers };
} else {
return {
// Lowercase the keys
reqHeaders: Object.fromEntries(
Object.entries(connection.context).map(([k, v]) => [
k.toLowerCase(),
v,
]),
),
};
}
},
driver: ApolloDriver,
}),
],
controllers: [AppController],
providers: [AppService],
providers: [AppService, AppResolver],
})
export class AppModule {}

View File

@@ -0,0 +1,12 @@
import { Query, Resolver } from '@nestjs/graphql';
import { AppService } from './app.service';
@Resolver((of) => String)
export class AppResolver {
constructor(private appService: AppService) {}
@Query((returns) => String)
async author() {
return this.appService.getHello();
}
}

View File

@@ -0,0 +1,211 @@
export const INVALID_EMAIL = 'invalid/email' as const;
export const EMAIL_FAILED = 'email/failed' as const;
/**
* Token Authorization failed (Check 'Authorization' Header)
* (GqlAuthGuard)
*/
export const AUTH_FAIL = 'auth/fail';
/**
* Tried to delete an user data document from fb firestore but failed.
* (FirebaseService)
*/
export const USER_FB_DOCUMENT_DELETION_FAILED =
'fb/firebase_document_deletion_failed' as const;
/**
* Tried to do an action on a user where user is not found
*/
export const USER_NOT_FOUND = 'user/not_found' as const;
/**
* User deletion failure
* (UserService)
*/
export const USER_DELETION_FAILED = 'user/deletion_failed' as const;
/**
* User deletion failure error due to user being a team owner
* (UserService)
*/
export const USER_IS_OWNER = 'user/is_owner' as const;
/**
* Tried to perform action on a team which they are not a member of
* (GqlTeamMemberGuard)
*/
export const TEAM_MEMBER_NOT_FOUND = 'team/member_not_found' as const;
/**
* Tried to perform action on a team that doesn't accept their member role level
* (GqlTeamMemberGuard)
*/
export const TEAM_NOT_REQUIRED_ROLE = 'team/not_required_role' as const;
/**
* Team name validation failure
* (TeamService)
*/
export const TEAM_NAME_INVALID = 'team/name_invalid';
/**
* Couldn't find the sync data from the user
* (TeamCollectionService)
*/
export const TEAM_USER_NO_FB_SYNCDATA = 'team/user_no_fb_syncdata';
/**
* There was a problem resolving the firebase collection path
* (TeamCollectionService)
*/
export const TEAM_FB_COLL_PATH_RESOLVE_FAIL = 'team/fb_coll_path_resolve_fail';
/**
* Tried to update the team to a state it doesn't have any owners
* (TeamService)
*/
export const TEAM_ONLY_ONE_OWNER = 'team/only_one_owner';
/**
* Invalid or non-existent Team ID
* (TeamService)
*/
export const TEAM_INVALID_ID = 'team/invalid_id' as const;
/**
* Invalid or non-existent collection id
* (GqlCollectionTeamMemberGuard)
*/
export const TEAM_INVALID_COLL_ID = 'team/invalid_coll_id' as const;
/**
* Invalid team id or user id
* (TeamService)
*/
export const TEAM_INVALID_ID_OR_USER = 'team/invalid_id_or_user';
/**
* The provided title for the team collection is short (less than 3 characters)
* (TeamCollectionService)
*/
export const TEAM_COLL_SHORT_TITLE = 'team_coll/short_title';
/**
* The JSON used is not valid
* (TeamCollectionService)
*/
export const TEAM_COLL_INVALID_JSON = 'team_coll/invalid_json';
/**
* Tried to perform action on a request that doesn't accept their member role level
* (GqlRequestTeamMemberGuard)
*/
export const TEAM_REQ_NOT_REQUIRED_ROLE = 'team_req/not_required_role';
/**
* Tried to operate on a request which does not exist
* (TeamRequestService)
*/
export const TEAM_REQ_NOT_FOUND = 'team_req/not_found' as const;
/**
* Invalid or non-existent collection id
* (TeamRequestService)
*/
export const TEAM_REQ_INVALID_TARGET_COLL_ID =
'team_req/invalid_target_id' as const;
/**
* Tried to perform action on a request when the user is not even member of the team
* (GqlRequestTeamMemberGuard, GqlCollectionTeamMemberGuard)
*/
export const TEAM_REQ_NOT_MEMBER = 'team_req/not_member';
export const TEAM_INVITE_MEMBER_HAS_INVITE =
'team_invite/member_has_invite' as const;
export const TEAM_INVITE_NO_INVITE_FOUND =
'team_invite/no_invite_found' as const;
export const TEAM_INVITE_ALREADY_MEMBER = 'team_invite/already_member' as const;
export const TEAM_INVITE_EMAIL_DO_NOT_MATCH =
'team_invite/email_do_not_match' as const;
export const TEAM_INVITE_NOT_VALID_VIEWER =
'team_invite/not_valid_viewer' as const;
export const SHORTCODE_NOT_FOUND = 'shortcode/not_found' as const;
export const SHORTCODE_INVALID_JSON = 'shortcode/invalid_json' as const;
/**
* Invalid or non-existent TEAM ENVIRONMMENT ID
* (TeamEnvironmentsService)
*/
export const TEAM_ENVIRONMMENT_NOT_FOUND =
'team_environment/not_found' as const;
/**
* The user is not a member of the team of the given environment
* (GqlTeamEnvTeamGuard)
*/
export const TEAM_ENVIRONMENT_NOT_TEAM_MEMBER =
'team_environment/not_team_member' as const;
/*
|------------------------------------|
|Server errors that are actually bugs|
|------------------------------------|
*/
/**
* Couldn't find user data from the GraphQL context (Check if GqlAuthGuard is applied)
* (GqlTeamMemberGuard, GqlCollectionTeamMemberGuard)
*/
export const BUG_AUTH_NO_USER_CTX = 'bug/auth/auth_no_user_ctx' as const;
/**
* Couldn't find teamID parameter in the attached GraphQL operation. (Check if teamID is present)
* (GqlTeamMemberGuard, GQLEAAdminGuard, GqlCollectionTeamMemberGuard)
*/
export const BUG_TEAM_NO_TEAM_ID = 'bug/team/no_team_id';
/**
* Couldn't find RequireTeamRole decorator. (Check if it is applied)
* (GqlTeamMemberGuard)
*/
export const BUG_TEAM_NO_REQUIRE_TEAM_ROLE = 'bug/team/no_require_team_role';
/**
* Couldn't find 'collectionID' param to the attached GQL operation. (Check if exists)
* (GqlCollectionTeamMemberGuard)
*/
export const BUG_TEAM_COLL_NO_COLL_ID = 'bug/team_coll/no_coll_id';
/**
* Couldn't find 'requestID' param to the attached GQL operation. (Check if exists)
* (GqlRequestTeamMemberGuard)
*/
export const BUG_TEAM_REQ_NO_REQ_ID = 'bug/team_req/no_req_id';
export const BUG_TEAM_INVITE_NO_INVITE_ID =
'bug/team_invite/no_invite_id' as const;
/**
* Couldn't find RequireTeamRole decorator. (Check if it is applied)
* (GqlTeamEnvTeamGuard)
*/
export const BUG_TEAM_ENV_GUARD_NO_REQUIRE_ROLES =
'bug/team_env/guard_no_require_roles' as const;
/**
* Couldn't find 'id' param to the operation. (Check if it is applied)
* (GqlTeamEnvTeamGuard)
*/
export const BUG_TEAM_ENV_GUARD_NO_ENV_ID =
'bug/team_env/guard_no_env_id' as const;

View File

@@ -1,8 +1,40 @@
import { NestFactory } from '@nestjs/core';
import { json } from 'express';
import { AppModule } from './app.module';
async function bootstrap() {
console.log(`Running in production: ${process.env.PRODUCTION}`);
console.log(`Port: ${process.env.PORT}`);
console.log(`Database: ${process.env.DATABASE_URL}`);
const app = await NestFactory.create(AppModule);
await app.listen(3000);
// Increase fil upload limit to 50MB
app.use(
json({
limit: '100mb',
}),
);
if (process.env.PRODUCTION === 'false') {
console.log('Enabling CORS with development settings');
app.enableCors({
origin: true,
});
} else {
console.log('Enabling CORS with production settings');
// HACK: Temporary fix for Liyas to work on production directly :P
/*
app.enableCors({
origin: /hoppscotch\.io$/
});
*/
app.enableCors({
origin: true,
});
}
await app.listen(process.env.PORT || 3170);
}
bootstrap();