Updates to improve the view development experience.
This commit is contained in:
parent
4dc24b7559
commit
34771e1ef7
|
@ -20,6 +20,7 @@ export enum ViewName {
|
|||
AUTOMATION_LOGS = "automation_logs",
|
||||
ACCOUNT_BY_EMAIL = "account_by_email",
|
||||
PLATFORM_USERS_LOWERCASE = "platform_users_lowercase",
|
||||
USER_BY_GROUP = "by_group_user",
|
||||
}
|
||||
|
||||
export const DeprecatedViews = {
|
||||
|
|
|
@ -3,7 +3,7 @@ import { DEFAULT_TENANT_ID, Configs } from "../constants"
|
|||
import env from "../environment"
|
||||
import { SEPARATOR, DocumentType, UNICODE_MAX, ViewName } from "./constants"
|
||||
import { getTenantId, getGlobalDB } from "../context"
|
||||
import { getGlobalDBName } from "../tenancy/utils"
|
||||
import { getGlobalDBName } from "../tenancy"
|
||||
import fetch from "node-fetch"
|
||||
import { doWithDB, allDbs } from "./index"
|
||||
import { getCouchInfo } from "./pouch"
|
||||
|
|
|
@ -36,154 +36,91 @@ async function removeDeprecated(db: PouchDB.Database, viewName: ViewName) {
|
|||
}
|
||||
}
|
||||
|
||||
export const createNewUserEmailView = async () => {
|
||||
const db = getGlobalDB()
|
||||
export async function createView(db: any, viewJs: string, viewName: string) {
|
||||
let designDoc
|
||||
try {
|
||||
designDoc = await db.get(DESIGN_DB)
|
||||
designDoc = (await db.get(DESIGN_DB)) as DesignDocument
|
||||
} catch (err) {
|
||||
// no design doc, make one
|
||||
designDoc = DesignDoc()
|
||||
}
|
||||
const view = {
|
||||
// if using variables in a map function need to inject them before use
|
||||
map: `function(doc) {
|
||||
if (doc._id.startsWith("${DocumentType.USER}${SEPARATOR}")) {
|
||||
emit(doc.email.toLowerCase(), doc._id)
|
||||
}
|
||||
}`,
|
||||
map: viewJs,
|
||||
}
|
||||
designDoc.views = {
|
||||
...designDoc.views,
|
||||
[ViewName.USER_BY_EMAIL]: view,
|
||||
[viewName]: view,
|
||||
}
|
||||
await db.put(designDoc)
|
||||
}
|
||||
|
||||
export const createAccountEmailView = async () => {
|
||||
await doWithDB(
|
||||
StaticDatabases.PLATFORM_INFO.name,
|
||||
async (db: PouchDB.Database) => {
|
||||
let designDoc
|
||||
try {
|
||||
designDoc = await db.get<DesignDocument>(DESIGN_DB)
|
||||
} catch (err) {
|
||||
// no design doc, make one
|
||||
designDoc = DesignDoc()
|
||||
export const createNewUserEmailView = async () => {
|
||||
const db = getGlobalDB()
|
||||
const viewJs = `function(doc) {
|
||||
if (doc._id.startsWith("${DocumentType.USER}${SEPARATOR}")) {
|
||||
emit(doc.email.toLowerCase(), doc._id)
|
||||
}
|
||||
const view = {
|
||||
// if using variables in a map function need to inject them before use
|
||||
map: `function(doc) {
|
||||
}`
|
||||
await createView(db, viewJs, ViewName.USER_BY_EMAIL)
|
||||
}
|
||||
|
||||
export const createAccountEmailView = async () => {
|
||||
const viewJs = `function(doc) {
|
||||
if (doc._id.startsWith("${DocumentType.ACCOUNT_METADATA}${SEPARATOR}")) {
|
||||
emit(doc.email.toLowerCase(), doc._id)
|
||||
}
|
||||
}`,
|
||||
}
|
||||
designDoc.views = {
|
||||
...designDoc.views,
|
||||
[ViewName.ACCOUNT_BY_EMAIL]: view,
|
||||
}
|
||||
await db.put(designDoc)
|
||||
}`
|
||||
await doWithDB(
|
||||
StaticDatabases.PLATFORM_INFO.name,
|
||||
async (db: PouchDB.Database) => {
|
||||
await createView(db, viewJs, ViewName.ACCOUNT_BY_EMAIL)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
export const createUserAppView = async () => {
|
||||
const db = getGlobalDB() as PouchDB.Database
|
||||
let designDoc
|
||||
try {
|
||||
designDoc = await db.get<DesignDocument>("_design/database")
|
||||
} catch (err) {
|
||||
// no design doc, make one
|
||||
designDoc = DesignDoc()
|
||||
}
|
||||
const view = {
|
||||
// if using variables in a map function need to inject them before use
|
||||
map: `function(doc) {
|
||||
const viewJs = `function(doc) {
|
||||
if (doc._id.startsWith("${DocumentType.USER}${SEPARATOR}") && doc.roles) {
|
||||
for (let prodAppId of Object.keys(doc.roles)) {
|
||||
let emitted = prodAppId + "${SEPARATOR}" + doc._id
|
||||
emit(emitted, null)
|
||||
}
|
||||
}
|
||||
}`,
|
||||
}
|
||||
designDoc.views = {
|
||||
...designDoc.views,
|
||||
[ViewName.USER_BY_APP]: view,
|
||||
}
|
||||
await db.put(designDoc)
|
||||
}`
|
||||
await createView(db, viewJs, ViewName.USER_BY_APP)
|
||||
}
|
||||
|
||||
export const createApiKeyView = async () => {
|
||||
const db = getGlobalDB()
|
||||
let designDoc
|
||||
try {
|
||||
designDoc = await db.get("_design/database")
|
||||
} catch (err) {
|
||||
designDoc = DesignDoc()
|
||||
}
|
||||
const view = {
|
||||
map: `function(doc) {
|
||||
const viewJs = `function(doc) {
|
||||
if (doc._id.startsWith("${DocumentType.DEV_INFO}") && doc.apiKey) {
|
||||
emit(doc.apiKey, doc.userId)
|
||||
}
|
||||
}`,
|
||||
}
|
||||
designDoc.views = {
|
||||
...designDoc.views,
|
||||
[ViewName.BY_API_KEY]: view,
|
||||
}
|
||||
await db.put(designDoc)
|
||||
}`
|
||||
await createView(db, viewJs, ViewName.BY_API_KEY)
|
||||
}
|
||||
|
||||
export const createUserBuildersView = async () => {
|
||||
const db = getGlobalDB()
|
||||
let designDoc
|
||||
try {
|
||||
designDoc = await db.get("_design/database")
|
||||
} catch (err) {
|
||||
// no design doc, make one
|
||||
designDoc = DesignDoc()
|
||||
}
|
||||
const view = {
|
||||
map: `function(doc) {
|
||||
const viewJs = `function(doc) {
|
||||
if (doc.builder && doc.builder.global === true) {
|
||||
emit(doc._id, doc._id)
|
||||
}
|
||||
}`,
|
||||
}
|
||||
designDoc.views = {
|
||||
...designDoc.views,
|
||||
[ViewName.USER_BY_BUILDERS]: view,
|
||||
}
|
||||
await db.put(designDoc)
|
||||
}`
|
||||
await createView(db, viewJs, ViewName.USER_BY_BUILDERS)
|
||||
}
|
||||
|
||||
export const createPlatformUserView = async () => {
|
||||
await doWithDB(
|
||||
StaticDatabases.PLATFORM_INFO.name,
|
||||
async (db: PouchDB.Database) => {
|
||||
let designDoc
|
||||
try {
|
||||
designDoc = await db.get<DesignDocument>(DESIGN_DB)
|
||||
} catch (err) {
|
||||
// no design doc, make one
|
||||
designDoc = DesignDoc()
|
||||
}
|
||||
const view = {
|
||||
// if using variables in a map function need to inject them before use
|
||||
map: `function(doc) {
|
||||
const viewJs = `function(doc) {
|
||||
if (doc.tenantId) {
|
||||
emit(doc._id.toLowerCase(), doc._id)
|
||||
}
|
||||
}`,
|
||||
}
|
||||
designDoc.views = {
|
||||
...designDoc.views,
|
||||
[ViewName.PLATFORM_USERS_LOWERCASE]: view,
|
||||
}
|
||||
await db.put(designDoc)
|
||||
}`
|
||||
await doWithDB(
|
||||
StaticDatabases.PLATFORM_INFO.name,
|
||||
async (db: PouchDB.Database) => {
|
||||
await createView(db, viewJs, ViewName.PLATFORM_USERS_LOWERCASE)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
@ -196,7 +133,7 @@ export const queryView = async <T>(
|
|||
viewName: ViewName,
|
||||
params: PouchDB.Query.Options<T, T>,
|
||||
db: PouchDB.Database,
|
||||
CreateFuncByName: any,
|
||||
createFunc: any,
|
||||
opts?: QueryViewOptions
|
||||
): Promise<T[] | T | undefined> => {
|
||||
try {
|
||||
|
@ -213,10 +150,9 @@ export const queryView = async <T>(
|
|||
}
|
||||
} catch (err: any) {
|
||||
if (err != null && err.name === "not_found") {
|
||||
const createFunc = CreateFuncByName[viewName]
|
||||
await removeDeprecated(db, viewName)
|
||||
await createFunc()
|
||||
return queryView(viewName, params, db, CreateFuncByName, opts)
|
||||
return queryView(viewName, params, db, createFunc, opts)
|
||||
} else {
|
||||
throw err
|
||||
}
|
||||
|
@ -228,7 +164,7 @@ export const queryPlatformView = async <T>(
|
|||
params: PouchDB.Query.Options<T, T>,
|
||||
opts?: QueryViewOptions
|
||||
): Promise<T[] | T | undefined> => {
|
||||
const CreateFuncByName = {
|
||||
const CreateFuncByName: any = {
|
||||
[ViewName.ACCOUNT_BY_EMAIL]: createAccountEmailView,
|
||||
[ViewName.PLATFORM_USERS_LOWERCASE]: createPlatformUserView,
|
||||
}
|
||||
|
@ -236,7 +172,8 @@ export const queryPlatformView = async <T>(
|
|||
return doWithDB(
|
||||
StaticDatabases.PLATFORM_INFO.name,
|
||||
async (db: PouchDB.Database) => {
|
||||
return queryView(viewName, params, db, CreateFuncByName, opts)
|
||||
const createFn = CreateFuncByName[viewName]
|
||||
return queryView(viewName, params, db, createFn, opts)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
@ -247,7 +184,7 @@ export const queryGlobalView = async <T>(
|
|||
db?: PouchDB.Database,
|
||||
opts?: QueryViewOptions
|
||||
): Promise<T[] | T | undefined> => {
|
||||
const CreateFuncByName = {
|
||||
const CreateFuncByName: any = {
|
||||
[ViewName.USER_BY_EMAIL]: createNewUserEmailView,
|
||||
[ViewName.BY_API_KEY]: createApiKeyView,
|
||||
[ViewName.USER_BY_BUILDERS]: createUserBuildersView,
|
||||
|
@ -257,5 +194,6 @@ export const queryGlobalView = async <T>(
|
|||
if (!db) {
|
||||
db = getGlobalDB() as PouchDB.Database
|
||||
}
|
||||
return queryView(viewName, params, db, CreateFuncByName, opts)
|
||||
const createFn = CreateFuncByName[viewName]
|
||||
return queryView(viewName, params, db, createFn, opts)
|
||||
}
|
||||
|
|
|
@ -1,15 +1,12 @@
|
|||
import { auth } from "../stores/portal"
|
||||
import { get } from "svelte/store"
|
||||
|
||||
export const FEATURE_FLAGS = {
|
||||
export const TENANT_FEATURE_FLAGS = {
|
||||
LICENSING: "LICENSING",
|
||||
USER_GROUPS: "USER_GROUPS",
|
||||
}
|
||||
|
||||
export const isEnabled = featureFlag => {
|
||||
const user = get(auth).user
|
||||
if (user?.featureFlags?.includes(featureFlag)) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
return !!user?.featureFlags?.includes(featureFlag)
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
import ChangePasswordModal from "components/settings/ChangePasswordModal.svelte"
|
||||
import UpdateAPIKeyModal from "components/settings/UpdateAPIKeyModal.svelte"
|
||||
import Logo from "assets/bb-emblem.svg"
|
||||
import { isEnabled, FEATURE_FLAGS } from "../../../helpers/featureFlags"
|
||||
import { isEnabled, TENANT_FEATURE_FLAGS } from "helpers/featureFlags"
|
||||
|
||||
let loaded = false
|
||||
let userInfoModal
|
||||
|
@ -44,7 +44,7 @@
|
|||
href: "/builder/portal/manage/users",
|
||||
heading: "Manage",
|
||||
},
|
||||
isEnabled(FEATURE_FLAGS.USER_GROUPS)
|
||||
isEnabled(TENANT_FEATURE_FLAGS.USER_GROUPS)
|
||||
? {
|
||||
title: "User Groups",
|
||||
href: "/builder/portal/manage/groups",
|
||||
|
@ -103,7 +103,7 @@
|
|||
])
|
||||
}
|
||||
|
||||
if (isEnabled(FEATURE_FLAGS.LICENSING)) {
|
||||
if (isEnabled(TENANT_FEATURE_FLAGS.LICENSING)) {
|
||||
// always show usage in self-host or cloud if licensing enabled
|
||||
menu = menu.concat([
|
||||
{
|
||||
|
|
|
@ -2,7 +2,7 @@ import { derived, writable, get } from "svelte/store"
|
|||
import { API } from "api"
|
||||
import { admin } from "stores/portal"
|
||||
import analytics from "analytics"
|
||||
import { FEATURE_FLAGS } from "helpers/featureFlags"
|
||||
import { TENANT_FEATURE_FLAGS } from "helpers/featureFlags"
|
||||
import { Constants } from "@budibase/frontend-core"
|
||||
|
||||
export function createAuthStore() {
|
||||
|
@ -35,7 +35,7 @@ export function createAuthStore() {
|
|||
isBuilder = !!user.builder?.global
|
||||
groupsEnabled =
|
||||
user?.license.features.includes(Constants.Features.USER_GROUPS) &&
|
||||
user?.featureFlags.includes(FEATURE_FLAGS.USER_GROUPS)
|
||||
user?.featureFlags.includes(TENANT_FEATURE_FLAGS.USER_GROUPS)
|
||||
}
|
||||
return {
|
||||
user: $store.user,
|
||||
|
|
Loading…
Reference in New Issue