Moving user admin/builder functions to shared-core for frontend to use.
This commit is contained in:
parent
91847504c8
commit
85dea47a31
|
@ -22,6 +22,7 @@
|
|||
"dependencies": {
|
||||
"@budibase/nano": "10.1.2",
|
||||
"@budibase/pouchdb-replication-stream": "1.2.10",
|
||||
"@budibase/shared-core": "0.0.0",
|
||||
"@budibase/types": "0.0.0",
|
||||
"@shopify/jest-koa-mocks": "5.0.1",
|
||||
"@techpass/passport-openidconnect": "0.3.2",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
export const SEPARATOR = "_"
|
||||
export const UNICODE_MAX = "\ufff0"
|
||||
import { prefixed, DocumentType } from "@budibase/types"
|
||||
export { SEPARATOR, UNICODE_MAX, DocumentType } from "@budibase/types"
|
||||
|
||||
/**
|
||||
* Can be used to create a few different forms of querying a view.
|
||||
|
@ -34,42 +34,6 @@ export enum InternalTable {
|
|||
USER_METADATA = "ta_users",
|
||||
}
|
||||
|
||||
export enum DocumentType {
|
||||
USER = "us",
|
||||
GROUP = "gr",
|
||||
WORKSPACE = "workspace",
|
||||
CONFIG = "config",
|
||||
TEMPLATE = "template",
|
||||
APP = "app",
|
||||
DEV = "dev",
|
||||
APP_DEV = "app_dev",
|
||||
APP_METADATA = "app_metadata",
|
||||
ROLE = "role",
|
||||
MIGRATIONS = "migrations",
|
||||
DEV_INFO = "devinfo",
|
||||
AUTOMATION_LOG = "log_au",
|
||||
ACCOUNT_METADATA = "acc_metadata",
|
||||
PLUGIN = "plg",
|
||||
DATASOURCE = "datasource",
|
||||
DATASOURCE_PLUS = "datasource_plus",
|
||||
APP_BACKUP = "backup",
|
||||
TABLE = "ta",
|
||||
ROW = "ro",
|
||||
AUTOMATION = "au",
|
||||
LINK = "li",
|
||||
WEBHOOK = "wh",
|
||||
INSTANCE = "inst",
|
||||
LAYOUT = "layout",
|
||||
SCREEN = "screen",
|
||||
QUERY = "query",
|
||||
DEPLOYMENTS = "deployments",
|
||||
METADATA = "metadata",
|
||||
MEM_VIEW = "view",
|
||||
USER_FLAG = "flag",
|
||||
AUTOMATION_METADATA = "meta_au",
|
||||
AUDIT_LOG = "al",
|
||||
}
|
||||
|
||||
export const StaticDatabases = {
|
||||
GLOBAL: {
|
||||
name: "global-db",
|
||||
|
@ -93,7 +57,7 @@ export const StaticDatabases = {
|
|||
},
|
||||
}
|
||||
|
||||
export const APP_PREFIX = DocumentType.APP + SEPARATOR
|
||||
export const APP_DEV = DocumentType.APP_DEV + SEPARATOR
|
||||
export const APP_PREFIX = prefixed(DocumentType.APP)
|
||||
export const APP_DEV = prefixed(DocumentType.APP_DEV)
|
||||
export const APP_DEV_PREFIX = APP_DEV
|
||||
export const BUDIBASE_DATASOURCE_TYPE = "budibase"
|
||||
|
|
|
@ -18,6 +18,7 @@ import {
|
|||
User,
|
||||
ContextUser,
|
||||
} from "@budibase/types"
|
||||
import { sdk } from "@budibase/shared-core"
|
||||
import { getGlobalDB } from "./context"
|
||||
import * as context from "./context"
|
||||
|
||||
|
@ -38,6 +39,12 @@ function removeUserPassword(users: User | User[]) {
|
|||
return users
|
||||
}
|
||||
|
||||
// extract from shared-core to make easily accessible from backend-core
|
||||
export const isBuilder = sdk.users.isBuilder
|
||||
export const isAdmin = sdk.users.isAdmin
|
||||
export const hasAdminPermissions = sdk.users.hasAdminPermissions
|
||||
export const hasBuilderPermissions = sdk.users.hasBuilderPermissions
|
||||
|
||||
export const bulkGetGlobalUsersById = async (
|
||||
userIds: string[],
|
||||
opts?: GetOpts
|
||||
|
@ -254,39 +261,6 @@ export async function getUserCount() {
|
|||
return response.total_rows
|
||||
}
|
||||
|
||||
// checks if a user is specifically a builder, given an app ID
|
||||
export function isBuilder(user: User | ContextUser, appId?: string) {
|
||||
if (user.builder?.global) {
|
||||
return true
|
||||
} else if (appId && user.builder?.apps?.includes(getProdAppID(appId))) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// alias for hasAdminPermission, currently do the same thing
|
||||
// in future whether someone has admin permissions and whether they are
|
||||
// an admin for a specific resource could be separated
|
||||
export function isAdmin(user: User | ContextUser) {
|
||||
return hasAdminPermissions(user)
|
||||
}
|
||||
|
||||
// checks if a user is capable of building any app
|
||||
export function hasBuilderPermissions(user?: User | ContextUser) {
|
||||
if (!user) {
|
||||
return false
|
||||
}
|
||||
return user.builder?.global || user.builder?.apps?.length !== 0
|
||||
}
|
||||
|
||||
// checks if a user is capable of being an admin
|
||||
export function hasAdminPermissions(user?: User | ContextUser) {
|
||||
if (!user) {
|
||||
return false
|
||||
}
|
||||
return user.admin?.global
|
||||
}
|
||||
|
||||
// used to remove the builder/admin permissions, for processing the
|
||||
// user as an app user (they may have some specific role/group
|
||||
export function removePortalUserPermissions(user: User | ContextUser) {
|
||||
|
|
|
@ -24,7 +24,7 @@ export default async (ctx: UserCtx, next: any) => {
|
|||
if (
|
||||
isDevAppID(requestAppId) &&
|
||||
!isWebhookEndpoint(ctx) &&
|
||||
(!ctx.user || !ctx.user.builder || !ctx.user.builder.global)
|
||||
!users.isBuilder(ctx.user, requestAppId)
|
||||
) {
|
||||
return ctx.redirect("/")
|
||||
}
|
||||
|
@ -70,7 +70,6 @@ export default async (ctx: UserCtx, next: any) => {
|
|||
}
|
||||
|
||||
return context.doInAppContext(appId, async () => {
|
||||
let skipCookie = false
|
||||
// if the user not in the right tenant then make sure they have no permissions
|
||||
// need to judge this only based on the request app ID,
|
||||
if (
|
||||
|
@ -83,7 +82,6 @@ export default async (ctx: UserCtx, next: any) => {
|
|||
ctx.user = users.cleanseUserObject(ctx.user) as ContextUser
|
||||
ctx.isAuthenticated = false
|
||||
roleId = roles.BUILTIN_ROLE_IDS.PUBLIC
|
||||
skipCookie = true
|
||||
}
|
||||
|
||||
ctx.appId = appId
|
||||
|
|
|
@ -2,3 +2,4 @@ export * from "./constants"
|
|||
export * as dataFilters from "./filters"
|
||||
export * as helpers from "./helpers"
|
||||
export * as utils from "./utils"
|
||||
export * as sdk from "./sdk"
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
import { DocumentType, prefixed } from "@budibase/types"
|
||||
|
||||
const APP_PREFIX = prefixed(DocumentType.APP)
|
||||
const APP_DEV_PREFIX = prefixed(DocumentType.APP_DEV)
|
||||
|
||||
export function getDevAppID(appId: string) {
|
||||
if (!appId || appId.startsWith(APP_DEV_PREFIX)) {
|
||||
return appId
|
||||
}
|
||||
// split to take off the app_ element, then join it together incase any other app_ exist
|
||||
const split = appId.split(APP_PREFIX)
|
||||
split.shift()
|
||||
const rest = split.join(APP_PREFIX)
|
||||
return `${APP_DEV_PREFIX}${rest}`
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a development app ID to a deployed app ID.
|
||||
*/
|
||||
export function getProdAppID(appId: string) {
|
||||
if (!appId || !appId.startsWith(APP_DEV_PREFIX)) {
|
||||
return appId
|
||||
}
|
||||
// split to take off the app_dev element, then join it together incase any other app_ exist
|
||||
const split = appId.split(APP_DEV_PREFIX)
|
||||
split.shift()
|
||||
const rest = split.join(APP_DEV_PREFIX)
|
||||
return `${APP_PREFIX}${rest}`
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
export * as applications from "./applications"
|
||||
export * as users from "./users"
|
|
@ -0,0 +1,35 @@
|
|||
import { ContextUser, User } from "@budibase/types"
|
||||
import { getProdAppID } from "./applications"
|
||||
|
||||
// checks if a user is specifically a builder, given an app ID
|
||||
export function isBuilder(user: User | ContextUser, appId?: string) {
|
||||
if (user.builder?.global) {
|
||||
return true
|
||||
} else if (appId && user.builder?.apps?.includes(getProdAppID(appId))) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// alias for hasAdminPermission, currently do the same thing
|
||||
// in future whether someone has admin permissions and whether they are
|
||||
// an admin for a specific resource could be separated
|
||||
export function isAdmin(user: User | ContextUser) {
|
||||
return hasAdminPermissions(user)
|
||||
}
|
||||
|
||||
// checks if a user is capable of building any app
|
||||
export function hasBuilderPermissions(user?: User | ContextUser) {
|
||||
if (!user) {
|
||||
return false
|
||||
}
|
||||
return user.builder?.global || user.builder?.apps?.length !== 0
|
||||
}
|
||||
|
||||
// checks if a user is capable of being an admin
|
||||
export function hasAdminPermissions(user?: User | ContextUser) {
|
||||
if (!user) {
|
||||
return false
|
||||
}
|
||||
return user.admin?.global
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
export * from "./documents"
|
|
@ -1,3 +1,44 @@
|
|||
export const SEPARATOR = "_"
|
||||
export const UNICODE_MAX = "\ufff0"
|
||||
|
||||
export const prefixed = (type: DocumentType) => `${type}${SEPARATOR}`
|
||||
|
||||
export enum DocumentType {
|
||||
USER = "us",
|
||||
GROUP = "gr",
|
||||
WORKSPACE = "workspace",
|
||||
CONFIG = "config",
|
||||
TEMPLATE = "template",
|
||||
APP = "app",
|
||||
DEV = "dev",
|
||||
APP_DEV = "app_dev",
|
||||
APP_METADATA = "app_metadata",
|
||||
ROLE = "role",
|
||||
MIGRATIONS = "migrations",
|
||||
DEV_INFO = "devinfo",
|
||||
AUTOMATION_LOG = "log_au",
|
||||
ACCOUNT_METADATA = "acc_metadata",
|
||||
PLUGIN = "plg",
|
||||
DATASOURCE = "datasource",
|
||||
DATASOURCE_PLUS = "datasource_plus",
|
||||
APP_BACKUP = "backup",
|
||||
TABLE = "ta",
|
||||
ROW = "ro",
|
||||
AUTOMATION = "au",
|
||||
LINK = "li",
|
||||
WEBHOOK = "wh",
|
||||
INSTANCE = "inst",
|
||||
LAYOUT = "layout",
|
||||
SCREEN = "screen",
|
||||
QUERY = "query",
|
||||
DEPLOYMENTS = "deployments",
|
||||
METADATA = "metadata",
|
||||
MEM_VIEW = "view",
|
||||
USER_FLAG = "flag",
|
||||
AUTOMATION_METADATA = "meta_au",
|
||||
AUDIT_LOG = "al",
|
||||
}
|
||||
|
||||
export interface Document {
|
||||
_id?: string
|
||||
_rev?: string
|
||||
|
|
|
@ -176,7 +176,7 @@ const validateUniqueUser = async (email: string, tenantId: string) => {
|
|||
export async function isPreventPasswordActions(user: User, account?: Account) {
|
||||
// when in maintenance mode we allow sso users with the admin role
|
||||
// to perform any password action - this prevents lockout
|
||||
if (coreEnv.ENABLE_SSO_MAINTENANCE_MODE && user.admin?.global) {
|
||||
if (coreEnv.ENABLE_SSO_MAINTENANCE_MODE && usersCore.isAdmin(user)) {
|
||||
return false
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue