1
0
Fork 0
mirror of synced 2024-06-28 11:00:55 +12:00
budibase/packages/worker/src/api/controllers/global/self.ts
2024-03-15 16:52:38 +00:00

198 lines
4.7 KiB
TypeScript

import * as userSdk from "../../../sdk/users"
import {
featureFlags,
tenancy,
db as dbCore,
utils,
encryption,
auth as authCore,
} from "@budibase/backend-core"
import env from "../../../environment"
import { groups } from "@budibase/pro"
import {
UpdateSelfRequest,
UpdateSelfResponse,
User,
UserCtx,
} from "@budibase/types"
const { newid } = utils
function newTestApiKey() {
return env.ENCRYPTED_TEST_PUBLIC_API_KEY
}
function newApiKey() {
return encryption.encrypt(
`${tenancy.getTenantId()}${dbCore.SEPARATOR}${newid()}`
)
}
function cleanupDevInfo(info: any) {
// user doesn't need to aware of dev doc info
delete info._id
delete info._rev
return info
}
export async function generateAPIKey(ctx: any) {
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()
}
const db = tenancy.getGlobalDB()
const id = dbCore.generateDevInfoID(userId)
let devInfo
try {
devInfo = await db.get<any>(id)
} catch (err) {
devInfo = { _id: id, userId }
}
devInfo.apiKey = apiKey
await db.put(devInfo)
ctx.body = cleanupDevInfo(devInfo)
}
export async function fetchAPIKey(ctx: any) {
const db = tenancy.getGlobalDB()
const id = dbCore.generateDevInfoID(ctx.user._id)
let devInfo
try {
devInfo = await db.get(id)
} catch (err) {
devInfo = {
_id: id,
userId: ctx.user._id,
apiKey: newApiKey(),
}
await db.put(devInfo)
}
ctx.body = cleanupDevInfo(devInfo)
}
/**
* Add the attributes that are session based to the current user.
*/
const addSessionAttributesToUser = (ctx: any) => {
ctx.body.account = ctx.user.account
ctx.body.license = ctx.user.license
ctx.body.budibaseAccess = !!ctx.user.budibaseAccess
ctx.body.accountPortalAccess = !!ctx.user.accountPortalAccess
ctx.body.csrfToken = ctx.user.csrfToken
}
export async function getSelf(ctx: any) {
if (!ctx.user) {
ctx.throw(403, "User not logged in")
}
const userId = ctx.user._id
ctx.params = {
id: userId,
}
// Adjust creators quotas (prevents wrong creators count if user has changed the plan)
await groups.adjustGroupCreatorsQuotas()
// get the main body of the user
const user = await userSdk.db.getUser(userId)
ctx.body = await groups.enrichUserRolesFromGroups(user)
// add the feature flags for this tenant
const tenantId = tenancy.getTenantId()
ctx.body.featureFlags = featureFlags.getTenantFeatureFlags(tenantId)
addSessionAttributesToUser(ctx)
}
export const syncAppFavourites = async (processedAppIds: string[]) => {
if (processedAppIds.length === 0) {
return []
}
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)
return apps?.reduce((acc: string[], app) => {
const id = app.appId.replace(appPrefix, "")
if (processedAppIds.includes(id)) {
acc.push(id)
}
return acc
}, [])
}
export const fetchAppsByIds = async (
processedAppIds: string[],
appPrefix: string
) => {
return await dbCore.getAppsByIDs(
processedAppIds.map(appId => {
return `${appPrefix}${appId}`
})
)
}
const processUserAppFavourites = async (
user: User,
update: UpdateSelfRequest
) => {
if (!("appFavourites" in update)) {
// Ignore requests without an explicit update to favourites.
return
}
const userAppFavourites = user.appFavourites || []
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
}
// Clean up the request by purging apps that no longer exist.
const syncedAppFavourites = await syncAppFavourites([...requestAppFavourites])
return syncedAppFavourites
}
export async function updateSelf(
ctx: UserCtx<UpdateSelfRequest, UpdateSelfResponse>
) {
const update = ctx.request.body
let user = await userSdk.db.getUser(ctx.user._id!)
const updatedAppFavourites = await processUserAppFavourites(user, update)
user = {
...user,
...update,
...(updatedAppFavourites ? { appFavourites: updatedAppFavourites } : {}),
}
user = await userSdk.db.save(user, { requirePassword: false })
if (update.password) {
// Log all other sessions out apart from the current one
await authCore.platformLogout({
ctx,
userId: ctx.user._id!,
keepActiveSession: true,
})
}
ctx.body = {
_id: user._id!,
_rev: user._rev!,
}
}