diff --git a/.github/workflows/deploy-qa.yml b/.github/workflows/deploy-qa.yml index 2a30e44def5..92c957acbde 100644 --- a/.github/workflows/deploy-qa.yml +++ b/.github/workflows/deploy-qa.yml @@ -3,7 +3,7 @@ name: Deploy QA on: push: branches: - - v3-ui + - feature/automation-branching-ux workflow_dispatch: jobs: diff --git a/hosting/single/Dockerfile b/hosting/single/Dockerfile index a1230f3c37b..a243e8cddc6 100644 --- a/hosting/single/Dockerfile +++ b/hosting/single/Dockerfile @@ -22,7 +22,7 @@ RUN ./scripts/removeWorkspaceDependencies.sh packages/worker/package.json RUN jq 'del(.scripts.postinstall)' package.json > temp.json && mv temp.json package.json RUN ./scripts/removeWorkspaceDependencies.sh package.json -RUN --mount=type=cache,target=/root/.yarn YARN_CACHE_FOLDER=/root/.yarn yarn install --production --frozen-lockfile +RUN --mount=type=cache,target=/root/.yarn YARN_CACHE_FOLDER=/root/.yarn yarn install --production --frozen-lockfile --network-concurrency 1 # copy the actual code COPY packages/server/dist packages/server/dist diff --git a/packages/backend-core/src/security/roles.ts b/packages/backend-core/src/security/roles.ts index c14178cacb1..42a55c16c77 100644 --- a/packages/backend-core/src/security/roles.ts +++ b/packages/backend-core/src/security/roles.ts @@ -219,7 +219,10 @@ export function getBuiltinRole(roleId: string): Role | undefined { export function builtinRoleToNumber(id: string) { const builtins = getBuiltinRoles() const MAX = Object.values(builtins).length + 1 - if (id === BUILTIN_IDS.ADMIN || id === BUILTIN_IDS.BUILDER) { + if ( + compareRoleIds(id, BUILTIN_IDS.ADMIN) || + compareRoleIds(id, BUILTIN_IDS.BUILDER) + ) { return MAX } let role = builtins[id], @@ -256,7 +259,9 @@ export async function roleToNumber(id: string) { // find the built-in roles, get their number, sort it, then get the last one const highestBuiltin: number | undefined = role.inherits .map(roleId => { - const foundRole = hierarchy.find(role => role._id === roleId) + const foundRole = hierarchy.find(role => + compareRoleIds(role._id!, roleId) + ) if (foundRole) { return findNumber(foundRole) + 1 } @@ -380,7 +385,7 @@ async function getAllUserRoles( ): Promise { const allRoles = await getAllRoles() // admins have access to all roles - if (userRoleId === BUILTIN_IDS.ADMIN) { + if (compareRoleIds(userRoleId, BUILTIN_IDS.ADMIN)) { return allRoles } @@ -491,17 +496,21 @@ export async function getAllRoles(appId?: string): Promise { // need to combine builtin with any DB record of them (for sake of permissions) for (let builtinRoleId of externalBuiltinRoles) { const builtinRole = builtinRoles[builtinRoleId] - const dbBuiltin = roles.filter( - dbRole => - getExternalRoleID(dbRole._id!, dbRole.version) === builtinRoleId + const dbBuiltin = roles.filter(dbRole => + compareRoleIds(dbRole._id!, builtinRoleId) )[0] if (dbBuiltin == null) { roles.push(builtinRole || builtinRoles.BASIC) } else { // remove role and all back after combining with the builtin roles = roles.filter(role => role._id !== dbBuiltin._id) - dbBuiltin._id = getExternalRoleID(dbBuiltin._id!, dbBuiltin.version) - roles.push(Object.assign(builtinRole, dbBuiltin)) + dbBuiltin._id = getExternalRoleID(builtinRole._id!, dbBuiltin.version) + roles.push({ + ...builtinRole, + ...dbBuiltin, + name: builtinRole.name, + _id: getExternalRoleID(builtinRole._id!, builtinRole.version), + }) } } // check permissions @@ -544,9 +553,9 @@ export class AccessController { if ( tryingRoleId == null || tryingRoleId === "" || - tryingRoleId === userRoleId || - tryingRoleId === BUILTIN_IDS.BUILDER || - userRoleId === BUILTIN_IDS.BUILDER + compareRoleIds(tryingRoleId, BUILTIN_IDS.BUILDER) || + compareRoleIds(userRoleId!, tryingRoleId) || + compareRoleIds(userRoleId!, BUILTIN_IDS.BUILDER) ) { return true } diff --git a/packages/builder/src/pages/builder/app/[application]/settings/automations/index.svelte b/packages/builder/src/pages/builder/app/[application]/settings/automations/index.svelte index 6518b6cf58a..dd332c92a91 100644 --- a/packages/builder/src/pages/builder/app/[application]/settings/automations/index.svelte +++ b/packages/builder/src/pages/builder/app/[application]/settings/automations/index.svelte @@ -38,6 +38,10 @@ let loaded = false $: app = $appsStore.apps.find(app => $appStore.appId?.includes(app.appId)) $: licensePlan = $auth.user?.license?.plan + + // Reset the page every time that a filter gets updated + $: pageInfo.reset(), automationId, status, timeRange + $: page = $pageInfo.page $: fetchLogs(automationId, status, page, timeRange) $: isCloud = $admin.cloud diff --git a/packages/builder/src/pages/builder/portal/users/users/index.svelte b/packages/builder/src/pages/builder/portal/users/users/index.svelte index 5a7e334c9c6..9ecb42b6d35 100644 --- a/packages/builder/src/pages/builder/portal/users/users/index.svelte +++ b/packages/builder/src/pages/builder/portal/users/users/index.svelte @@ -71,7 +71,6 @@ ] let userData = [] let invitesLoaded = false - let tenantOwnerLoaded = false let pendingInvites = [] let parsedInvites = [] @@ -100,13 +99,9 @@ $: pendingSchema = getPendingSchema(schema) $: userData = [] $: inviteUsersResponse = { successful: [], unsuccessful: [] } - $: setEnrichedUsers($fetch.rows, tenantOwnerLoaded) + $: setEnrichedUsers($fetch.rows, tenantOwner) - const setEnrichedUsers = async rows => { - if (!tenantOwnerLoaded) { - enrichedUsers = [] - return - } + const setEnrichedUsers = async (rows, owner) => { enrichedUsers = rows?.map(user => { let userGroups = [] $groups.forEach(group => { @@ -118,7 +113,9 @@ }) } }) - user.tenantOwnerEmail = tenantOwner?.email + if (owner) { + user.tenantOwnerEmail = owner.email + } const role = Constants.ExtendedBudibaseRoleOptions.find( x => x.value === users.getUserRole(user) ) @@ -322,12 +319,21 @@ try { await groups.actions.init() groupsLoaded = true + } catch (error) { + notifications.error("Error fetching user group data") + } + try { pendingInvites = await users.getInvites() invitesLoaded = true + } catch (err) { + notifications.error("Error fetching user invitations") + } + try { tenantOwner = await users.getAccountHolder() - tenantOwnerLoaded = true - } catch (error) { - notifications.error("Error fetching user group data") + } catch (err) { + if (err.status !== 404) { + notifications.error("Error fetching account holder") + } } }) diff --git a/packages/client/src/components/app/forms/RelationshipField.svelte b/packages/client/src/components/app/forms/RelationshipField.svelte index a6d0564f7f4..1439902b264 100644 --- a/packages/client/src/components/app/forms/RelationshipField.svelte +++ b/packages/client/src/components/app/forms/RelationshipField.svelte @@ -113,7 +113,10 @@ $: debouncedFetchRows(searchTerm, primaryDisplay, defaultValue) const forceFetchRows = async () => { + // if the filter has changed, then we need to reset the options, clear the selection, and re-fetch + optionsObj = {} fieldApi?.setValue([]) + selectedValue = [] debouncedFetchRows(searchTerm, primaryDisplay, defaultValue) } const fetchRows = async (searchTerm, primaryDisplay, defaultVal) => { diff --git a/packages/frontend-core/src/fetch/UserFetch.js b/packages/frontend-core/src/fetch/UserFetch.js index cb2c045cc66..a68a3a06f40 100644 --- a/packages/frontend-core/src/fetch/UserFetch.js +++ b/packages/frontend-core/src/fetch/UserFetch.js @@ -32,7 +32,7 @@ export default class UserFetch extends DataFetch { const { cursor, query } = get(this.store) let finalQuery // convert old format to new one - we now allow use of the lucene format - const { appId, paginated, ...rest } = query + const { appId, paginated, ...rest } = query || {} if (!QueryUtils.hasFilters(query) && rest.email != null) { finalQuery = { string: { email: rest.email } } } else { diff --git a/packages/pro b/packages/pro index f6aebba9445..2ab8536b600 160000 --- a/packages/pro +++ b/packages/pro @@ -1 +1 @@ -Subproject commit f6aebba94451ce47bba551926e5ad72bd75f71c6 +Subproject commit 2ab8536b6005576684810d774f1ac22239218546 diff --git a/packages/server/Dockerfile b/packages/server/Dockerfile index 2206d49d9b7..8dec5b67719 100644 --- a/packages/server/Dockerfile +++ b/packages/server/Dockerfile @@ -41,7 +41,7 @@ RUN chmod +x ./scripts/removeWorkspaceDependencies.sh RUN ./scripts/removeWorkspaceDependencies.sh package.json # Install yarn packages with caching -RUN --mount=type=cache,target=/root/.yarn YARN_CACHE_FOLDER=/root/.yarn yarn install --production=true --network-timeout 1000000 \ +RUN --mount=type=cache,target=/root/.yarn YARN_CACHE_FOLDER=/root/.yarn yarn install --production=true --network-timeout 1000000 --network-concurrency 1 \ && yarn cache clean \ && apk del g++ make python3 jq \ && rm -rf /tmp/* /root/.node-gyp /usr/local/lib/node_modules/npm/node_modules/node-gyp diff --git a/packages/worker/Dockerfile b/packages/worker/Dockerfile index 4b708626f35..807a91de5f4 100644 --- a/packages/worker/Dockerfile +++ b/packages/worker/Dockerfile @@ -24,7 +24,7 @@ COPY packages/worker/dist/yarn.lock . RUN ../scripts/removeWorkspaceDependencies.sh package.json -RUN --mount=type=cache,target=/root/.yarn YARN_CACHE_FOLDER=/root/.yarn yarn install --production=true --network-timeout 1000000 +RUN --mount=type=cache,target=/root/.yarn YARN_CACHE_FOLDER=/root/.yarn yarn install --production=true --network-timeout 1000000 --network-concurrency 1 # Remove unneeded data from file system to reduce image size RUN apk del .gyp \ && yarn cache clean