Skip to content

Commit

Permalink
Merge pull request #135 from Carifio24/refactor
Browse files Browse the repository at this point in the history
Refactor package to allow for more modularity
  • Loading branch information
Carifio24 authored Sep 13, 2024
2 parents 5f49a3a + 9b4ea9d commit 542209c
Show file tree
Hide file tree
Showing 19 changed files with 9,773 additions and 4,157 deletions.
12,103 changes: 8,809 additions & 3,294 deletions package-lock.json

Large diffs are not rendered by default.

14 changes: 12 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
"build": "tsc",
"lint": "node_modules/.bin/eslint src --ext .ts",
"serve": "node dist/main.js",
"start": "npm run serve"
"start": "npm run serve",
"test": "jest"
},
"dependencies": {
"@effect/schema": "^0.63.2",
Expand Down Expand Up @@ -37,12 +38,21 @@
"winston": "^3.10.0"
},
"devDependencies": {
"@types/supertest": "^6.0.2",
"eslint": "^8.13.0",
"eslint-plugin-vue": "^8.6.0",
"jest": "^29.7.0",
"sass": "~1.32.0",
"sass-loader": "^10.0.0"
"sass-loader": "^10.0.0",
"supertest": "^7.0.0"
},
"engines": {
"node": "18.18.0"
},
"jest": {
"testEnvironment": "node",
"coveragePathIgnorePatterns": [
"/node_modules/"
]
}
}
87 changes: 87 additions & 0 deletions src/app.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import { Express } from "express";
import session from "express-session";
import bodyParser from "body-parser";
import cookieParser from "cookie-parser";
import cors, { CorsOptions } from "cors";
import { Sequelize } from "sequelize";
import sequelizeStore from "connect-session-sequelize";
import { v4 } from "uuid";

import { apiKeyMiddleware } from "./middleware";
import { ALLOWED_ORIGINS } from "./utils";

export function setupApp(app: Express, db: Sequelize) {

const corsOptions: CorsOptions = {
origin: "*",
methods: "GET,HEAD,PUT,PATCH,POST,DELETE",
preflightContinue: false,
optionsSuccessStatus: 204
};

const PRODUCTION = process.env.NODE_ENV === "production";
const SESSION_MAX_AGE = 24 * 60 * 60; // in seconds

app.use(cors(corsOptions));
app.use(cookieParser());
const SequelizeStore = sequelizeStore(session.Store);
const store = new SequelizeStore({
db,
table: "CosmicDSSession", // We need to use the model name instead of the table name (here they are different)
checkExpirationInterval: 15 * 60 * 1000, // The interval at which to cleanup expired sessions in milliseconds
expiration: SESSION_MAX_AGE * 1000, // The maximum age (in milliseconds) of a valid session
extendDefaultFields: function (defaults, sess) {
return {
data: defaults.data,
expires: defaults.expires,
user_id: sess.user_id,
username: sess.username,
email: sess.email
};
}
});


const SECRET = "ADD_REAL_SECRET";
const SESSION_NAME = "cosmicds";

app.set("trust proxy", 1);
app.use(session({
secret: SECRET,
genid: (_req) => v4(),
store: store,
name: SESSION_NAME,
saveUninitialized: false,
resave: true,
cookie: {
path: "/",
maxAge: SESSION_MAX_AGE,
httpOnly: true,
secure: PRODUCTION
}
}));
store.sync();

app.use(apiKeyMiddleware);

// parse requests of content-type - application/json
app.use(bodyParser.json());

// parse requests of content-type - application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: true }));

app.use(function(req, res, next) {

const origin = req.get("origin");
if (origin !== undefined && ALLOWED_ORIGINS.includes(origin)) {
res.header("Access-Control-Allow-Origin", origin);
}
next();
});

app.all("*", (req, _res, next) => {
console.log(req.session.id);
next();
});

}
43 changes: 20 additions & 23 deletions src/database.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,32 +62,29 @@ export enum UserType {
Admin
}

export function getDatabaseConnection() {
// Grab any environment variables
// Currently, just the DB password
dotenv.config();

const dbName = "cosmicds_db";
const username = "cdsadmin";
const password = process.env.DB_PASSWORD;
//const username = "jon";
//const password = "Testp@ss123";
export const cosmicdsDB = new Sequelize(dbName, username, password, {
host: "cosmicds-db.cupwuw3jvfpc.us-east-1.rds.amazonaws.com",
dialect: "mysql",
define: {
timestamps: false
}
});
dotenv.config();

const dbName = process.env.DB_NAME as string;
const username = process.env.DB_USERNAME as string;
const password = process.env.DB_PASSWORD;
const database = new Sequelize(dbName, username, password, {
host: process.env.DB_HOSTNAME as string,
dialect: "mysql",
define: {
timestamps: false
}
});

// Initialize our models with our database connection
initializeModels(database);

// Initialize our models with our database connection
initializeModels(cosmicdsDB);
// (async () => {
// await CosmicDSSession.sync({}).catch(console.log);
// console.log("Done sync!");
// })();
// Create any associations that we need
setUpAssociations();

// Create any associations that we need
setUpAssociations();
return database;
}

// For now, this just distinguishes between duplicate account creation and other errors
// We can flesh this out layer
Expand Down
14 changes: 10 additions & 4 deletions src/main.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,26 @@
import { promises } from "fs";
import { join } from "path";
import { app } from "./server";
import { createApp } from "./server";
import { getDatabaseConnection } from "./database";

const STORIES_DIR = join(__dirname, "stories");
const MAIN_FILE = "main.js";

const db = getDatabaseConnection();
const app = createApp(db);
promises.readdir(STORIES_DIR, { withFileTypes: true }).then(entries => {
entries.forEach(async (entry) => {
if (entry.isDirectory()) {
const file = join(STORIES_DIR, entry.name, MAIN_FILE);
const data = await import(file);
data.setup(app, db);
app.use(data.path, data.router);
}
});
}).then(() => {
import("./server");
});


// set port, listen for requests
const PORT = process.env.PORT || 8081;
app.listen(PORT, () => {
console.log(`Server is running on port ${PORT}.`);
});
30 changes: 30 additions & 0 deletions src/middleware.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { Request, Response as ExpressResponse, NextFunction } from "express";

import { getAPIKey, hasPermission } from "./authorization";
import { ALLOWED_ORIGINS } from "./utils";


export async function apiKeyMiddleware(req: Request, res: ExpressResponse, next: NextFunction): Promise<void> {

if (req.originalUrl === "/") {
next();
return;
}

// The whitelisting of hosts is temporary!
const host = req.headers.origin;
const validOrigin = host && ALLOWED_ORIGINS.includes(host);
const key = req.get("Authorization");
const apiKey = key ? await getAPIKey(key) : null;
const apiKeyExists = apiKey !== null;
if (validOrigin || (apiKeyExists && hasPermission(apiKey, req))) {
next();
} else {
res.statusCode = apiKeyExists ? 403 : 401;
const message = apiKeyExists ?
"Your API key does not provide permission to access this endpoint!" :
"You must provide a valid CosmicDS API key!";
res.json({ message });
res.end();
}
}
Loading

0 comments on commit 542209c

Please sign in to comment.