Change config file handling

- Add Folder config to top level
- Add module config to load the config files
- Change to toml format for config files
pull/4/head
trivernis 5 years ago
parent 0ff6791c19
commit b1ec17b9d7

1
.gitignore vendored

@ -10,3 +10,4 @@ sqz-force
greenvironment.db greenvironment.db
logs logs
logs* logs*
config/*

@ -0,0 +1 @@
config/default.toml

@ -37,6 +37,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- gql field userVote requires a userId - gql field userVote requires a userId
- default findUser param limit to 20 - default findUser param limit to 20
- only group admins can create group events - only group admins can create group events
- config behaviour to use all files that reside in the ./config directory with the .toml format
### Fixed ### Fixed

@ -0,0 +1,26 @@
# Configuration of the database connection
[database]
connectionUri = "sqlite://greenvironment.db"
# Configuration of the http server
[server]
port = 8080
cors = false
# Configuration for the sessions
[session]
secret = "REPLACE WITH SAFE RANDOM GENERATED SECRET"
cookieMaxAge = 6048e+5 # 7 days
# Configuration for markdown rendering
[markdown]
plugins = ["markdown-it-emoji"]
# Configuration for logging
[logging]
level = "info"
# Configuration for the frontend files
[frontend]
angularIndex = "index.html"
publicPath = "./public"

@ -57,7 +57,9 @@
"typescript": "^3.7.2" "typescript": "^3.7.2"
}, },
"dependencies": { "dependencies": {
"@types/config": "^0.0.36",
"compression": "^1.7.4", "compression": "^1.7.4",
"config": "^3.2.4",
"connect-session-sequelize": "^6.0.0", "connect-session-sequelize": "^6.0.0",
"cookie-parser": "^1.4.4", "cookie-parser": "^1.4.4",
"cors": "^2.8.5", "cors": "^2.8.5",
@ -82,6 +84,7 @@
"socket.io": "^2.2.0", "socket.io": "^2.2.0",
"socket.io-redis": "^5.2.0", "socket.io-redis": "^5.2.0",
"sqlite3": "^4.1.0", "sqlite3": "^4.1.0",
"toml": "^3.0.0",
"uuid": "^3.3.3", "uuid": "^3.3.3",
"winston": "^3.2.1", "winston": "^3.2.1",
"winston-daily-rotate-file": "^4.2.1" "winston-daily-rotate-file": "^4.2.1"

@ -1,4 +1,5 @@
import * as compression from "compression"; import * as compression from "compression";
import * as config from "config";
import * as cookieParser from "cookie-parser"; import * as cookieParser from "cookie-parser";
import * as cors from "cors"; import * as cors from "cors";
import {Request, Response} from "express"; import {Request, Response} from "express";
@ -64,8 +65,8 @@ class App {
this.app = express(); this.app = express();
this.server = new http.Server(this.app); this.server = new http.Server(this.app);
this.io = socketIo(this.server); this.io = socketIo(this.server);
this.sequelize = new Sequelize(globals.config.database.connectionUri); this.sequelize = new Sequelize(config.get("database.connectionUri"));
this.publicPath = globals.config.frontend.publicPath; this.publicPath = config.get("frontend.publicPath");
if (!path.isAbsolute(this.publicPath)) { if (!path.isAbsolute(this.publicPath)) {
this.publicPath = path.normalize(path.join(__dirname, this.publicPath)); this.publicPath = path.normalize(path.join(__dirname, this.publicPath));
} }
@ -79,13 +80,13 @@ class App {
const appSession = session({ const appSession = session({
cookie: { cookie: {
maxAge: Number(globals.config.session.cookieMaxAge) || 604800000, maxAge: Number(config.get("session.cookieMaxAge")),
// @ts-ignore // @ts-ignore
secure: "auto", secure: "auto",
}, },
resave: false, resave: false,
saveUninitialized: false, saveUninitialized: false,
secret: globals.config.session.secret, secret: config.get("session.secret"),
store: new SequelizeStore({db: this.sequelize}), store: new SequelizeStore({db: this.sequelize}),
}); });
@ -112,7 +113,7 @@ class App {
this.app.use(cookieParser()); this.app.use(cookieParser());
this.app.use(appSession); this.app.use(appSession);
// enable cross origin requests if enabled in the config // enable cross origin requests if enabled in the config
if (globals.config.server?.cors) { if (config.get("server.cors")) {
this.app.use(cors()); this.app.use(cors());
} }
// handle authentication via bearer in the Authorization header // handle authentication via bearer in the Authorization header
@ -166,8 +167,8 @@ class App {
}); });
// redirect all request to the angular file // redirect all request to the angular file
this.app.use((req: any, res: Response) => { this.app.use((req: any, res: Response) => {
if (globals.config.frontend.angularIndex) { if (config.get("frontend.angularIndex")) {
const angularIndex = path.join(this.publicPath, globals.config.frontend.angularIndex); const angularIndex = path.join(this.publicPath, config.get("frontend.angularIndex"));
if (fsx.existsSync(path.join(angularIndex))) { if (fsx.existsSync(path.join(angularIndex))) {
res.sendFile(angularIndex); res.sendFile(angularIndex);
} else { } else {
@ -191,10 +192,10 @@ class App {
* Starts the web server. * Starts the web server.
*/ */
public start(): void { public start(): void {
if (globals.config.server?.port) { if (config.has("server.port")) {
logger.info(`Starting server...`); logger.info(`Starting server...`);
this.app.listen(globals.config.server.port); this.app.listen(config.get("server.port"));
logger.info(`Server running on port ${globals.config.server.port}`); logger.info(`Server running on port ${config.get("server.port")}`);
} else { } else {
logger.error("No port specified in the config." + logger.error("No port specified in the config." +
"Please configure a port in the config.yaml."); "Please configure a port in the config.yaml.");

@ -1,26 +0,0 @@
# database connection info
database:
connectionUri: "sqlite://greenvironment.db"
# http server configuration
server:
port: 8080
cors: false
# configuration of sessions
session:
secret: REPLACE WITH SAFE RANDOM GENERATED SECRET
cookieMaxAge: 604800000 # 7 days
# configuration of the markdown parser
markdown:
plugins:
- 'markdown-it-emoji'
# configuration for logging
logging:
level: info
frontend:
angularIndex: index.html
publicPath: ./public

@ -1,3 +1,4 @@
process.env.NODE_CONFIG_DIR = __dirname + "/../config";
// tslint:disable:no-console // tslint:disable:no-console
import * as cluster from "cluster"; import * as cluster from "cluster";
import App from "./app"; import App from "./app";

@ -1,28 +1,13 @@
import * as config from "config";
import {EventEmitter} from "events"; import {EventEmitter} from "events";
import * as fsx from "fs-extra";
import * as yaml from "js-yaml";
import * as path from "path";
import * as winston from "winston"; import * as winston from "winston";
require("winston-daily-rotate-file"); require("winston-daily-rotate-file");
const configPath = "config.yaml";
const defaultConfig = path.join(__dirname, "/../default-config.yaml");
// ensure that the config exists by copying the default config.
if (!(fsx.pathExistsSync(configPath))) {
fsx.copySync(defaultConfig, configPath);
} else {
const conf = yaml.safeLoad(fsx.readFileSync(configPath, "utf-8"));
const defConf = yaml.safeLoad(fsx.readFileSync(defaultConfig, "utf-8"));
fsx.writeFileSync(configPath, yaml.safeDump(Object.assign(defConf, conf)));
}
/** /**
* Defines global variables to be used. * Defines global variables to be used.
*/ */
namespace globals { namespace globals {
export const config: IConfig = yaml.safeLoad(fsx.readFileSync("config.yaml", "utf-8"));
// @ts-ignore // @ts-ignore
export const logger: winston.Logger = winston.createLogger({ export const logger: winston.Logger = winston.createLogger({
transports: [ transports: [
@ -34,7 +19,7 @@ namespace globals {
return `${timestamp} ${level}: ${message}`; return `${timestamp} ${level}: ${message}`;
}), }),
), ),
level: config.logging?.level ?? "info", level: config.get("logging.level"),
}), }),
// @ts-ignore // @ts-ignore
new (winston.transports.DailyRotateFile)({ new (winston.transports.DailyRotateFile)({
@ -47,7 +32,7 @@ namespace globals {
}), }),
), ),
json: false, json: false,
level: config.logging?.level ?? "info", level: config.get("logging.level"),
maxFiles: "7d", maxFiles: "7d",
zippedArchive: true, zippedArchive: true,
}), }),

@ -1,3 +1,4 @@
import * as config from "config";
import * as MarkdownIt from "markdown-it/lib"; import * as MarkdownIt from "markdown-it/lib";
import globals from "./globals"; import globals from "./globals";
@ -5,7 +6,7 @@ namespace markdown {
const md = new MarkdownIt(); const md = new MarkdownIt();
for (const pluginName of globals.config.markdown.plugins) { for (const pluginName of config.get("markdown.plugins") as string[]) {
try { try {
const plugin = require(pluginName); const plugin = require(pluginName);
if (plugin) { if (plugin) {

@ -1,6 +1,5 @@
import * as sqz from "sequelize"; import * as sqz from "sequelize";
import {BelongsTo, BelongsToMany, Column, CreatedAt, ForeignKey, Model, NotNull, Table} from "sequelize-typescript"; import {BelongsTo, BelongsToMany, Column, CreatedAt, ForeignKey, Model, NotNull, Table} from "sequelize-typescript";
import globals from "../globals";
import markdown from "../markdown"; import markdown from "../markdown";
import {Activity} from "./Activity"; import {Activity} from "./Activity";
import {PostVote, VoteType} from "./PostVote"; import {PostVote, VoteType} from "./PostVote";

@ -55,6 +55,11 @@
dependencies: dependencies:
"@types/express" "*" "@types/express" "*"
"@types/config@^0.0.36":
version "0.0.36"
resolved "https://registry.yarnpkg.com/@types/config/-/config-0.0.36.tgz#bf53ca640f3a1a6a2072a9f33e02a44def07a40b"
integrity sha512-EoAeT1MyFWh2BJvBDEFInY714bQBbHOAucqxqqhprhbBFqr+B7fuN5T9CJqUIGDzvwubnKKRqmSo6yPo0aSpNw==
"@types/connect-pg-simple@^4.2.0": "@types/connect-pg-simple@^4.2.0":
version "4.2.0" version "4.2.0"
resolved "https://registry.yarnpkg.com/@types/connect-pg-simple/-/connect-pg-simple-4.2.0.tgz#cb0d85701fa73d16be7a4050e4c95fe070a6df7f" resolved "https://registry.yarnpkg.com/@types/connect-pg-simple/-/connect-pg-simple-4.2.0.tgz#cb0d85701fa73d16be7a4050e4c95fe070a6df7f"
@ -1200,6 +1205,13 @@ concat-stream@^1.6.0:
readable-stream "^2.2.2" readable-stream "^2.2.2"
typedarray "^0.0.6" typedarray "^0.0.6"
config@^3.2.4:
version "3.2.4"
resolved "https://registry.yarnpkg.com/config/-/config-3.2.4.tgz#e60a908582991e800852f9cb60fcf424f3274a6c"
integrity sha512-H1XIGfnU1EAkfjSLn9ZvYDRx9lOezDViuzLDgiJ/lMeqjYe3q6iQfpcLt2NInckJgpAeekbNhQkmnnbdEDs9rw==
dependencies:
json5 "^1.0.1"
connect-session-sequelize@^6.0.0: connect-session-sequelize@^6.0.0:
version "6.0.0" version "6.0.0"
resolved "https://registry.yarnpkg.com/connect-session-sequelize/-/connect-session-sequelize-6.0.0.tgz#afd4456c65d92c9b6b955fdff00afff795e8a420" resolved "https://registry.yarnpkg.com/connect-session-sequelize/-/connect-session-sequelize-6.0.0.tgz#afd4456c65d92c9b6b955fdff00afff795e8a420"
@ -2988,6 +3000,13 @@ json-stringify-safe@~5.0.1:
resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb"
integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=
json5@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe"
integrity sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==
dependencies:
minimist "^1.2.0"
jsonfile@^4.0.0: jsonfile@^4.0.0:
version "4.0.0" version "4.0.0"
resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb"
@ -5320,6 +5339,11 @@ token-stream@0.0.1:
resolved "https://registry.yarnpkg.com/token-stream/-/token-stream-0.0.1.tgz#ceeefc717a76c4316f126d0b9dbaa55d7e7df01a" resolved "https://registry.yarnpkg.com/token-stream/-/token-stream-0.0.1.tgz#ceeefc717a76c4316f126d0b9dbaa55d7e7df01a"
integrity sha1-zu78cXp2xDFvEm0LnbqlXX598Bo= integrity sha1-zu78cXp2xDFvEm0LnbqlXX598Bo=
toml@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/toml/-/toml-3.0.0.tgz#342160f1af1904ec9d204d03a5d61222d762c5ee"
integrity sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w==
toposort-class@^1.0.1: toposort-class@^1.0.1:
version "1.0.1" version "1.0.1"
resolved "https://registry.yarnpkg.com/toposort-class/-/toposort-class-1.0.1.tgz#7ffd1f78c8be28c3ba45cd4e1a3f5ee193bd9988" resolved "https://registry.yarnpkg.com/toposort-class/-/toposort-class-1.0.1.tgz#7ffd1f78c8be28c3ba45cd4e1a3f5ee193bd9988"

Loading…
Cancel
Save