2023-02-21 21:23:53 +13:00
|
|
|
import * as userSdk from "../../../sdk/users"
|
2022-09-23 01:09:20 +12:00
|
|
|
import {
|
|
|
|
featureFlags,
|
|
|
|
tenancy,
|
|
|
|
db as dbCore,
|
|
|
|
utils,
|
|
|
|
encryption,
|
2023-02-21 21:23:53 +13:00
|
|
|
auth as authCore,
|
2022-09-23 01:09:20 +12:00
|
|
|
} from "@budibase/backend-core"
|
|
|
|
import env from "../../../environment"
|
2022-09-23 05:27:43 +12:00
|
|
|
import { groups } from "@budibase/pro"
|
2024-03-06 22:33:17 +13:00
|
|
|
import {
|
|
|
|
UpdateSelfRequest,
|
|
|
|
UpdateSelfResponse,
|
|
|
|
User,
|
|
|
|
UserCtx,
|
|
|
|
} from "@budibase/types"
|
2023-11-21 09:52:29 +13:00
|
|
|
|
2023-03-31 01:11:42 +13:00
|
|
|
const { newid } = utils
|
2022-09-06 05:28:53 +12:00
|
|
|
|
|
|
|
function newTestApiKey() {
|
|
|
|
return env.ENCRYPTED_TEST_PUBLIC_API_KEY
|
|
|
|
}
|
2022-02-11 08:06:49 +13:00
|
|
|
|
2022-02-12 11:24:48 +13:00
|
|
|
function newApiKey() {
|
2022-09-23 01:09:20 +12:00
|
|
|
return encryption.encrypt(
|
|
|
|
`${tenancy.getTenantId()}${dbCore.SEPARATOR}${newid()}`
|
|
|
|
)
|
2022-02-12 11:24:48 +13:00
|
|
|
}
|
|
|
|
|
2022-09-23 01:09:20 +12:00
|
|
|
function cleanupDevInfo(info: any) {
|
2022-02-11 08:06:49 +13:00
|
|
|
// user doesn't need to aware of dev doc info
|
|
|
|
delete info._id
|
|
|
|
delete info._rev
|
|
|
|
return info
|
|
|
|
}
|
|
|
|
|
2022-09-23 01:59:28 +12:00
|
|
|
export async function generateAPIKey(ctx: any) {
|
2022-09-06 05:28:53 +12:00
|
|
|
let userId
|
|
|
|
let apiKey
|
|
|
|
if (env.isTest() && ctx.request.body.userId) {
|
|
|
|
userId = ctx.request.body.userId
|
|
|
|
apiKey = newTestApiKey()
|
|
|
|
} else {
|
|
|
|
userId = ctx.user._id
|
|
|
|
apiKey = newApiKey()
|
|
|
|
}
|
|
|
|
|
2022-09-23 01:09:20 +12:00
|
|
|
const db = tenancy.getGlobalDB()
|
|
|
|
const id = dbCore.generateDevInfoID(userId)
|
2022-02-11 08:06:49 +13:00
|
|
|
let devInfo
|
|
|
|
try {
|
2023-07-18 21:41:51 +12:00
|
|
|
devInfo = await db.get<any>(id)
|
2022-02-11 08:06:49 +13:00
|
|
|
} catch (err) {
|
2022-09-06 05:28:53 +12:00
|
|
|
devInfo = { _id: id, userId }
|
2022-02-11 07:34:55 +13:00
|
|
|
}
|
2023-08-23 05:14:08 +12:00
|
|
|
devInfo.apiKey = apiKey
|
2022-02-11 08:06:49 +13:00
|
|
|
await db.put(devInfo)
|
|
|
|
ctx.body = cleanupDevInfo(devInfo)
|
2022-02-11 07:34:55 +13:00
|
|
|
}
|
|
|
|
|
2022-09-23 01:59:28 +12:00
|
|
|
export async function fetchAPIKey(ctx: any) {
|
2022-09-23 01:09:20 +12:00
|
|
|
const db = tenancy.getGlobalDB()
|
|
|
|
const id = dbCore.generateDevInfoID(ctx.user._id)
|
2022-02-11 08:06:49 +13:00
|
|
|
let devInfo
|
|
|
|
try {
|
|
|
|
devInfo = await db.get(id)
|
|
|
|
} catch (err) {
|
|
|
|
devInfo = {
|
|
|
|
_id: id,
|
2022-02-12 11:24:48 +13:00
|
|
|
userId: ctx.user._id,
|
2023-08-23 05:14:08 +12:00
|
|
|
apiKey: newApiKey(),
|
2022-02-11 08:06:49 +13:00
|
|
|
}
|
|
|
|
await db.put(devInfo)
|
2022-02-11 07:34:55 +13:00
|
|
|
}
|
2022-02-11 08:06:49 +13:00
|
|
|
ctx.body = cleanupDevInfo(devInfo)
|
2022-02-11 07:34:55 +13:00
|
|
|
}
|
2022-02-15 07:11:35 +13:00
|
|
|
|
2022-03-22 06:13:16 +13:00
|
|
|
/**
|
|
|
|
* Add the attributes that are session based to the current user.
|
|
|
|
*/
|
2022-09-23 01:09:20 +12:00
|
|
|
const addSessionAttributesToUser = (ctx: any) => {
|
2022-03-22 06:13:16 +13:00
|
|
|
ctx.body.account = ctx.user.account
|
|
|
|
ctx.body.license = ctx.user.license
|
2022-05-18 23:03:27 +12:00
|
|
|
ctx.body.budibaseAccess = !!ctx.user.budibaseAccess
|
|
|
|
ctx.body.accountPortalAccess = !!ctx.user.accountPortalAccess
|
2022-03-22 06:13:16 +13:00
|
|
|
ctx.body.csrfToken = ctx.user.csrfToken
|
|
|
|
}
|
|
|
|
|
2022-09-23 01:59:28 +12:00
|
|
|
export async function getSelf(ctx: any) {
|
2022-02-15 07:11:35 +13:00
|
|
|
if (!ctx.user) {
|
|
|
|
ctx.throw(403, "User not logged in")
|
|
|
|
}
|
|
|
|
const userId = ctx.user._id
|
|
|
|
ctx.params = {
|
|
|
|
id: userId,
|
|
|
|
}
|
2022-03-09 05:31:07 +13:00
|
|
|
|
2024-01-24 01:21:54 +13:00
|
|
|
// Adjust creators quotas (prevents wrong creators count if user has changed the plan)
|
|
|
|
await groups.adjustGroupCreatorsQuotas()
|
|
|
|
|
2022-02-15 07:11:35 +13:00
|
|
|
// get the main body of the user
|
2023-07-27 05:13:18 +12:00
|
|
|
const user = await userSdk.db.getUser(userId)
|
2022-09-23 05:27:43 +12:00
|
|
|
ctx.body = await groups.enrichUserRolesFromGroups(user)
|
2022-04-20 20:46:20 +12:00
|
|
|
|
|
|
|
// add the feature flags for this tenant
|
2022-09-23 01:09:20 +12:00
|
|
|
const tenantId = tenancy.getTenantId()
|
2022-04-20 20:46:20 +12:00
|
|
|
ctx.body.featureFlags = featureFlags.getTenantFeatureFlags(tenantId)
|
|
|
|
|
2022-03-22 06:13:16 +13:00
|
|
|
addSessionAttributesToUser(ctx)
|
2022-02-15 07:11:35 +13:00
|
|
|
}
|
|
|
|
|
2024-03-06 22:33:17 +13:00
|
|
|
export const syncAppFavourites = async (processedAppIds: string[]) => {
|
2024-03-15 22:09:44 +13:00
|
|
|
if (processedAppIds.length === 0) {
|
|
|
|
return []
|
|
|
|
}
|
2024-03-16 05:52:38 +13:00
|
|
|
|
|
|
|
const tenantId = tenancy.getTenantId()
|
|
|
|
const appPrefix =
|
|
|
|
tenantId === tenancy.DEFAULT_TENANT_ID
|
|
|
|
? dbCore.APP_DEV_PREFIX
|
|
|
|
: `${dbCore.APP_DEV_PREFIX}${tenantId}_`
|
|
|
|
|
|
|
|
const apps = await fetchAppsByIds(processedAppIds, appPrefix)
|
2024-03-06 22:33:17 +13:00
|
|
|
return apps?.reduce((acc: string[], app) => {
|
2024-03-16 05:52:38 +13:00
|
|
|
const id = app.appId.replace(appPrefix, "")
|
2024-03-06 22:33:17 +13:00
|
|
|
if (processedAppIds.includes(id)) {
|
|
|
|
acc.push(id)
|
|
|
|
}
|
|
|
|
return acc
|
|
|
|
}, [])
|
|
|
|
}
|
|
|
|
|
2024-03-16 05:52:38 +13:00
|
|
|
export const fetchAppsByIds = async (
|
|
|
|
processedAppIds: string[],
|
|
|
|
appPrefix: string
|
|
|
|
) => {
|
2024-03-06 22:33:17 +13:00
|
|
|
return await dbCore.getAppsByIDs(
|
2024-03-16 05:52:38 +13:00
|
|
|
processedAppIds.map(appId => {
|
|
|
|
return `${appPrefix}${appId}`
|
|
|
|
})
|
2024-03-06 22:33:17 +13:00
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2024-03-15 22:09:44 +13:00
|
|
|
const processUserAppFavourites = async (
|
2024-03-06 22:33:17 +13:00
|
|
|
user: User,
|
2024-03-15 22:09:44 +13:00
|
|
|
update: UpdateSelfRequest
|
2024-03-06 22:33:17 +13:00
|
|
|
) => {
|
2024-03-15 22:09:44 +13:00
|
|
|
if (!("appFavourites" in update)) {
|
|
|
|
// Ignore requests without an explicit update to favourites.
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2024-03-06 22:33:17 +13:00
|
|
|
const userAppFavourites = user.appFavourites || []
|
2024-03-15 22:09:44 +13:00
|
|
|
const requestAppFavourites = new Set(update.appFavourites || [])
|
|
|
|
const containsAll = userAppFavourites.every(v => requestAppFavourites.has(v))
|
|
|
|
|
|
|
|
if (containsAll && requestAppFavourites.size === userAppFavourites.length) {
|
|
|
|
// Ignore request if the outcome will have no change
|
|
|
|
return
|
2024-03-06 22:33:17 +13:00
|
|
|
}
|
2024-03-15 22:09:44 +13:00
|
|
|
|
|
|
|
// Clean up the request by purging apps that no longer exist.
|
|
|
|
const syncedAppFavourites = await syncAppFavourites([...requestAppFavourites])
|
|
|
|
return syncedAppFavourites
|
2024-03-06 22:33:17 +13:00
|
|
|
}
|
|
|
|
|
2023-02-21 21:23:53 +13:00
|
|
|
export async function updateSelf(
|
|
|
|
ctx: UserCtx<UpdateSelfRequest, UpdateSelfResponse>
|
|
|
|
) {
|
2023-03-08 05:39:26 +13:00
|
|
|
const update = ctx.request.body
|
2023-03-08 02:35:18 +13:00
|
|
|
|
2023-07-27 05:13:18 +12:00
|
|
|
let user = await userSdk.db.getUser(ctx.user._id!)
|
2024-03-15 22:09:44 +13:00
|
|
|
const updatedAppFavourites = await processUserAppFavourites(user, update)
|
2024-03-06 22:33:17 +13:00
|
|
|
|
2024-03-12 01:21:59 +13:00
|
|
|
user = {
|
|
|
|
...user,
|
|
|
|
...update,
|
|
|
|
...(updatedAppFavourites ? { appFavourites: updatedAppFavourites } : {}),
|
2023-02-21 21:23:53 +13:00
|
|
|
}
|
2024-03-06 22:33:17 +13:00
|
|
|
|
2023-07-27 05:13:18 +12:00
|
|
|
user = await userSdk.db.save(user, { requirePassword: false })
|
2023-02-21 21:23:53 +13:00
|
|
|
|
|
|
|
if (update.password) {
|
2022-02-15 07:11:35 +13:00
|
|
|
// Log all other sessions out apart from the current one
|
2023-02-21 21:23:53 +13:00
|
|
|
await authCore.platformLogout({
|
2022-02-15 07:11:35 +13:00
|
|
|
ctx,
|
2023-02-21 21:23:53 +13:00
|
|
|
userId: ctx.user._id!,
|
2022-02-15 07:11:35 +13:00
|
|
|
keepActiveSession: true,
|
|
|
|
})
|
|
|
|
}
|
2022-03-22 06:13:16 +13:00
|
|
|
|
2022-02-15 07:11:35 +13:00
|
|
|
ctx.body = {
|
2023-02-21 21:23:53 +13:00
|
|
|
_id: user._id!,
|
|
|
|
_rev: user._rev!,
|
2022-04-12 23:34:36 +12:00
|
|
|
}
|
2022-02-15 07:11:35 +13:00
|
|
|
}
|