forked from tsai/budibase
12 changed files with 187 additions and 162 deletions
@ -1,105 +1,105 @@ |
|||||
const env = require("../environment") |
// const env = require("../environment")
|
||||
const { apiKeyTable } = require("../db/dynamoClient") |
// const { apiKeyTable } = require("../db/dynamoClient")
|
||||
|
|
||||
const DEFAULT_USAGE = { |
// const DEFAULT_USAGE = {
|
||||
rows: 0, |
// rows: 0,
|
||||
storage: 0, |
// storage: 0,
|
||||
views: 0, |
// views: 0,
|
||||
automationRuns: 0, |
// automationRuns: 0,
|
||||
users: 0, |
// users: 0,
|
||||
} |
// }
|
||||
|
|
||||
const DEFAULT_PLAN = { |
// const DEFAULT_PLAN = {
|
||||
rows: 1000, |
// rows: 1000,
|
||||
// 1 GB
|
// // 1 GB
|
||||
storage: 8589934592, |
// storage: 8589934592,
|
||||
views: 10, |
// views: 10,
|
||||
automationRuns: 100, |
// automationRuns: 100,
|
||||
users: 10000, |
// users: 10000,
|
||||
} |
// }
|
||||
|
|
||||
function buildUpdateParams(key, property, usage) { |
// function buildUpdateParams(key, property, usage) {
|
||||
return { |
// return {
|
||||
primary: key, |
// primary: key,
|
||||
condition: |
// condition:
|
||||
"attribute_exists(#quota) AND attribute_exists(#limits) AND #quota.#prop < #limits.#prop AND #quotaReset > :now", |
// "attribute_exists(#quota) AND attribute_exists(#limits) AND #quota.#prop < #limits.#prop AND #quotaReset > :now",
|
||||
expression: "ADD #quota.#prop :usage", |
// expression: "ADD #quota.#prop :usage",
|
||||
names: { |
// names: {
|
||||
"#quota": "usageQuota", |
// "#quota": "usageQuota",
|
||||
"#prop": property, |
// "#prop": property,
|
||||
"#limits": "usageLimits", |
// "#limits": "usageLimits",
|
||||
"#quotaReset": "quotaReset", |
// "#quotaReset": "quotaReset",
|
||||
}, |
// },
|
||||
values: { |
// values: {
|
||||
":usage": usage, |
// ":usage": usage,
|
||||
":now": Date.now(), |
// ":now": Date.now(),
|
||||
}, |
// },
|
||||
} |
// }
|
||||
} |
// }
|
||||
|
|
||||
function getNewQuotaReset() { |
// function getNewQuotaReset() {
|
||||
return Date.now() + 2592000000 |
// return Date.now() + 2592000000
|
||||
} |
// }
|
||||
|
|
||||
exports.Properties = { |
// exports.Properties = {
|
||||
ROW: "rows", |
// ROW: "rows",
|
||||
UPLOAD: "storage", |
// UPLOAD: "storage",
|
||||
VIEW: "views", |
// VIEW: "views",
|
||||
USER: "users", |
// USER: "users",
|
||||
AUTOMATION: "automationRuns", |
// AUTOMATION: "automationRuns",
|
||||
} |
// }
|
||||
|
|
||||
exports.getAPIKey = async appId => { |
// exports.getAPIKey = async appId => {
|
||||
if (!env.USE_QUOTAS) { |
// if (!env.USE_QUOTAS) {
|
||||
return { apiKey: null } |
// return { apiKey: null }
|
||||
} |
// }
|
||||
return apiKeyTable.get({ primary: appId }) |
// return apiKeyTable.get({ primary: appId })
|
||||
} |
// }
|
||||
|
|
||||
/** |
// /**
|
||||
* Given a specified API key this will add to the usage object for the specified property. |
// * Given a specified API key this will add to the usage object for the specified property.
|
||||
* @param {string} apiKey The API key which is to be updated. |
// * @param {string} apiKey The API key which is to be updated.
|
||||
* @param {string} property The property which is to be added to (within the nested usageQuota object). |
// * @param {string} property The property which is to be added to (within the nested usageQuota object).
|
||||
* @param {number} usage The amount (this can be negative) to adjust the number by. |
// * @param {number} usage The amount (this can be negative) to adjust the number by.
|
||||
* @returns {Promise<void>} When this completes the API key will now be up to date - the quota period may have |
// * @returns {Promise<void>} When this completes the API key will now be up to date - the quota period may have
|
||||
* also been reset after this call. |
// * also been reset after this call.
|
||||
*/ |
// */
|
||||
exports.update = async (apiKey, property, usage) => { |
// exports.update = async (apiKey, property, usage) => {
|
||||
if (!env.USE_QUOTAS) { |
// if (!env.USE_QUOTAS) {
|
||||
return |
// return
|
||||
} |
// }
|
||||
try { |
// try {
|
||||
await apiKeyTable.update(buildUpdateParams(apiKey, property, usage)) |
// await apiKeyTable.update(buildUpdateParams(apiKey, property, usage))
|
||||
} catch (err) { |
// } catch (err) {
|
||||
// conditional check means the condition failed, need to check why
|
// // conditional check means the condition failed, need to check why
|
||||
if (err.code === "ConditionalCheckFailedException") { |
// if (err.code === "ConditionalCheckFailedException") {
|
||||
// get the API key so we can check it
|
// // get the API key so we can check it
|
||||
const keyObj = await apiKeyTable.get({ primary: apiKey }) |
// const keyObj = await apiKeyTable.get({ primary: apiKey })
|
||||
// the usage quota or usage limits didn't exist
|
// // the usage quota or usage limits didn't exist
|
||||
if (keyObj && (keyObj.usageQuota == null || keyObj.usageLimits == null)) { |
// if (keyObj && (keyObj.usageQuota == null || keyObj.usageLimits == null)) {
|
||||
keyObj.usageQuota = |
// keyObj.usageQuota =
|
||||
keyObj.usageQuota == null ? DEFAULT_USAGE : keyObj.usageQuota |
// keyObj.usageQuota == null ? DEFAULT_USAGE : keyObj.usageQuota
|
||||
keyObj.usageLimits = |
// keyObj.usageLimits =
|
||||
keyObj.usageLimits == null ? DEFAULT_PLAN : keyObj.usageLimits |
// keyObj.usageLimits == null ? DEFAULT_PLAN : keyObj.usageLimits
|
||||
keyObj.quotaReset = getNewQuotaReset() |
// keyObj.quotaReset = getNewQuotaReset()
|
||||
await apiKeyTable.put({ item: keyObj }) |
// await apiKeyTable.put({ item: keyObj })
|
||||
return |
// return
|
||||
} |
// }
|
||||
// we have in fact breached the reset period
|
// // we have in fact breached the reset period
|
||||
else if (keyObj && keyObj.quotaReset <= Date.now()) { |
// else if (keyObj && keyObj.quotaReset <= Date.now()) {
|
||||
// update the quota reset period and reset the values for all properties
|
// // update the quota reset period and reset the values for all properties
|
||||
keyObj.quotaReset = getNewQuotaReset() |
// keyObj.quotaReset = getNewQuotaReset()
|
||||
for (let prop of Object.keys(keyObj.usageQuota)) { |
// for (let prop of Object.keys(keyObj.usageQuota)) {
|
||||
if (prop === property) { |
// if (prop === property) {
|
||||
keyObj.usageQuota[prop] = usage > 0 ? usage : 0 |
// keyObj.usageQuota[prop] = usage > 0 ? usage : 0
|
||||
} else { |
// } else {
|
||||
keyObj.usageQuota[prop] = 0 |
// keyObj.usageQuota[prop] = 0
|
||||
} |
// }
|
||||
} |
// }
|
||||
await apiKeyTable.put({ item: keyObj }) |
// await apiKeyTable.put({ item: keyObj })
|
||||
return |
// return
|
||||
} |
// }
|
||||
} |
// }
|
||||
throw err |
// throw err
|
||||
} |
// }
|
||||
} |
// }
|
||||
|
|||||
Loading…
Reference in new issue