Merge pull request #2574 from Budibase/feature/onboarding-backend
Add new redis key for email verification & pre-hashed password option
This commit is contained in:
commit
d2c5197fa0
|
@ -3,7 +3,27 @@ const { getTenantId, lookupTenantId, getGlobalDB } = require("../tenancy")
|
||||||
|
|
||||||
const EXPIRY_SECONDS = 3600
|
const EXPIRY_SECONDS = 3600
|
||||||
|
|
||||||
exports.getUser = async (userId, tenantId = null) => {
|
/**
|
||||||
|
* The default populate user function
|
||||||
|
*/
|
||||||
|
const populateFromDB = (userId, tenantId) => {
|
||||||
|
return getGlobalDB(tenantId).get(userId)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the requested user by id.
|
||||||
|
* Use redis cache to first read the user.
|
||||||
|
* If not present fallback to loading the user directly and re-caching.
|
||||||
|
* @param {*} userId the id of the user to get
|
||||||
|
* @param {*} tenantId the tenant of the user to get
|
||||||
|
* @param {*} populateUser function to provide the user for re-caching. default to couch db
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
exports.getUser = async (
|
||||||
|
userId,
|
||||||
|
tenantId = null,
|
||||||
|
populateUser = populateFromDB
|
||||||
|
) => {
|
||||||
if (!tenantId) {
|
if (!tenantId) {
|
||||||
try {
|
try {
|
||||||
tenantId = getTenantId()
|
tenantId = getTenantId()
|
||||||
|
@ -15,7 +35,7 @@ exports.getUser = async (userId, tenantId = null) => {
|
||||||
// try cache
|
// try cache
|
||||||
let user = await client.get(userId)
|
let user = await client.get(userId)
|
||||||
if (!user) {
|
if (!user) {
|
||||||
user = await getGlobalDB(tenantId).get(userId)
|
user = await populateUser(userId, tenantId)
|
||||||
client.store(userId, user, EXPIRY_SECONDS)
|
client.store(userId, user, EXPIRY_SECONDS)
|
||||||
}
|
}
|
||||||
if (user && !user.tenantId && tenantId) {
|
if (user && !user.tenantId && tenantId) {
|
||||||
|
|
|
@ -21,7 +21,10 @@ function finalise(
|
||||||
* The tenancy modules should not be used here and it should be assumed that the tenancy context
|
* The tenancy modules should not be used here and it should be assumed that the tenancy context
|
||||||
* has not yet been populated.
|
* has not yet been populated.
|
||||||
*/
|
*/
|
||||||
module.exports = (noAuthPatterns = [], opts = { publicAllowed: false }) => {
|
module.exports = (
|
||||||
|
noAuthPatterns = [],
|
||||||
|
opts = { publicAllowed: false, populateUser: null }
|
||||||
|
) => {
|
||||||
const noAuthOptions = noAuthPatterns ? buildMatcherRegex(noAuthPatterns) : []
|
const noAuthOptions = noAuthPatterns ? buildMatcherRegex(noAuthPatterns) : []
|
||||||
return async (ctx, next) => {
|
return async (ctx, next) => {
|
||||||
let publicEndpoint = false
|
let publicEndpoint = false
|
||||||
|
@ -46,7 +49,15 @@ module.exports = (noAuthPatterns = [], opts = { publicAllowed: false }) => {
|
||||||
error = "No session found"
|
error = "No session found"
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
|
if (opts && opts.populateUser) {
|
||||||
|
user = await getUser(
|
||||||
|
userId,
|
||||||
|
session.tenantId,
|
||||||
|
opts.populateUser(ctx)
|
||||||
|
)
|
||||||
|
} else {
|
||||||
user = await getUser(userId, session.tenantId)
|
user = await getUser(userId, session.tenantId)
|
||||||
|
}
|
||||||
delete user.password
|
delete user.password
|
||||||
authenticated = true
|
authenticated = true
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|
|
@ -8,6 +8,7 @@ const REDIS_PASSWORD = !env.REDIS_PASSWORD ? "budibase" : env.REDIS_PASSWORD
|
||||||
|
|
||||||
exports.Databases = {
|
exports.Databases = {
|
||||||
PW_RESETS: "pwReset",
|
PW_RESETS: "pwReset",
|
||||||
|
VERIFICATIONS: "verification",
|
||||||
INVITATIONS: "invitation",
|
INVITATIONS: "invitation",
|
||||||
DEV_LOCKS: "devLocks",
|
DEV_LOCKS: "devLocks",
|
||||||
DEBOUNCE: "debounce",
|
DEBOUNCE: "debounce",
|
||||||
|
|
|
@ -33,7 +33,7 @@ async function allUsers() {
|
||||||
return response.rows.map(row => row.doc)
|
return response.rows.map(row => row.doc)
|
||||||
}
|
}
|
||||||
|
|
||||||
async function saveUser(user, tenantId) {
|
async function saveUser(user, tenantId, hashPassword = true) {
|
||||||
if (!tenantId) {
|
if (!tenantId) {
|
||||||
throw "No tenancy specified."
|
throw "No tenancy specified."
|
||||||
}
|
}
|
||||||
|
@ -56,7 +56,7 @@ async function saveUser(user, tenantId) {
|
||||||
// get the password, make sure one is defined
|
// get the password, make sure one is defined
|
||||||
let hashedPassword
|
let hashedPassword
|
||||||
if (password) {
|
if (password) {
|
||||||
hashedPassword = await hash(password)
|
hashedPassword = hashPassword ? await hash(password) : password
|
||||||
} else if (dbUser) {
|
} else if (dbUser) {
|
||||||
hashedPassword = dbUser.password
|
hashedPassword = dbUser.password
|
||||||
} else {
|
} else {
|
||||||
|
@ -110,6 +110,15 @@ exports.save = async ctx => {
|
||||||
|
|
||||||
exports.adminUser = async ctx => {
|
exports.adminUser = async ctx => {
|
||||||
const { email, password, tenantId } = ctx.request.body
|
const { email, password, tenantId } = ctx.request.body
|
||||||
|
|
||||||
|
// account portal sends a pre-hashed password - honour param to prevent double hashing
|
||||||
|
let hashPassword = ctx.request.query.hashPassword
|
||||||
|
if (hashPassword && hashPassword == "false") {
|
||||||
|
hashPassword = false
|
||||||
|
} else {
|
||||||
|
hashPassword = true
|
||||||
|
}
|
||||||
|
|
||||||
if (await doesTenantExist(tenantId)) {
|
if (await doesTenantExist(tenantId)) {
|
||||||
ctx.throw(403, "Organisation already exists.")
|
ctx.throw(403, "Organisation already exists.")
|
||||||
}
|
}
|
||||||
|
@ -141,7 +150,7 @@ exports.adminUser = async ctx => {
|
||||||
tenantId,
|
tenantId,
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
ctx.body = await saveUser(user, tenantId)
|
ctx.body = await saveUser(user, tenantId, hashPassword)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
ctx.throw(err.status || 400, err)
|
ctx.throw(err.status || 400, err)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue