From a5d0b8c74b8b9b146e9480d891b03a000f86d626 Mon Sep 17 00:00:00 2001 From: Peter Clement Date: Fri, 22 Jul 2022 10:12:16 +0100 Subject: [PATCH] fixing bug on multi tenant environment --- .../src/pages/builder/apps/index.svelte | 10 ++-- .../overview/_components/AccessTab.svelte | 48 +++++++++++-------- .../_components/AssignmentModal.svelte | 2 + .../overview/_components/OverviewTab.svelte | 4 +- packages/builder/src/stores/portal/groups.js | 11 +---- .../src/middleware/tests/currentapp.spec.js | 11 +++++ packages/server/src/utilities/global.js | 3 ++ packages/worker/src/sdk/users/users.ts | 24 ++++++---- 8 files changed, 68 insertions(+), 45 deletions(-) diff --git a/packages/builder/src/pages/builder/apps/index.svelte b/packages/builder/src/pages/builder/apps/index.svelte index 6c18e229b5..b358e3bde0 100644 --- a/packages/builder/src/pages/builder/apps/index.svelte +++ b/packages/builder/src/pages/builder/apps/index.svelte @@ -45,19 +45,23 @@ $: publishedApps = $apps.filter(publishedAppsOnly) $: { - if (!Object.keys($auth.user?.roles).length) { + if (!Object.keys($auth.user?.roles).length && $auth.user?.userGroups) { userApps = $auth.user?.builder?.global ? publishedApps : publishedApps.filter(app => { return userGroups.find(group => { - return Object.keys(group.roles).includes(app.appId) + return Object.keys(group.roles) + .map(role => apps.extractAppId(role)) + .includes(app.appId) }) }) } else { userApps = $auth.user?.builder?.global ? publishedApps : publishedApps.filter(app => - Object.keys($auth.user?.roles).includes(app.appId) + Object.keys($auth.user?.roles) + .map(x => apps.extractAppId(x)) + .includes(app.appId) ) } } diff --git a/packages/builder/src/pages/builder/portal/overview/_components/AccessTab.svelte b/packages/builder/src/pages/builder/portal/overview/_components/AccessTab.svelte index 4181574e6d..5ea9f2784e 100644 --- a/packages/builder/src/pages/builder/portal/overview/_components/AccessTab.svelte +++ b/packages/builder/src/pages/builder/portal/overview/_components/AccessTab.svelte @@ -21,28 +21,33 @@ import { roles } from "stores/backend" export let app - $: console.log(app._id) let assignmentModal let appGroups = [] let appUsers = [] let prevSearch = undefined, search = undefined let pageInfo = createPaginationStore() - + let fixedAppId $: page = $pageInfo.page $: fetchUsers(page, search) - + $: console.log(app) $: hasGroupsLicense = $auth.user?.license.features.includes( Constants.Features.USER_GROUPS ) + $: { + if (!app.tenantId) { + fixedAppId = `app_${app.appId}` + } else { + fixedAppId = `app_${app.tenantId}_${app.appId}` + } + } $: appUsers = $users.data?.filter(x => { return Object.keys(x.roles).find(y => { - return y === app.appId + return y === fixedAppId }) }) || [] - $: appGroups = $groups.filter(x => { return x.apps.find(y => { return y.appId === app.appId @@ -58,7 +63,7 @@ return group._id === data.id }) matchedGroup.apps.push(app) - matchedGroup.roles[app.appId] = data.role + matchedGroup.roles[fixedAppId] = data.role groups.actions.save(matchedGroup) } else if (data.id.startsWith(us_prefix)) { @@ -68,35 +73,36 @@ let newUser = { ...matchedUser, - roles: { [app.appId]: data.role, ...matchedUser.roles }, + roles: { [fixedAppId]: data.role, ...matchedUser.roles }, } - await users.save(newUser) + await users.save(newUser, { opts: { appId: fixedAppId } }) + await fetchUsers(page, search) } }) await groups.actions.init() - await users.search({ page, appId: app.appId }) } async function removeUser(user) { // Remove the user role const filteredRoles = { ...user.roles } - delete filteredRoles[app?.appId] + delete filteredRoles[fixedAppId] await users.save({ ...user, roles: { ...filteredRoles, }, }) - await users.search({ page, appId: app.appId }) + await fetchUsers(page, search) } async function removeGroup(group) { // Remove the user role - - let filteredApps = group.apps.filter(x => x.appId !== app.appId) + let filteredApps = group.apps.filter( + x => apps.extractAppId(x) !== app.appId + ) const filteredRoles = { ...group.roles } - delete filteredRoles[app?.appId] + delete filteredRoles[fixedAppId] await groups.actions.save({ ...group, @@ -104,16 +110,16 @@ roles: { ...filteredRoles }, }) - await users.search({ page, appId: app.appId }) + await fetchUsers(page, search) } async function updateUserRole(role, user) { - user.roles[app.appId] = role + user.roles[fixedAppId] = role users.save(user) } async function updateGroupRole(role, group) { - group.roles[app.appId] = role + group.roles[fixedAppId] = role groups.actions.save(group) } @@ -129,7 +135,7 @@ prevSearch = search try { pageInfo.loading() - await users.search({ page, appId: app.appId }) + await users.search({ page, appId: fixedAppId }) pageInfo.fetched($users.hasNextPage, $users.nextPage) } catch (error) { notifications.error("Error getting user list") @@ -142,7 +148,7 @@ await apps.load() await roles.fetch() } catch (error) { - notifications.error("Error") + notifications.error(error) } }) @@ -174,7 +180,7 @@ autoWidth quiet value={group.roles[ - Object.keys(group.roles).find(x => x === app.appId) + Object.keys(group.roles).find(x => x === fixedAppId) ]} /> x === app.appId) + Object.keys(user.roles).find(x => x === fixedAppId) ]} /> { - await users.search({ page: undefined, appId: app.appId }) + await users.search({ page: undefined, appId: "app_" + app.appId }) }) diff --git a/packages/builder/src/stores/portal/groups.js b/packages/builder/src/stores/portal/groups.js index e9fefd21a8..ca814ac057 100644 --- a/packages/builder/src/stores/portal/groups.js +++ b/packages/builder/src/stores/portal/groups.js @@ -4,16 +4,7 @@ import { auth } from "stores/portal" import { Constants } from "@budibase/frontend-core" export function createGroupsStore() { - const DEFAULT_CONFIG = { - name: "", - icon: "", - color: "", - users: [], - apps: [], - roles: {}, - } - - const store = writable([DEFAULT_CONFIG]) + const store = writable([]) const actions = { init: async () => { diff --git a/packages/server/src/middleware/tests/currentapp.spec.js b/packages/server/src/middleware/tests/currentapp.spec.js index 85447581cc..57c21b2107 100644 --- a/packages/server/src/middleware/tests/currentapp.spec.js +++ b/packages/server/src/middleware/tests/currentapp.spec.js @@ -1,5 +1,6 @@ mockAuthWithNoCookie() mockWorker() +mockUserGroups() jest.mock("@budibase/backend-core/db", () => { const coreDb = jest.requireActual("@budibase/backend-core/db") @@ -29,6 +30,16 @@ function mockReset() { mockWorker() } +function mockUserGroups() { + jest.mock("@budibase/pro", () => ({ + groups: { + getGroupRoleId: () => { + return "BASIC" + }, + }, + })) +} + function mockAuthWithNoCookie() { jest.resetModules() mockWorker() diff --git a/packages/server/src/utilities/global.js b/packages/server/src/utilities/global.js index 81c64b9cde..17b1f26eaf 100644 --- a/packages/server/src/utilities/global.js +++ b/packages/server/src/utilities/global.js @@ -15,6 +15,7 @@ const { getAppId } = require("@budibase/backend-core/context") const { groups } = require("@budibase/pro") exports.updateAppRole = async (user, { appId } = {}) => { + console.log(appId) appId = appId || getAppId() if (!user || !user.roles) { return user @@ -37,6 +38,8 @@ exports.updateAppRole = async (user, { appId } = {}) => { let roleId = await groups.getGroupRoleId(user, appId) user.roleId = roleId } + console.log(user.roleId) + delete user.roles return user } diff --git a/packages/worker/src/sdk/users/users.ts b/packages/worker/src/sdk/users/users.ts index 35a4083df9..73a80ae086 100644 --- a/packages/worker/src/sdk/users/users.ts +++ b/packages/worker/src/sdk/users/users.ts @@ -31,8 +31,9 @@ export const allUsers = async () => { export const paginatedUsers = async ({ page, - search, -}: { page?: string; search?: string } = {}) => { + email, + appId, +}: { page?: string; email?: string; appId?: string } = {}) => { const db = tenancy.getGlobalDB() // get one extra document, to have the next page const opts: any = { @@ -44,19 +45,24 @@ export const paginatedUsers = async ({ opts.startkey = page } // property specifies what to use for the page/anchor - let userList, property - // no search, query allDocs - if (!search) { + let userList, + property = "_id", + getKey + if (appId) { + userList = await usersCore.searchGlobalUsersByApp(appId, opts) + getKey = (doc: any) => usersCore.getGlobalUserByAppPage(appId, doc) + } else if (email) { + userList = await usersCore.searchGlobalUsersByEmail(email, opts) + property = "email" + } else { + // no search, query allDocs const response = await db.allDocs(dbUtils.getGlobalUserParams(null, opts)) userList = response.rows.map((row: any) => row.doc) - property = "_id" - } else { - userList = await usersCore.searchGlobalUsersByEmail(search, opts) - property = "email" } return dbUtils.pagination(userList, PAGE_LIMIT, { paginate: true, property, + getKey, }) }