Skip to content

Make mstacm api production ready #65

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

Merged
merged 7 commits into from
Sep 1, 2019
Merged
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
61 changes: 61 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# Javascript Node CircleCI 2.0 configuration file
#
# Check https://circleci.com/docs/2.0/language-javascript/ for more details
#
version: 2
jobs:
build:
docker:
# specify the version you desire here
- image: circleci/node:lts

# Specify service dependencies here if necessary
# CircleCI maintains a library of pre-built images
# documented at https://circleci.com/docs/2.0/circleci-images/
# - image: circleci/mongo:3.4.4

working_directory: ~/mstacm.org/apps/web

steps:
- checkout:
path: ~/mstacm.org

# Download and cache dependencies
- restore_cache:
keys:
- v1-dependencies-{{ checksum "yarn.lock" }}
# fallback to using the latest cache if no exact match is found
- v1-dependencies-

- run: yarn install

- save_cache:
paths:
- node_modules
key: v1-dependencies-{{ checksum "yarn.lock" }}

# run tests!
- run: yarn test

# TODO: when we have access to a production machine with SSH access
# deploy:
# machine:
# enabled: true
# working_directory: ~/mstacm.org/apps/web
# steps:
# - run:
# name: Deploy Over SSH
# command: |
# ssh $SSH_USER@$SSH_HOST "cd /opt/mstacm.org/api && git pull && bash deploy.sh"
# workflows:
#workflows:
# version: 2
# build-and-deploy:
# jobs:
# - build
# - deploy:
# requires:
# - build
# filters:
# branches:
# only: master
37 changes: 37 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,40 @@ docker-compose up

