fallback SMTP configuration for cloud

This commit is contained in:
Martin McKeaveney 2021-09-27 14:57:22 +01:00
parent 3b49866825
commit 35d4eac78a
13 changed files with 48 additions and 26 deletions

View File

@ -546,7 +546,7 @@ module External {
}, },
meta: { meta: {
table, table,
} },
} }
// can't really use response right now // can't really use response right now
const response = await makeExternalQuery(appId, json) const response = await makeExternalQuery(appId, json)

View File

@ -13,8 +13,6 @@ const { makePartial } = require("../../tests/utilities")
const { cleanInputValues } = require("../automationUtils") const { cleanInputValues } = require("../automationUtils")
const setup = require("./utilities") const setup = require("./utilities")
usageQuota.getAPIKey.mockReturnValue({ apiKey: "test" })
describe("Run through some parts of the automations system", () => { describe("Run through some parts of the automations system", () => {
let config = setup.getConfig() let config = setup.getConfig()

View File

@ -46,7 +46,7 @@ describe("test the create row action", () => {
await setup.runStep(setup.actions.CREATE_ROW.stepId, { await setup.runStep(setup.actions.CREATE_ROW.stepId, {
row row
}) })
expect(usageQuota.update).toHaveBeenCalledWith(setup.apiKey, "rows", 1) expect(usageQuota.update).toHaveBeenCalledWith("rows", 1)
}) })
}) })

View File

@ -37,7 +37,7 @@ describe("test the delete row action", () => {
it("check usage quota attempts", async () => { it("check usage quota attempts", async () => {
await setup.runInProd(async () => { await setup.runInProd(async () => {
await setup.runStep(setup.actions.DELETE_ROW.stepId, inputs) await setup.runStep(setup.actions.DELETE_ROW.stepId, inputs)
expect(usageQuota.update).toHaveBeenCalledWith(setup.apiKey, "rows", -1) expect(usageQuota.update).toHaveBeenCalledWith("rows", -1)
}) })
}) })

View File

@ -1,4 +1,4 @@
import {Table} from "./common"; import { Table } from "./common"
export enum Operation { export enum Operation {
CREATE = "CREATE", CREATE = "CREATE",
@ -139,7 +139,7 @@ export interface QueryJson {
paginate?: PaginationJson paginate?: PaginationJson
body?: object body?: object
meta?: { meta?: {
table?: Table, table?: Table
} }
extra?: { extra?: {
idFilter?: SearchFilters idFilter?: SearchFilters

View File

@ -252,9 +252,9 @@ module MySQLModule {
json.extra = { json.extra = {
idFilter: { idFilter: {
equal: { equal: {
[primaryKey]: results.insertId [primaryKey]: results.insertId,
},
}, },
}
} }
return json return json
} }

View File

@ -39,7 +39,7 @@ class TestConfiguration {
if (bool) { if (bool) {
env.isDev = () => false env.isDev = () => false
env.isProd = () => true env.isProd = () => true
this.ctx.auth = { apiKey: "test" } this.ctx.user = { tenantId: "test" }
} else { } else {
env.isDev = () => true env.isDev = () => true
env.isProd = () => false env.isProd = () => false
@ -114,7 +114,7 @@ describe("usageQuota middleware", () => {
await config.executeMiddleware() await config.executeMiddleware()
expect(usageQuota.update).toHaveBeenCalledWith("test", "rows", 1) expect(usageQuota.update).toHaveBeenCalledWith("rows", 1)
expect(config.next).toHaveBeenCalled() expect(config.next).toHaveBeenCalled()
}) })
@ -131,7 +131,7 @@ describe("usageQuota middleware", () => {
]) ])
await config.executeMiddleware() await config.executeMiddleware()
expect(usageQuota.update).toHaveBeenCalledWith("test", "storage", 10100) expect(usageQuota.update).toHaveBeenCalledWith("storage", 10100)
expect(config.next).toHaveBeenCalled() expect(config.next).toHaveBeenCalled()
}) })
}) })

View File

