Major update, fixing email test case.
This commit is contained in:
parent
0dd46d12fa
commit
48c1b4b1fe
|
@ -28,6 +28,12 @@ async function buildEmail(purpose, email, user) {
|
||||||
getTemplateByPurpose(TYPE, EmailTemplatePurpose.STYLES),
|
getTemplateByPurpose(TYPE, EmailTemplatePurpose.STYLES),
|
||||||
getTemplateByPurpose(TYPE, purpose),
|
getTemplateByPurpose(TYPE, purpose),
|
||||||
])
|
])
|
||||||
|
if (!base || !styles || !body) {
|
||||||
|
throw "Unable to build email, missing base components"
|
||||||
|
}
|
||||||
|
base = base.contents
|
||||||
|
styles = styles.contents
|
||||||
|
body = body.contents
|
||||||
|
|
||||||
// TODO: need to extend the context as much as possible
|
// TODO: need to extend the context as much as possible
|
||||||
const context = {
|
const context = {
|
||||||
|
@ -59,6 +65,9 @@ exports.sendEmail = async ctx => {
|
||||||
user = db.get(userId)
|
user = db.get(userId)
|
||||||
}
|
}
|
||||||
const config = await determineScopedConfig(db, params)
|
const config = await determineScopedConfig(db, params)
|
||||||
|
if (!config) {
|
||||||
|
ctx.throw(400, "Unable to find SMTP configuration")
|
||||||
|
}
|
||||||
const transport = createSMTPTransport(config)
|
const transport = createSMTPTransport(config)
|
||||||
const message = {
|
const message = {
|
||||||
from: config.from,
|
from: config.from,
|
||||||
|
|
|
@ -1,10 +1,13 @@
|
||||||
const { generateTemplateID, StaticDatabases } = require("@budibase/auth").db
|
const { generateTemplateID, StaticDatabases } = require("@budibase/auth").db
|
||||||
const { CouchDB } = require("../../../db")
|
const { CouchDB } = require("../../../db")
|
||||||
const { TemplateMetadata, TemplateBindings } = require("../../../constants")
|
const {
|
||||||
|
TemplateMetadata,
|
||||||
|
TemplateBindings,
|
||||||
|
GLOBAL_OWNER,
|
||||||
|
} = require("../../../constants")
|
||||||
const { getTemplates } = require("../../../constants/templates")
|
const { getTemplates } = require("../../../constants/templates")
|
||||||
|
|
||||||
const GLOBAL_DB = StaticDatabases.GLOBAL.name
|
const GLOBAL_DB = StaticDatabases.GLOBAL.name
|
||||||
const GLOBAL_OWNER = "global"
|
|
||||||
|
|
||||||
exports.save = async ctx => {
|
exports.save = async ctx => {
|
||||||
const db = new CouchDB(GLOBAL_DB)
|
const db = new CouchDB(GLOBAL_DB)
|
||||||
|
|
|
@ -11,7 +11,7 @@ const FIRST_USER_EMAIL = "test@test.com"
|
||||||
const FIRST_USER_PASSWORD = "test"
|
const FIRST_USER_PASSWORD = "test"
|
||||||
const GLOBAL_DB = StaticDatabases.GLOBAL.name
|
const GLOBAL_DB = StaticDatabases.GLOBAL.name
|
||||||
|
|
||||||
exports.userSave = async ctx => {
|
exports.save = async ctx => {
|
||||||
const db = new CouchDB(GLOBAL_DB)
|
const db = new CouchDB(GLOBAL_DB)
|
||||||
const { email, password, _id } = ctx.request.body
|
const { email, password, _id } = ctx.request.body
|
||||||
|
|
||||||
|
@ -69,10 +69,10 @@ exports.firstUser = async ctx => {
|
||||||
global: true,
|
global: true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
await exports.userSave(ctx)
|
await exports.save(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.userDelete = async ctx => {
|
exports.destroy = async ctx => {
|
||||||
const db = new CouchDB(GLOBAL_DB)
|
const db = new CouchDB(GLOBAL_DB)
|
||||||
const dbUser = await db.get(ctx.params.id)
|
const dbUser = await db.get(ctx.params.id)
|
||||||
await db.remove(dbUser._id, dbUser._rev)
|
await db.remove(dbUser._id, dbUser._rev)
|
||||||
|
@ -82,7 +82,7 @@ exports.userDelete = async ctx => {
|
||||||
}
|
}
|
||||||
|
|
||||||
// called internally by app server user fetch
|
// called internally by app server user fetch
|
||||||
exports.userFetch = async ctx => {
|
exports.fetch = async ctx => {
|
||||||
const db = new CouchDB(GLOBAL_DB)
|
const db = new CouchDB(GLOBAL_DB)
|
||||||
const response = await db.allDocs(
|
const response = await db.allDocs(
|
||||||
getGlobalUserParams(null, {
|
getGlobalUserParams(null, {
|
||||||
|
@ -100,7 +100,7 @@ exports.userFetch = async ctx => {
|
||||||
}
|
}
|
||||||
|
|
||||||
// called internally by app server user find
|
// called internally by app server user find
|
||||||
exports.userFind = async ctx => {
|
exports.find = async ctx => {
|
||||||
const db = new CouchDB(GLOBAL_DB)
|
const db = new CouchDB(GLOBAL_DB)
|
||||||
let user
|
let user
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -25,7 +25,7 @@ function smtpValidation() {
|
||||||
function settingValidation() {
|
function settingValidation() {
|
||||||
// prettier-ignore
|
// prettier-ignore
|
||||||
return Joi.object({
|
return Joi.object({
|
||||||
url: Joi.string().valid("", null),
|
platformUrl: Joi.string().valid("", null),
|
||||||
logoUrl: Joi.string().valid("", null),
|
logoUrl: Joi.string().valid("", null),
|
||||||
company: Joi.string().required(),
|
company: Joi.string().required(),
|
||||||
}).unknown(true)
|
}).unknown(true)
|
||||||
|
|
|
@ -25,10 +25,10 @@ function buildUserSaveValidation() {
|
||||||
}
|
}
|
||||||
|
|
||||||
router
|
router
|
||||||
.post("/api/admin/users", buildUserSaveValidation(), controller.userSave)
|
.post("/api/admin/users", buildUserSaveValidation(), controller.save)
|
||||||
.get("/api/admin/users", controller.userFetch)
|
.get("/api/admin/users", controller.fetch)
|
||||||
.post("/api/admin/users/first", controller.firstUser)
|
.post("/api/admin/users/first", controller.firstUser)
|
||||||
.delete("/api/admin/users/:id", controller.userDelete)
|
.delete("/api/admin/users/:id", controller.destroy)
|
||||||
.get("/api/admin/users/:id", controller.userFind)
|
.get("/api/admin/users/:id", controller.find)
|
||||||
|
|
||||||
module.exports = router
|
module.exports = router
|
||||||
|
|
|
@ -5,12 +5,19 @@ const { EmailTemplatePurpose } = require("../../../constants")
|
||||||
const sendMailMock = jest.fn()
|
const sendMailMock = jest.fn()
|
||||||
jest.mock("nodemailer")
|
jest.mock("nodemailer")
|
||||||
const nodemailer = require("nodemailer")
|
const nodemailer = require("nodemailer")
|
||||||
nodemailer.createTransport.mockReturnValue({"sendMail": sendMailMock});
|
nodemailer.createTransport.mockReturnValue({
|
||||||
|
sendMail: sendMailMock,
|
||||||
|
verify: jest.fn()
|
||||||
|
})
|
||||||
|
|
||||||
describe("/api/admin/email", () => {
|
describe("/api/admin/email", () => {
|
||||||
let request = setup.getRequest()
|
let request = setup.getRequest()
|
||||||
let config = setup.getConfig()
|
let config = setup.getConfig()
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
await config.init()
|
||||||
|
})
|
||||||
|
|
||||||
afterAll(setup.afterAll)
|
afterAll(setup.afterAll)
|
||||||
|
|
||||||
it("should be able to send an email (with mocking)", async () => {
|
it("should be able to send an email (with mocking)", async () => {
|
||||||
|
@ -26,5 +33,10 @@ describe("/api/admin/email", () => {
|
||||||
.set(config.defaultHeaders())
|
.set(config.defaultHeaders())
|
||||||
.expect("Content-Type", /json/)
|
.expect("Content-Type", /json/)
|
||||||
.expect(200)
|
.expect(200)
|
||||||
|
expect(res.body.message).toBeDefined()
|
||||||
|
expect(sendMailMock).toHaveBeenCalled()
|
||||||
|
const emailCall = sendMailMock.mock.calls[0][0]
|
||||||
|
expect(emailCall.subject).toBe("Hello!")
|
||||||
|
expect(emailCall.html).not.toContain("Invalid Binding")
|
||||||
})
|
})
|
||||||
})
|
})
|
|
@ -39,6 +39,8 @@ class TestConfiguration {
|
||||||
async init() {
|
async init() {
|
||||||
// create a test user
|
// create a test user
|
||||||
await this._req({
|
await this._req({
|
||||||
|
email: "test@test.com",
|
||||||
|
password: "test",
|
||||||
_id: "us_uuid1",
|
_id: "us_uuid1",
|
||||||
builder: {
|
builder: {
|
||||||
global: true,
|
global: true,
|
||||||
|
@ -64,7 +66,7 @@ class TestConfiguration {
|
||||||
await this._req({
|
await this._req({
|
||||||
type: Configs.SETTINGS,
|
type: Configs.SETTINGS,
|
||||||
config: {
|
config: {
|
||||||
url: "http://localhost:10000",
|
platformUrl: "http://localhost:10000",
|
||||||
logoUrl: "http://localhost:10000/logo",
|
logoUrl: "http://localhost:10000/logo",
|
||||||
company: "TestCompany",
|
company: "TestCompany",
|
||||||
}
|
}
|
||||||
|
@ -78,7 +80,7 @@ class TestConfiguration {
|
||||||
port: 12345,
|
port: 12345,
|
||||||
host: "smtptesthost.com",
|
host: "smtptesthost.com",
|
||||||
from: "testfrom@test.com",
|
from: "testfrom@test.com",
|
||||||
|
subject: "Hello!",
|
||||||
}
|
}
|
||||||
}, null, controllers.config.save)
|
}, null, controllers.config.save)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
module.exports = {
|
module.exports = {
|
||||||
email: require("../../../controllers/admin/email"),
|
email: require("../../../controllers/admin/email"),
|
||||||
groups: require("../../../controllers/admin/groups"),
|
groups: require("../../../controllers/admin/groups"),
|
||||||
config: require("../../../controllers/admin/groups"),
|
config: require("../../../controllers/admin/configs"),
|
||||||
templates: require("../../../controllers/admin/groups"),
|
templates: require("../../../controllers/admin/templates"),
|
||||||
users: require("../../../controllers/admin/groups"),
|
users: require("../../../controllers/admin/users"),
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,7 @@ const EmailTemplatePurpose = {
|
||||||
}
|
}
|
||||||
|
|
||||||
const TemplateBindings = {
|
const TemplateBindings = {
|
||||||
URL: "url",
|
PLATFORM_URL: "platformUrl",
|
||||||
COMPANY: "company",
|
COMPANY: "company",
|
||||||
LOGO_URL: "logoUrl",
|
LOGO_URL: "logoUrl",
|
||||||
STYLES: "styles",
|
STYLES: "styles",
|
||||||
|
@ -76,3 +76,4 @@ exports.TemplateTypes = TemplateTypes
|
||||||
exports.EmailTemplatePurpose = EmailTemplatePurpose
|
exports.EmailTemplatePurpose = EmailTemplatePurpose
|
||||||
exports.TemplateMetadata = TemplateMetadata
|
exports.TemplateMetadata = TemplateMetadata
|
||||||
exports.TemplateBindings = TemplateBindings
|
exports.TemplateBindings = TemplateBindings
|
||||||
|
exports.GLOBAL_OWNER = "global"
|
||||||
|
|
|
@ -47,7 +47,7 @@
|
||||||
<table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%">
|
<table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%">
|
||||||
<tbody><tr>
|
<tbody><tr>
|
||||||
<td style="text-align: left; padding-left: 10px;">
|
<td style="text-align: left; padding-left: 10px;">
|
||||||
<h3 class="heading"><a href="{{ url }}">Budibase Platform</a></h3>
|
<h3 class="heading"><a href="{{ platformUrl }}">Budibase Platform</a></h3>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody></table>
|
</tbody></table>
|
||||||
|
@ -64,7 +64,7 @@
|
||||||
<table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%">
|
<table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%">
|
||||||
<tbody><tr>
|
<tbody><tr>
|
||||||
<td style="text-align: left; padding-right: 10px;">
|
<td style="text-align: left; padding-right: 10px;">
|
||||||
<p>© 2021 Restobar. All Rights Reserved</p>
|
<p>© 2021 {{ company }}. All Rights Reserved</p>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody></table>
|
</tbody></table>
|
||||||
|
@ -80,3 +80,4 @@
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</body>
|
</body>
|
||||||
|
</html>
|
|
@ -3,6 +3,7 @@ const {
|
||||||
EmailTemplatePurpose,
|
EmailTemplatePurpose,
|
||||||
TemplateTypes,
|
TemplateTypes,
|
||||||
TemplatePurpose,
|
TemplatePurpose,
|
||||||
|
GLOBAL_OWNER,
|
||||||
} = require("../index")
|
} = require("../index")
|
||||||
const { join } = require("path")
|
const { join } = require("path")
|
||||||
const CouchDB = require("../../db")
|
const CouchDB = require("../../db")
|
||||||
|
@ -10,14 +11,14 @@ const { getTemplateParams, StaticDatabases } = require("@budibase/auth").db
|
||||||
|
|
||||||
exports.EmailTemplates = {
|
exports.EmailTemplates = {
|
||||||
[EmailTemplatePurpose.PASSWORD_RECOVERY]: readStaticFile(
|
[EmailTemplatePurpose.PASSWORD_RECOVERY]: readStaticFile(
|
||||||
join(__dirname, "passwordRecovery.html")
|
join(__dirname, "passwordRecovery.hbs")
|
||||||
),
|
),
|
||||||
[EmailTemplatePurpose.INVITATION]: readStaticFile(
|
[EmailTemplatePurpose.INVITATION]: readStaticFile(
|
||||||
join(__dirname, "invitation.html")
|
join(__dirname, "invitation.hbs")
|
||||||
),
|
),
|
||||||
[EmailTemplatePurpose.BASE]: readStaticFile(join(__dirname, "base.html")),
|
[EmailTemplatePurpose.BASE]: readStaticFile(join(__dirname, "base.hbs")),
|
||||||
[EmailTemplatePurpose.STYLES]: readStaticFile(
|
[EmailTemplatePurpose.STYLES]: readStaticFile(
|
||||||
join(__dirname, "style.css")
|
join(__dirname, "style.hbs")
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,7 +38,11 @@ exports.addBaseTemplates = (templates, type = null) => {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if (exports.EmailTemplates[purpose]) {
|
if (exports.EmailTemplates[purpose]) {
|
||||||
templates.push(exports.EmailTemplates[purpose])
|
templates.push({
|
||||||
|
contents: exports.EmailTemplates[purpose],
|
||||||
|
purpose,
|
||||||
|
type,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return templates
|
return templates
|
||||||
|
@ -46,7 +51,7 @@ exports.addBaseTemplates = (templates, type = null) => {
|
||||||
exports.getTemplates = async ({ ownerId, type, id } = {}) => {
|
exports.getTemplates = async ({ ownerId, type, id } = {}) => {
|
||||||
const db = new CouchDB(StaticDatabases.GLOBAL.name)
|
const db = new CouchDB(StaticDatabases.GLOBAL.name)
|
||||||
const response = await db.allDocs(
|
const response = await db.allDocs(
|
||||||
getTemplateParams(ownerId, id, {
|
getTemplateParams(ownerId || GLOBAL_OWNER, id, {
|
||||||
include_docs: true,
|
include_docs: true,
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
|
@ -15,17 +15,18 @@ exports.getSettingsTemplateContext = async () => {
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
let settings = response.rows.map(row => row.doc)[0] || {}
|
let settings = response.rows.map(row => row.doc)[0] || {}
|
||||||
if (!settings.url) {
|
if (!settings.platformUrl) {
|
||||||
settings.url = LOCAL_URL
|
settings.platformUrl = LOCAL_URL
|
||||||
}
|
}
|
||||||
// TODO: need to fully spec out the context
|
// TODO: need to fully spec out the context
|
||||||
|
const URL = settings.platformUrl
|
||||||
return {
|
return {
|
||||||
[TemplateBindings.LOGO_URL]: settings.logoUrl || LOGO_URL,
|
[TemplateBindings.LOGO_URL]: settings.logoUrl || LOGO_URL,
|
||||||
[TemplateBindings.URL]: settings.url,
|
[TemplateBindings.PLATFORM_URL]: URL,
|
||||||
[TemplateBindings.REGISTRATION_URL]: checkSlashesInUrl(
|
[TemplateBindings.REGISTRATION_URL]: checkSlashesInUrl(
|
||||||
`${settings.url}/registration`
|
`${URL}/registration`
|
||||||
),
|
),
|
||||||
[TemplateBindings.RESET_URL]: checkSlashesInUrl(`${settings.url}/reset`),
|
[TemplateBindings.RESET_URL]: checkSlashesInUrl(`${URL}/reset`),
|
||||||
[TemplateBindings.COMPANY]: settings.company || BASE_COMPANY,
|
[TemplateBindings.COMPANY]: settings.company || BASE_COMPANY,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue