Browse Source

Adding in self hosted API key.

master
mike12345567 6 years ago
parent
commit
1cbe3771ab
  1. 6
      packages/server/src/app.js
  2. 6
      packages/server/src/middleware/authorized.js
  3. 7
      packages/server/src/middleware/usageQuota.js
  4. 7
      packages/server/src/selfhost/README.md
  5. 39
      packages/server/src/selfhost/index.js
  6. 22
      packages/server/src/utilities/security/apikey.js

6
packages/server/src/app.js

@ -9,6 +9,7 @@ const env = require("./environment")
const eventEmitter = require("./events") const eventEmitter = require("./events")
const automations = require("./automations/index") const automations = require("./automations/index")
const Sentry = require("@sentry/node") const Sentry = require("@sentry/node")
const selfhost = require("./selfhost")
const app = new Koa() const app = new Koa()
@ -49,9 +50,12 @@ destroyable(server)
server.on("close", () => console.log("Server Closed")) server.on("close", () => console.log("Server Closed"))
module.exports = server.listen(env.PORT || 4001, () => { module.exports = server.listen(env.PORT || 4001, async () => {
console.log(`Budibase running on ${JSON.stringify(server.address())}`) console.log(`Budibase running on ${JSON.stringify(server.address())}`)
automations.init() automations.init()
if (env.SELF_HOSTED) {
await selfhost.init()
}
}) })
process.on("uncaughtException", err => { process.on("uncaughtException", err => {

6
packages/server/src/middleware/authorized.js

@ -7,7 +7,7 @@ const {
doesHavePermission, doesHavePermission,
} = require("../utilities/security/permissions") } = require("../utilities/security/permissions")
const env = require("../environment") const env = require("../environment")
const { apiKeyTable } = require("../db/dynamoClient") const { getAPIKey } = require("../utilities/security/apikey")
const { AuthTypes } = require("../constants") const { AuthTypes } = require("../constants")
const ADMIN_ROLES = [BUILTIN_ROLE_IDS.ADMIN, BUILTIN_ROLE_IDS.BUILDER] const ADMIN_ROLES = [BUILTIN_ROLE_IDS.ADMIN, BUILTIN_ROLE_IDS.BUILDER]
@ -21,9 +21,7 @@ module.exports = (permType, permLevel = null) => async (ctx, next) => {
} }
if (env.CLOUD && ctx.headers["x-api-key"] && ctx.headers["x-instanceid"]) { if (env.CLOUD && ctx.headers["x-api-key"] && ctx.headers["x-instanceid"]) {
// api key header passed by external webhook // api key header passed by external webhook
const apiKeyInfo = await apiKeyTable.get({ const apiKeyInfo = await getAPIKey(ctx.headers["x-api-key"])
primary: ctx.headers["x-api-key"],
})
if (apiKeyInfo) { if (apiKeyInfo) {
ctx.auth = { ctx.auth = {

7
packages/server/src/middleware/usageQuota.js

@ -43,6 +43,10 @@ module.exports = async (ctx, next) => {
return return
} }
} }
// if running in builder or a self hosted cloud usage quotas should not be executed
if (!env.CLOUD || env.SELF_HOSTED) {
return next()
}
// update usage for uploads to be the total size // update usage for uploads to be the total size
if (property === usageQuota.Properties.UPLOAD) { if (property === usageQuota.Properties.UPLOAD) {
const files = const files =
@ -51,9 +55,6 @@ module.exports = async (ctx, next) => {
: [ctx.request.files.file] : [ctx.request.files.file]
usage = files.map(file => file.size).reduce((total, size) => total + size) usage = files.map(file => file.size).reduce((total, size) => total + size)
} }
if (!env.CLOUD) {
return next()
}
try { try {
await usageQuota.update(ctx.auth.apiKey, property, usage) await usageQuota.update(ctx.auth.apiKey, property, usage)
return next() return next()

7
packages/server/src/selfhost/README.md

@ -0,0 +1,7 @@
### Self hosting
This directory contains utilities that are needed for self hosted platforms to operate.
These will mostly be utilities, necessary to the operation of the server e.g. storing self
hosting specific options and attributes to CouchDB.
All the internal operations should be exposed through the `index.js` so importing
the self host directory should give you everything you need.

39
packages/server/src/selfhost/index.js

@ -0,0 +1,39 @@
const CouchDB = require("../db")
const env = require("../environment")
const newid = require("../db/newid")
const SELF_HOST_DB = "self-host-db"
const SELF_HOST_DOC = "self-host-info"
async function createSelfHostDB(db) {
await db.put({
_id: "_design/database",
views: {},
})
const selfHostInfo = {
_id: SELF_HOST_DOC,
apiKeyId: newid(),
}
await db.put(selfHostInfo)
return selfHostInfo
}
exports.init = async () => {
if (!env.SELF_HOSTED) {
return
}
const db = new CouchDB(SELF_HOST_DB)
try {
await db.get(SELF_HOST_DOC)
} catch (err) {
// failed to retrieve
if (err.status === 404) {
await createSelfHostDB(db)
}
}
}
exports.getSelfHostInfo = async () => {
const db = new CouchDB(SELF_HOST_DB)
return db.get(SELF_HOST_DOC)
}

22
packages/server/src/utilities/security/apikey.js

@ -0,0 +1,22 @@
const { apiKeyTable } = require("../../db/dynamoClient")
const env = require("../../environment")
const { getSelfHostInfo } = require("../../selfhost")
/**
* This file purely exists so that we can centralise all logic pertaining to API keys, as their usage differs
* in our Cloud environment versus self hosted.
*/
exports.getAPIKey = async apiKeyId => {
if (env.CLOUD && !env.SELF_HOSTED) {
return apiKeyTable.get({
primary: apiKeyId,
})
}
if (env.SELF_HOSTED) {
const selfHostInfo = await getSelfHostInfo()
// if the api key supplied is correct then return structure similar
return apiKeyId === selfHostInfo.apiKeyId ? { pk: apiKeyId } : null
}
return null
}
Loading…
Cancel
Save