|
|
@ -1,8 +1,7 @@ |
|
|
const { |
|
|
const { |
|
|
generateGlobalUserID, |
|
|
generateGlobalUserID, |
|
|
getGlobalUserParams, |
|
|
getGlobalUserParams, |
|
|
getGlobalDB, |
|
|
|
|
|
getGlobalDBFromCtx, |
|
|
|
|
|
StaticDatabases, |
|
|
StaticDatabases, |
|
|
} = require("@budibase/auth/db") |
|
|
} = require("@budibase/auth/db") |
|
|
const { hash, getGlobalUserByEmail } = require("@budibase/auth").utils |
|
|
const { hash, getGlobalUserByEmail } = require("@budibase/auth").utils |
|
|
@ -14,6 +13,7 @@ const { user: userCache } = require("@budibase/auth/cache") |
|
|
const { invalidateSessions } = require("@budibase/auth/sessions") |
|
|
const { invalidateSessions } = require("@budibase/auth/sessions") |
|
|
const CouchDB = require("../../../db") |
|
|
const CouchDB = require("../../../db") |
|
|
const env = require("../../../environment") |
|
|
const env = require("../../../environment") |
|
|
|
|
|
const { getGlobalDB, getTenantId } = require("@budibase/auth/tenancy") |
|
|
|
|
|
|
|
|
const PLATFORM_INFO_DB = StaticDatabases.PLATFORM_INFO.name |
|
|
const PLATFORM_INFO_DB = StaticDatabases.PLATFORM_INFO.name |
|
|
const TENANT_DOC = StaticDatabases.PLATFORM_INFO.docs.tenants |
|
|
const TENANT_DOC = StaticDatabases.PLATFORM_INFO.docs.tenants |
|
|
@ -73,8 +73,8 @@ async function doesTenantExist(tenantId) { |
|
|
) |
|
|
) |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
async function allUsers(ctx) { |
|
|
async function allUsers() { |
|
|
const db = getGlobalDBFromCtx(ctx) |
|
|
const db = getGlobalDB() |
|
|
const response = await db.allDocs( |
|
|
const response = await db.allDocs( |
|
|
getGlobalUserParams(null, { |
|
|
getGlobalUserParams(null, { |
|
|
include_docs: true, |
|
|
include_docs: true, |
|
|
@ -87,12 +87,13 @@ async function saveUser(user, tenantId) { |
|
|
if (!tenantId) { |
|
|
if (!tenantId) { |
|
|
throw "No tenancy specified." |
|
|
throw "No tenancy specified." |
|
|
} |
|
|
} |
|
|
|
|
|
// specify the tenancy incase we're making a new admin user (public)
|
|
|
const db = getGlobalDB(tenantId) |
|
|
const db = getGlobalDB(tenantId) |
|
|
let { email, password, _id } = user |
|
|
let { email, password, _id } = user |
|
|
// make sure another user isn't using the same email
|
|
|
// make sure another user isn't using the same email
|
|
|
let dbUser |
|
|
let dbUser |
|
|
if (email) { |
|
|
if (email) { |
|
|
dbUser = await getGlobalUserByEmail(email, tenantId) |
|
|
dbUser = await getGlobalUserByEmail(email) |
|
|
if (dbUser != null && (dbUser._id !== _id || Array.isArray(dbUser))) { |
|
|
if (dbUser != null && (dbUser._id !== _id || Array.isArray(dbUser))) { |
|
|
throw "Email address already in use." |
|
|
throw "Email address already in use." |
|
|
} |
|
|
} |
|
|
@ -148,10 +149,8 @@ async function saveUser(user, tenantId) { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
exports.save = async ctx => { |
|
|
exports.save = async ctx => { |
|
|
// this always stores the user into the requesting users tenancy
|
|
|
|
|
|
const tenantId = ctx.user.tenantId |
|
|
|
|
|
try { |
|
|
try { |
|
|
ctx.body = await saveUser(ctx.request.body, tenantId) |
|
|
ctx.body = await saveUser(ctx.request.body, getTenantId()) |
|
|
} catch (err) { |
|
|
} catch (err) { |
|
|
ctx.throw(err.status || 400, err) |
|
|
ctx.throw(err.status || 400, err) |
|
|
} |
|
|
} |
|
|
@ -163,7 +162,7 @@ exports.adminUser = async ctx => { |
|
|
ctx.throw(403, "Organisation already exists.") |
|
|
ctx.throw(403, "Organisation already exists.") |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
const db = getGlobalDB(tenantId) |
|
|
const db = getGlobalDB() |
|
|
const response = await db.allDocs( |
|
|
const response = await db.allDocs( |
|
|
getGlobalUserParams(null, { |
|
|
getGlobalUserParams(null, { |
|
|
include_docs: true, |
|
|
include_docs: true, |
|
|
@ -197,7 +196,7 @@ exports.adminUser = async ctx => { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
exports.destroy = async ctx => { |
|
|
exports.destroy = async ctx => { |
|
|
const db = getGlobalDBFromCtx(ctx) |
|
|
const db = getGlobalDB() |
|
|
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) |
|
|
await userCache.invalidateUser(dbUser._id) |
|
|
await userCache.invalidateUser(dbUser._id) |
|
|
@ -209,7 +208,7 @@ exports.destroy = async ctx => { |
|
|
|
|
|
|
|
|
exports.removeAppRole = async ctx => { |
|
|
exports.removeAppRole = async ctx => { |
|
|
const { appId } = ctx.params |
|
|
const { appId } = ctx.params |
|
|
const db = getGlobalDBFromCtx(ctx) |
|
|
const db = getGlobalDB() |
|
|
const users = await allUsers(ctx) |
|
|
const users = await allUsers(ctx) |
|
|
const bulk = [] |
|
|
const bulk = [] |
|
|
const cacheInvalidations = [] |
|
|
const cacheInvalidations = [] |
|
|
@ -239,7 +238,7 @@ exports.getSelf = async ctx => { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
exports.updateSelf = async ctx => { |
|
|
exports.updateSelf = async ctx => { |
|
|
const db = getGlobalDBFromCtx(ctx) |
|
|
const db = getGlobalDB() |
|
|
const user = await db.get(ctx.user._id) |
|
|
const user = await db.get(ctx.user._id) |
|
|
if (ctx.request.body.password) { |
|
|
if (ctx.request.body.password) { |
|
|
ctx.request.body.password = await hash(ctx.request.body.password) |
|
|
ctx.request.body.password = await hash(ctx.request.body.password) |
|
|
@ -272,7 +271,7 @@ exports.fetch = async ctx => { |
|
|
|
|
|
|
|
|
// called internally by app server user find
|
|
|
// called internally by app server user find
|
|
|
exports.find = async ctx => { |
|
|
exports.find = async ctx => { |
|
|
const db = getGlobalDBFromCtx(ctx) |
|
|
const db = getGlobalDB() |
|
|
let user |
|
|
let user |
|
|
try { |
|
|
try { |
|
|
user = await db.get(ctx.params.id) |
|
|
user = await db.get(ctx.params.id) |
|
|
@ -310,16 +309,14 @@ exports.tenantLookup = async ctx => { |
|
|
|
|
|
|
|
|
exports.invite = async ctx => { |
|
|
exports.invite = async ctx => { |
|
|
let { email, userInfo } = ctx.request.body |
|
|
let { email, userInfo } = ctx.request.body |
|
|
const tenantId = ctx.user.tenantId |
|
|
const existing = await getGlobalUserByEmail(email) |
|
|
const existing = await getGlobalUserByEmail(email, tenantId) |
|
|
|
|
|
if (existing) { |
|
|
if (existing) { |
|
|
ctx.throw(400, "Email address already in use.") |
|
|
ctx.throw(400, "Email address already in use.") |
|
|
} |
|
|
} |
|
|
if (!userInfo) { |
|
|
if (!userInfo) { |
|
|
userInfo = {} |
|
|
userInfo = {} |
|
|
} |
|
|
} |
|
|
userInfo.tenantId = tenantId |
|
|
await sendEmail(email, EmailTemplatePurpose.INVITATION, { |
|
|
await sendEmail(tenantId, email, EmailTemplatePurpose.INVITATION, { |
|
|
|
|
|
subject: "{{ company }} platform invitation", |
|
|
subject: "{{ company }} platform invitation", |
|
|
info: userInfo, |
|
|
info: userInfo, |
|
|
}) |
|
|
}) |
|
|
@ -333,17 +330,13 @@ exports.inviteAccept = async ctx => { |
|
|
try { |
|
|
try { |
|
|
// info is an extension of the user object that was stored by global
|
|
|
// info is an extension of the user object that was stored by global
|
|
|
const { email, info } = await checkInviteCode(inviteCode) |
|
|
const { email, info } = await checkInviteCode(inviteCode) |
|
|
// only pass through certain props for accepting
|
|
|
ctx.body = await saveUser({ |
|
|
ctx.request.body = { |
|
|
|
|
|
firstName, |
|
|
firstName, |
|
|
lastName, |
|
|
lastName, |
|
|
password, |
|
|
password, |
|
|
email, |
|
|
email, |
|
|
...info, |
|
|
...info, |
|
|
} |
|
|
}, info.tenantId) |
|
|
ctx.user = { |
|
|
|
|
|
tenantId: info.tenantId, |
|
|
|
|
|
} |
|
|
|
|
|
// this will flesh out the body response
|
|
|
// this will flesh out the body response
|
|
|
await exports.save(ctx) |
|
|
await exports.save(ctx) |
|
|
} catch (err) { |
|
|
} catch (err) { |
|
|
|