@ -50,15 +50,15 @@ module.exports = async (ctx, 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 =
// ctx.request.files.file.length > 1 ctx.request.files.file.length > 1
// ? Array.from(ctx.request.files.file) ? Array.from(ctx.request.files.file)
// : [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)
// } }
try { try {
await usageQuota.update(ctx.user.tenantId, property, usage) await usageQuota.update(property, usage)
return next() return next()
} catch (err) { } catch (err) {
ctx.throw(400, err) ctx.throw(400, err)

View File

@ -12,6 +12,7 @@ exports.Properties = {
USER: "users", USER: "users",
AUTOMATION: "automationRuns", AUTOMATION: "automationRuns",
APPS: "apps", APPS: "apps",
EMAILS: "emails",
} }
/** /**
@ -28,7 +29,8 @@ exports.update = async (property, usage) => {
try { try {
const db = getGlobalDB() const db = getGlobalDB()
const quota = await db.get("usage_quota") const quota = await db.get("usage_quota")
// TODO: check if the quota needs reset
// Check if the quota needs reset
if (Date.now() >= quota.quotaReset) { if (Date.now() >= quota.quotaReset) {
quota.quotaReset = getNewQuotaReset() quota.quotaReset = getNewQuotaReset()
for (let prop of Object.keys(quota.usageQuota)) { for (let prop of Object.keys(quota.usageQuota)) {

View File

@ -151,6 +151,7 @@ exports.adminUser = async ctx => {
apps: 0, apps: 0,
users: 0, users: 0,
views: 0, views: 0,
emails: 0,
}, },
usageLimits: { usageLimits: {
automationRuns: 1000, automationRuns: 1000,
@ -158,6 +159,7 @@ exports.adminUser = async ctx => {
apps: 4, apps: 4,
storage: 1000, storage: 1000,
users: 10, users: 10,
emails: 50,
}, },
}) })
// } // }

View File

@ -33,6 +33,11 @@ module.exports = {
INTERNAL_API_KEY: process.env.INTERNAL_API_KEY, INTERNAL_API_KEY: process.env.INTERNAL_API_KEY,
MULTI_TENANCY: process.env.MULTI_TENANCY, MULTI_TENANCY: process.env.MULTI_TENANCY,
ACCOUNT_PORTAL_URL: process.env.ACCOUNT_PORTAL_URL, ACCOUNT_PORTAL_URL: process.env.ACCOUNT_PORTAL_URL,
SMTP_USER: process.env.SMTP_USER,
SMTP_PASSWORD: process.env.SMTP_PASSWORD,
SMTP_HOST: process.env.SMTP_HOST,
SMTP_PORT: process.env.SMTP_PORT,
SMTP_FROM_ADDRESS: process.env.SMTP_FROM_ADDRESS,
_set(key, value) { _set(key, value) {
process.env[key] = value process.env[key] = value
module.exports[key] = value module.exports[key] = value

View File

@ -1,4 +1,5 @@
const nodemailer = require("nodemailer") const nodemailer = require("nodemailer")
const env = require("../environment")
const { getScopedConfig } = require("@budibase/auth/db") const { getScopedConfig } = require("@budibase/auth/db")
const { EmailTemplatePurpose, TemplateTypes, Configs } = require("../constants") const { EmailTemplatePurpose, TemplateTypes, Configs } = require("../constants")
const { getTemplateByPurpose } = require("../constants/templates") const { getTemplateByPurpose } = require("../constants/templates")
@ -110,7 +111,21 @@ async function getSmtpConfiguration(db, workspaceId = null) {
if (workspaceId) { if (workspaceId) {
params.workspace = workspaceId params.workspace = workspaceId
} }
if (!env.SMTP_FALLBACK_ENABLED) {
return getScopedConfig(db, params) return getScopedConfig(db, params)
} else {
// Use an SMTP fallback configuration from env variables
return {
port: env.SMTP_PORT,
host: env.SMTP_HOST,
secure: false,
auth: {
user: env.SMTP_USER,
pass: env.SMTP_PASSWORD,
},
}
}
} }
/** /**
@ -118,8 +133,8 @@ async function getSmtpConfiguration(db, workspaceId = null) {
* @return {Promise<boolean>} returns true if there is a configuration that can be used. * @return {Promise<boolean>} returns true if there is a configuration that can be used.
*/ */
exports.isEmailConfigured = async (workspaceId = null) => { exports.isEmailConfigured = async (workspaceId = null) => {
// when "testing" simply return true // when "testing" or smtp fallback is enabled simply return true
if (TEST_MODE) { if (TEST_MODE || env.SMTP_FALLBACK_ENABLED) {
return true return true
} }
const db = getGlobalDB() const db = getGlobalDB()