## Developing
I recommend installing [altair](https://altair.sirmuel.design/).

## Deployment
The deployment of the website is targeted to be as automated as possible, but
these steps serve as a safe guard in case something breaks or to bolster
understanding of the underlying system.

To setup automatic deployment, perform the following steps:
1. ssh into the production server:
```bash
ssh changeme-user@changeme-host
```
2. If this is a fresh new server, perform some kind of ssh hardening
as automatic deployment currently occurs over ssh:
+ https://linux-audit.com/audit-and-harden-your-ssh-configuration/
+ https://www.cyberciti.biz/tips/linux-unix-bsd-openssh-server-best-practices.html
+ https://medium.com/@jasonrigden/hardening-ssh-1bcb99cd4cef
3. Install [Docker Compose](https://docs.docker.com/compose/install/)
4. Clone the `mstacm.org` repo in `/opt/`:
```bash
cd /opt/
sudo git clone [email protected]:sigdotcom/mstacm.org.git
sudo chown -R <YOUR_USERNAME>:<YOUR_USERNAME> mstacm.org/
```
5. Setup the necessary secrets:
```bash
# Enter the directory
cd mstacm.org/api
# Create docker environment variable file
cp .docker/web.env.default .docker/web.env
vim .docker/web.env
# Return to root repository directory
cd ..
```
5. Run `deploy.sh` in the root repository:
```bash
bash deploy.sh
```
5 changes: 3 additions & 2 deletions api/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ WORKDIR /server

COPY . /server
ADD package.json /server/package.json
RUN yarn install
RUN yarn

EXPOSE 4000
CMD yarn start:dev
RUN yarn build
CMD yarn start:prod
8 changes: 8 additions & 0 deletions api/docker-compose.override.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
version: '3'

services:
phoenix_web:
command: yarn start:dev
build: .
volumes:
- .:/server
5 changes: 5 additions & 0 deletions api/docker-compose.production.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
version: '3'

services:
phoenix_web:
image: "acmweb/api"
15 changes: 6 additions & 9 deletions api/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
version: '3'

services:
phoenix_db:
services:
phoenix_db:
image: "postgres"
ports:
- "5432:5432"
Expand All @@ -10,18 +10,15 @@ services:
environment:
- POSTGRES_USER=phoenix
- POSTGRES_PASSWORD=phoenix
phoenix_web:
build: .
volumes:
- .:/server
phoenix_web:
networks:
- db_nw
- web_nw
depends_on:
- phoenix_db
depends_on:
- phoenix_db
env_file:
- ./.docker/web.env
environment:
environment:
- DB_HOST=phoenix_db
- DB_USERNAME=phoenix
- DB_PASSWORD=phoenix
Expand Down
6 changes: 6 additions & 0 deletions api/nodemon.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"watch": ["src"],
"ext": "ts",
"ignore": ["src/**/*.spec.ts"],
"exec": "ts-node -r tsconfig-paths/register src/main.ts"
}
25 changes: 15 additions & 10 deletions api/ormconfig.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
const ROOT_DIR = process.env.NODE_ENV != "production" ? "src/" : "build/";
const EXT = process.env.NODE_ENV != "production" ? ".ts" : ".js";
const IS_PROD = process.env.NODE_ENV === "production";
const ROOT_DIR = IS_PROD ? "build/src" : "src";

module.exports = {
type: "postgres",
Expand All @@ -8,17 +8,22 @@ module.exports = {
password: process.env.DB_PASSWORD || "phoenix",
database: process.env.DB_TABLE || "phoenix",
port: process.env.DB_PORT || 5432,
synchronize: true,
logging: "all",
logger: "advanced-console",
dropSchema: true,
cache: true,
entities: [ROOT_DIR + "/**/entity" + EXT],
migrations: [ROOT_DIR + "migrations/**/*" + EXT],
subscribers: [ROOT_DIR + "subscribers/**/*" + EXT],
// See src/main.ts as to why these are all false
// Should we automatically synchronize our database?
synchronize: false,
// Run migrations automatically,
migrationsRun: false,
// Should we automatically drop the entire database on start?
dropSchema: false,
entities: [`${ROOT_DIR}/resources/**/index{.js,.ts}`],
migrations: [`${ROOT_DIR}/migrations/**/*{.js,.ts}`],
subscribers: [`${ROOT_DIR}/subscribers/**/*{.js.ts}`],
cli: {
entitiesDir: ROOT_DIR + "entities",
migrationsDir: ROOT_DIR + "migrations",
subscribersDir: ROOT_DIR + "subscribers"
entitiesDir: `${ROOT_DIR}/entities`,
migrationsDir: `${ROOT_DIR}/migrations`,
subscribersDir: `${ROOT_DIR}/subscribers`
}
};
9 changes: 5 additions & 4 deletions api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@
"uuid": "^3.3.2"
},
"devDependencies": {
"@types/graphql": "^14.2.1",
"@types/jsonwebtoken": "^8.3.2",
"@types/koa-logger": "^3.1.1",
"@types/koa-passport": "^4.0.2",
Expand All @@ -47,17 +46,19 @@
"jest": "^24.8.0",
"prettier": "^1.18.2",
"ts-jest": "^24.0.2",
"tsconfig-paths": "^3.8.0",
"tslint-config-prettier": "^1.18.0",
"tslint-microsoft-contrib": "^6.2.0",
"typescript": "^3.5.2"
"typescript": "3.3.4000"
},
"scripts": {
"start:dev": "NODE_ENV='development' nodemon --watch 'src/**/*' -e ts,tsx --exec \"ts-node\" --files ./src/index.ts",
"start:dev": "NODE_ENV='development' nodemon",
"start:prod": "NODE_ENV='production' node build/src/main.js",
"build": "tsc -p tsconfig.release.json",
"build:watch": "tsc -w -p tsconfig.release.json",
"lint": "tslint -t stylish --project \"tsconfig.json\"",
"test": "jest --coverage",
"test:watch": "jest --watch",
"typeorm": "ts-node --files -r src/ ./node_modules/typeorm/cli.js"
"typeorm": "ts-node -r tsconfig-paths/register ./node_modules/typeorm/cli.js"
}
}
8 changes: 5 additions & 3 deletions api/src/lib/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,23 +10,25 @@ export async function seedDatabase() {
const defaultUser = userRepository.create({
email: "[email protected]",
firstName: "Kevin",
googleSub: "123421",
sub: "123421",
lastName: "Schoonover"
});
await userRepository.save(defaultUser);

await productRepository
.create({
description: "Payment for ACM Yearly Membership",
name: "ACM Yearly Membership",
displayName: "ACM Yearly Membership",
tag: "yearly-membership",
price: 20
})
.save();

await productRepository
.create({
description: "Payment for ACM Semesterly Membership",
name: "ACM Semesterly Membership",
displayName: "ACM Semesterly Membership",
tag: "semesterly-membership",
price: 11
})
.save();
Expand Down
5 changes: 0 additions & 5 deletions api/src/lib/interfaces.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,3 @@
import { ParameterizedContext } from "koa";
import { User } from "../User";

export interface IContext extends ParameterizedContext {}

interface IOwnership {
isOwner(user: User): boolean;
}
11 changes: 11 additions & 0 deletions api/src/lib/products.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// WARNING: be very careful about editting this file
// as it is tied directly to the initial_values migration.
// DO NOT edit this file unless you know what you're doing.

export const YEARLY_MEMBERSHIP = {
tag: "yearly-membership"
};

export const SEMESTERLY_MEMBERSHIP = {
tag: "semesterly-membership"
};
10 changes: 6 additions & 4 deletions api/src/index.ts → api/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,20 @@ import "./lib/errors";
import { authChecker } from "./lib/auth";

import { ParameterizedContext as KoaContext } from "koa";
import { seedDatabase } from "./lib/helpers";

// register 3rd party IOC container
useContainer(Container);

async function bootstrap() {
try {
// create TypeORM connection
await createConnection();
const connection = await createConnection();

// seed database with some data
await seedDatabase();
await connection.runMigrations();

if (process.env.NODE_ENV !== "production") {
await connection.synchronize();
}

// build TypeGraphQL executable schema
const schema = await TypeGraphQL.buildSchema({
Expand Down
4 changes: 2 additions & 2 deletions api/src/middleware/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,15 +95,15 @@ passport.use(

try {
let user = await User.findOne({
googleSub: sub
sub
});

if (!user) {
user = new User();
user.firstName = given_name;
user.lastName = family_name;
user.email = email;
user.googleSub = sub;
user.sub = sub;
user = await user.save();
}
done(undefined, user);
Expand Down
Loading