Merge pull request #2691 from Budibase/feature/onboarding-backend
SSO flow and account deletion
This commit is contained in:
commit
e4fb901e24
|
@ -12,6 +12,7 @@ const {
|
||||||
auditLog,
|
auditLog,
|
||||||
tenancy,
|
tenancy,
|
||||||
appTenancy,
|
appTenancy,
|
||||||
|
authError,
|
||||||
} = require("./middleware")
|
} = require("./middleware")
|
||||||
const { setDB } = require("./db")
|
const { setDB } = require("./db")
|
||||||
const userCache = require("./cache/user")
|
const userCache = require("./cache/user")
|
||||||
|
@ -60,6 +61,7 @@ module.exports = {
|
||||||
buildTenancyMiddleware: tenancy,
|
buildTenancyMiddleware: tenancy,
|
||||||
buildAppTenancyMiddleware: appTenancy,
|
buildAppTenancyMiddleware: appTenancy,
|
||||||
auditLog,
|
auditLog,
|
||||||
|
authError,
|
||||||
},
|
},
|
||||||
cache: {
|
cache: {
|
||||||
user: userCache,
|
user: userCache,
|
||||||
|
|
|
@ -2,6 +2,7 @@ const jwt = require("./passport/jwt")
|
||||||
const local = require("./passport/local")
|
const local = require("./passport/local")
|
||||||
const google = require("./passport/google")
|
const google = require("./passport/google")
|
||||||
const oidc = require("./passport/oidc")
|
const oidc = require("./passport/oidc")
|
||||||
|
const { authError } = require("./passport/utils")
|
||||||
const authenticated = require("./authenticated")
|
const authenticated = require("./authenticated")
|
||||||
const auditLog = require("./auditLog")
|
const auditLog = require("./auditLog")
|
||||||
const tenancy = require("./tenancy")
|
const tenancy = require("./tenancy")
|
||||||
|
@ -16,4 +17,5 @@ module.exports = {
|
||||||
auditLog,
|
auditLog,
|
||||||
tenancy,
|
tenancy,
|
||||||
appTenancy,
|
appTenancy,
|
||||||
|
authError,
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,11 @@ async function authenticate(accessToken, refreshToken, profile, done) {
|
||||||
* from couchDB rather than environment variables, using this factory is necessary for dynamically configuring passport.
|
* from couchDB rather than environment variables, using this factory is necessary for dynamically configuring passport.
|
||||||
* @returns Dynamically configured Passport Google Strategy
|
* @returns Dynamically configured Passport Google Strategy
|
||||||
*/
|
*/
|
||||||
exports.strategyFactory = async function (config, callbackUrl) {
|
exports.strategyFactory = async function (
|
||||||
|
config,
|
||||||
|
callbackUrl,
|
||||||
|
verify = authenticate
|
||||||
|
) {
|
||||||
try {
|
try {
|
||||||
const { clientID, clientSecret } = config
|
const { clientID, clientSecret } = config
|
||||||
|
|
||||||
|
@ -43,7 +47,7 @@ exports.strategyFactory = async function (config, callbackUrl) {
|
||||||
clientSecret: config.clientSecret,
|
clientSecret: config.clientSecret,
|
||||||
callbackURL: callbackUrl,
|
callbackURL: callbackUrl,
|
||||||
},
|
},
|
||||||
authenticate
|
verify
|
||||||
)
|
)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err)
|
console.error(err)
|
||||||
|
|
|
@ -30,6 +30,10 @@ exports.invalidateSessions = async (userId, sessionId = null) => {
|
||||||
sessions.push({ key: makeSessionID(userId, sessionId) })
|
sessions.push({ key: makeSessionID(userId, sessionId) })
|
||||||
} else {
|
} else {
|
||||||
sessions = await getSessionsForUser(userId)
|
sessions = await getSessionsForUser(userId)
|
||||||
|
sessions.forEach(
|
||||||
|
session =>
|
||||||
|
(session.key = makeSessionID(session.userId, session.sessionId))
|
||||||
|
)
|
||||||
}
|
}
|
||||||
const client = await redis.getSessionClient()
|
const client = await redis.getSessionClient()
|
||||||
const promises = []
|
const promises = []
|
||||||
|
|
|
@ -31,7 +31,12 @@ async function allUsers() {
|
||||||
return response.rows.map(row => row.doc)
|
return response.rows.map(row => row.doc)
|
||||||
}
|
}
|
||||||
|
|
||||||
async function saveUser(user, tenantId, hashPassword = true) {
|
async function saveUser(
|
||||||
|
user,
|
||||||
|
tenantId,
|
||||||
|
hashPassword = true,
|
||||||
|
requirePassword = true
|
||||||
|
) {
|
||||||
if (!tenantId) {
|
if (!tenantId) {
|
||||||
throw "No tenancy specified."
|
throw "No tenancy specified."
|
||||||
}
|
}
|
||||||
|
@ -57,7 +62,7 @@ async function saveUser(user, tenantId, hashPassword = true) {
|
||||||
hashedPassword = hashPassword ? await hash(password) : password
|
hashedPassword = hashPassword ? await hash(password) : password
|
||||||
} else if (dbUser) {
|
} else if (dbUser) {
|
||||||
hashedPassword = dbUser.password
|
hashedPassword = dbUser.password
|
||||||
} else {
|
} else if (requirePassword) {
|
||||||
throw "Password must be specified."
|
throw "Password must be specified."
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,16 +111,21 @@ exports.save = async ctx => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const parseBooleanParam = param => {
|
||||||
|
if (param && param == "false") {
|
||||||
|
return false
|
||||||
|
} else {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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
|
// account portal sends a pre-hashed password - honour param to prevent double hashing
|
||||||
let hashPassword = ctx.request.query.hashPassword
|
const hashPassword = parseBooleanParam(ctx.request.query.hashPassword)
|
||||||
if (hashPassword && hashPassword == "false") {
|
// account portal sends no password for SSO users
|
||||||
hashPassword = false
|
const requirePassword = parseBooleanParam(ctx.request.query.requirePassword)
|
||||||
} else {
|
|
||||||
hashPassword = true
|
|
||||||
}
|
|
||||||
|
|
||||||
if (await doesTenantExist(tenantId)) {
|
if (await doesTenantExist(tenantId)) {
|
||||||
ctx.throw(403, "Organisation already exists.")
|
ctx.throw(403, "Organisation already exists.")
|
||||||
|
@ -148,7 +158,7 @@ exports.adminUser = async ctx => {
|
||||||
tenantId,
|
tenantId,
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
ctx.body = await saveUser(user, tenantId, hashPassword)
|
ctx.body = await saveUser(user, tenantId, hashPassword, requirePassword)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
ctx.throw(err.status || 400, err)
|
ctx.throw(err.status || 400, err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ function buildAdminInitValidation() {
|
||||||
return joiValidator.body(
|
return joiValidator.body(
|
||||||
Joi.object({
|
Joi.object({
|
||||||
email: Joi.string().required(),
|
email: Joi.string().required(),
|
||||||
password: Joi.string().required(),
|
password: Joi.string(),
|
||||||
tenantId: Joi.string().required(),
|
tenantId: Joi.string().required(),
|
||||||
})
|
})
|
||||||
.required()
|
.required()
|
||||||
|
|
Loading…
Reference in New Issue