diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..dc80496 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,32 @@ +FROM node:12 + + +LABEL maintainer="Fabian Stamm " + + + +RUN apt-get update + +# for https +RUN apt-get install -yyq ca-certificates +# install libraries +RUN apt-get install -yyq libappindicator1 libasound2 libatk1.0-0 libc6 libcairo2 libcups2 libdbus-1-3 libexpat1 libfontconfig1 libgcc1 libgconf-2-4 libgdk-pixbuf2.0-0 libglib2.0-0 libgtk-3-0 libnspr4 libnss3 libpango-1.0-0 libpangocairo-1.0-0 libstdc++6 libx11-6 libx11-xcb1 libxcb1 libxcomposite1 libxcursor1 libxdamage1 libxext6 libxfixes3 libxi6 libxrandr2 libxrender1 libxss1 libxtst6 +# tools +RUN apt-get install -yyq gconf-service lsb-release wget xdg-utils +# and fonts +RUN apt-get install -yyq fonts-liberation + +RUN mkdir -p /usr/src/app +WORKDIR /usr/src/app + +COPY package.json /usr/src/app +COPY package-lock.json /usr/src/app +COPY lib/ /usr/src/app + +RUN npm install + +VOLUME [ "/usr/src/app/databases", "/usr/src/app/logs" ] + +EXPOSE 5000/tcp + +CMD ["npm", "run", "start"] \ No newline at end of file diff --git a/config.ini b/config.ini deleted file mode 100644 index 93d0117..0000000 --- a/config.ini +++ /dev/null @@ -1,5 +0,0 @@ -[general] -dev=true -port=5013 -admin=admin -access_log=true \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 72e6b7f..5423d8d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,5 +1,5 @@ { - "name": "@hibas123/realtime-db", + "name": "@hibas123/realtimedb", "version": "1.0.0", "lockfileVersion": 1, "requires": true, @@ -76,6 +76,15 @@ "@types/node": "*" } }, + "@types/dotenv": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/@types/dotenv/-/dotenv-6.1.1.tgz", + "integrity": "sha512-ftQl3DtBvqHl9L16tpqqzA4YzCSXZfi7g8cQceTz5rOlYtk/IZbFjAv3mLOQlNIgOaylCQWQoBdDQHPgEBJPHg==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, "@types/events": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.0.tgz", @@ -930,6 +939,11 @@ "is-obj": "^1.0.0" } }, + "dotenv": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.1.0.tgz", + "integrity": "sha512-GUE3gqcDCaMltj2++g6bRQ5rBJWtkWTmqmD0fo1RnnMuUqHNCt2oTPeDnS9n6fKYvlhn7AeBkb38lymBtWBQdA==" + }, "duplexer3": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", diff --git a/package.json b/package.json index e34d1ec..f970324 100644 --- a/package.json +++ b/package.json @@ -9,11 +9,13 @@ "watch-ts": "tsc -w", "watch-node": "nodemon --ignore *.ts lib/index.js", "watch": "concurrently \"npm:watch-*\"", + "build-docker": "npm run build && docker build -t realtimedb .", "prepublishOnly": "tsc" }, "author": "Fabian Stamm ", "license": "ISC", "devDependencies": { + "@types/dotenv": "^6.1.1", "@types/ini": "^1.3.30", "@types/leveldown": "^4.0.0", "@types/levelup": "^3.1.1", @@ -30,6 +32,7 @@ "@hibas123/utils": "^2.1.1", "@types/koa": "^2.0.49", "@types/koa-router": "^7.0.42", + "dotenv": "^8.1.0", "handlebars": "^4.2.0", "ini": "^1.3.5", "koa": "^2.8.1", @@ -40,4 +43,4 @@ "shortid": "^2.2.15", "socket.io": "^2.2.0" } -} \ No newline at end of file +} diff --git a/src/config.ts b/src/config.ts index b0536b2..d5571db 100644 --- a/src/config.ts +++ b/src/config.ts @@ -1,16 +1,20 @@ -import * as ini from "ini"; -import * as fs from "fs"; import Logging from "@hibas123/nodelogging"; +import * as dotenv from "dotenv"; interface IConfig { - general: { - port: string; - admin: string; - access_log: boolean; - dev: boolean - } + port: number; + admin: string; + access_log: boolean; + dev: boolean } -const config = ini.parse(fs.readFileSync("config.ini").toString()) as IConfig; -Logging.debug("Config:", config); +const config: IConfig = { + port: Number(process.env.PORT), + access_log: (process.env.ACCESS_LOG || "").toLowerCase() === "true", + admin: process.env.ADMIN_KEY, + dev: (process.env.DEV || "").toLowerCase() === "true" +} + +dotenv.config() + export default config; \ No newline at end of file diff --git a/src/database/database.ts b/src/database/database.ts index 726458d..394aa07 100644 --- a/src/database/database.ts +++ b/src/database/database.ts @@ -13,7 +13,7 @@ export class DatabaseManager { let databases = await Settings.getDatabases(); databases.forEach(dbconfig => { - let db = new Database(dbconfig.name, dbconfig.accesskey, dbconfig.rules, dbconfig.publickey); + let db = new Database(dbconfig.name, dbconfig.accesskey, dbconfig.rules, dbconfig.publickey, dbconfig.rootkey); this.databases.set(dbconfig.name, db); }) } @@ -68,7 +68,7 @@ export class Database { } } - constructor(public name: string, public accesskey?: string, rawRules?: string, public publickey?: string) { + constructor(public name: string, public accesskey?: string, rawRules?: string, public publickey?: string, public rootkey?: string) { if (rawRules) this.rules = new Rules(rawRules); } @@ -84,11 +84,17 @@ export class Database { this.accesskey = key; } + async setRootKey(key: string) { + await Settings.setDatabaseAccessKey(this.name, key); + this.accesskey = key; + } + async setPublicKey(key: string) { await Settings.setDatabasePublicKey(this.name, key); this.publickey = key; } + getQuery(path: string[]) { return new Query(this, path); } diff --git a/src/index.ts b/src/index.ts index 93c830e..332bdc3 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,18 +1,14 @@ import Logging from "@hibas123/nodelogging"; -// import getLevelDB from "./storage"; -// import Settings from "./settings"; import Web from "./web"; import config from "./config"; import { DatabaseManager } from "./database/database"; import { createServer } from "http"; import { ConnectionManager } from "./connection"; -// Logging.debug(getLevelDB("system")); - DatabaseManager.init().then(() => { const http = createServer(Web.callback()); ConnectionManager.bind(http); - const port = Number(config.general.port) || 5013; + const port = config.port || 5000; http.listen(port, () => Logging.log("Listening on port:", port)) }).catch(err => { Logging.error(err); diff --git a/src/settings.ts b/src/settings.ts index 035021c..668c4d7 100644 --- a/src/settings.ts +++ b/src/settings.ts @@ -1,7 +1,4 @@ import getLevelDB, { resNull } from "./storage"; - -import Encoder, { DataTypes } from "@hibas123/binary-encoder"; -import Logging from "@hibas123/nodelogging"; import { Lock } from "@hibas123/utils"; interface IDatabaseConfig { @@ -9,19 +6,9 @@ interface IDatabaseConfig { publickey?: string; rules?: string; accesskey?: string; + rootkey?: string; } -// const DatabaseEncoder = new Encoder({ -// publickey: { -// index: 1, -// type: DataTypes.STRING, -// allowNull: true -// }, -// rules: { -// index: 2, -// type: DataTypes.STRING -// } -// }); class SettingComponent { db = getLevelDB("_server"); @@ -54,7 +41,8 @@ class SettingComponent { await Promise.all([ this.getField(database, "publickey").then(r => res.publickey = r), this.getField(database, "rules").then(r => res.rules = r), - this.getField(database, "accesskey").then(r => res.accesskey = r) + this.getField(database, "accesskey").then(r => res.accesskey = r), + this.getField(database, "rootkey").then(r => res.rootkey = r) ]) return res; }))) @@ -107,6 +95,14 @@ class SettingComponent { lock.release(); } + async setDatabaseRootKey(name: string, accesskey: string) { + const lock = await this.databaseLock.getLock(); + + await this.setField(name, "rootkey", accesskey); + + lock.release(); + } + async deleteDatabase(name: string) { const lock = await this.databaseLock.getLock(); @@ -119,6 +115,7 @@ class SettingComponent { .del(pref + ":publickey") .del(pref + ":rules") .del(pref + ":accesskey") + .del(pref + ":rootkey") .write(); lock.release(); diff --git a/src/web/helper/hb.ts b/src/web/helper/hb.ts index 3945d61..4361599 100644 --- a/src/web/helper/hb.ts +++ b/src/web/helper/hb.ts @@ -42,7 +42,7 @@ const cache = new Map(); export default function getTemplate(name: string) { let tl: Handlebars.TemplateDelegate; - if (!config.general.dev) + if (!config.dev) tl = cache.get(name); if (!tl) { diff --git a/src/web/helper/log.ts b/src/web/helper/log.ts index cb0e360..a9cddf9 100644 --- a/src/web/helper/log.ts +++ b/src/web/helper/log.ts @@ -2,9 +2,9 @@ import { LoggingBase } from "@hibas123/nodelogging"; import { Context } from "koa"; import config from "../../config"; -const route_logging = new LoggingBase({ name: "access", files: { errorfile: null }, console: config.general.dev }) +const route_logging = new LoggingBase({ name: "access", files: { errorfile: null }, console: config.dev }) const RequestLog = async (ctx: Context, next) => { - if (!config.general.access_log) return next(); + if (!config.access_log) return next(); let start = process.hrtime() let to = false let print = () => { diff --git a/src/web/v1/admin.ts b/src/web/v1/admin.ts index c2db86e..ab3617b 100644 --- a/src/web/v1/admin.ts +++ b/src/web/v1/admin.ts @@ -13,7 +13,7 @@ const AdminRoute = new Router(); AdminRoute.use(async (ctx, next) => { const { key } = ctx.query; - if (key !== config.general.admin) + if (key !== config.admin) throw new NoPermissionError("No permission!"); return next(); }) @@ -87,7 +87,7 @@ AdminRoute } }) .post("/database", async ctx => { - const { name, rules, publickey, accesskey } = ctx.request.body; + const { name, rules, publickey, accesskey, rootkey } = ctx.request.body; if (!name) throw new BadRequestError("Name must be set!"); @@ -101,16 +101,22 @@ AdminRoute if (rules) await db.setRules(rules); - db + if (accesskey) await db.setAccessKey(accesskey); + + if (rootkey) + await db.setRootKey(rootkey); + + ctx.body = "Success"; }) AdminRoute.get("/database/new", getForm("/v1/admin/database", "New/Change Database", { name: { label: "Name", type: "text", }, accesskey: { label: "Access Key", type: "text" }, + rootkey: { label: "Root access key", type: "text" }, rules: { label: "Rules", type: "textarea", value: `{\n ".write": true, \n ".read": true \n}` }, publickey: { label: "Public Key", type: "textarea" } }))