reworking frontend to use shared core functions to check if is admin or builder (needs further expansion).

This commit is contained in:
mike12345567 2023-07-19 18:05:02 +01:00
parent 85dea47a31
commit e469abb679
11 changed files with 58 additions and 47 deletions

View File

@ -1,10 +1,8 @@
import { UserCtx } from "@budibase/types" import { UserCtx } from "@budibase/types"
import { isAdmin } from "../users"
export default async (ctx: UserCtx, next: any) => { export default async (ctx: UserCtx, next: any) => {
if ( if (!ctx.internal && !isAdmin(ctx.user)) {
!ctx.internal &&
(!ctx.user || !ctx.user.admin || !ctx.user.admin.global)
) {
ctx.throw(403, "Admin user only endpoint.") ctx.throw(403, "Admin user only endpoint.")
} }
return next() return next()

View File

@ -12,12 +12,12 @@
} from "@budibase/bbui" } from "@budibase/bbui"
import { store } from "builderStore" import { store } from "builderStore"
import { groups, licensing, apps, users, auth, admin } from "stores/portal" import { groups, licensing, apps, users, auth, admin } from "stores/portal"
import { fetchData } from "@budibase/frontend-core" import { fetchData, Constants, Utils } from "@budibase/frontend-core"
import { sdk } from "@budibase/shared-core"
import { API } from "api" import { API } from "api"
import GroupIcon from "../../../portal/users/groups/_components/GroupIcon.svelte" import GroupIcon from "../../../portal/users/groups/_components/GroupIcon.svelte"
import RoleSelect from "components/common/RoleSelect.svelte" import RoleSelect from "components/common/RoleSelect.svelte"
import UpgradeModal from "components/common/users/UpgradeModal.svelte" import UpgradeModal from "components/common/users/UpgradeModal.svelte"
import { Constants, Utils } from "@budibase/frontend-core"
import { emailValidator } from "helpers/validation" import { emailValidator } from "helpers/validation"
import { roles } from "stores/backend" import { roles } from "stores/backend"
import { fly } from "svelte/transition" import { fly } from "svelte/transition"
@ -108,7 +108,7 @@
await usersFetch.refresh() await usersFetch.refresh()
filteredUsers = $usersFetch.rows.map(user => { filteredUsers = $usersFetch.rows.map(user => {
const isBuilderOrAdmin = user.admin?.global || user.builder?.global const isBuilderOrAdmin = sdk.users.isBuilderOrAdmin(user, prodAppId)
let role = undefined let role = undefined
if (isBuilderOrAdmin) { if (isBuilderOrAdmin) {
role = Constants.Roles.ADMIN role = Constants.Roles.ADMIN
@ -258,7 +258,7 @@
} }
// Must exclude users who have explicit privileges // Must exclude users who have explicit privileges
const userByEmail = filteredUsers.reduce((acc, user) => { const userByEmail = filteredUsers.reduce((acc, user) => {
if (user.role || user.admin?.global || user.builder?.global) { if (user.role || sdk.users.isBuilderOrAdmin(user, prodAppId)) {
acc.push(user.email) acc.push(user.email)
} }
return acc return acc
@ -389,9 +389,9 @@
} }
const userTitle = user => { const userTitle = user => {
if (user.admin?.global) { if (sdk.users.isAdmin(user)) {
return "Admin" return "Admin"
} else if (user.builder?.global) { } else if (sdk.users.isBuilder(user, prodAppId)) {
return "Developer" return "Developer"
} else { } else {
return "App user" return "App user"

View File

@ -22,7 +22,7 @@
import Spaceman from "assets/bb-space-man.svg" import Spaceman from "assets/bb-space-man.svg"
import Logo from "assets/bb-emblem.svg" import Logo from "assets/bb-emblem.svg"
import { UserAvatar } from "@budibase/frontend-core" import { UserAvatar } from "@budibase/frontend-core"
import { helpers } from "@budibase/shared-core" import { helpers, sdk } from "@budibase/shared-core"
let loaded = false let loaded = false
let userInfoModal let userInfoModal
@ -43,32 +43,30 @@
$: userGroups = $groups.filter(group => $: userGroups = $groups.filter(group =>
group.users.find(user => user._id === $auth.user?._id) group.users.find(user => user._id === $auth.user?._id)
) )
let userApps = []
$: publishedApps = $apps.filter(publishedAppsOnly) $: publishedApps = $apps.filter(publishedAppsOnly)
$: userApps = getUserApps($auth.user)
$: { function getUserApps(user) {
if (!Object.keys($auth.user?.roles).length && $auth.user?.userGroups) { if (sdk.users.isAdmin(user)) {
userApps = return publishedApps
$auth.user?.builder?.global || $auth.user?.admin?.global
? publishedApps
: publishedApps.filter(app => {
return userGroups.find(group => {
return groups.actions
.getGroupAppIds(group)
.map(role => apps.extractAppId(role))
.includes(app.appId)
})
})
} else {
userApps =
$auth.user?.builder?.global || $auth.user?.admin?.global
? publishedApps
: publishedApps.filter(app =>
Object.keys($auth.user?.roles)
.map(x => apps.extractAppId(x))
.includes(app.appId)
)
} }
return publishedApps.filter(app => {
if (sdk.users.isBuilder(user, app.appId)) {
return true
}
if (!Object.keys(user?.roles).length && user?.userGroups) {
return userGroups.find(group => {
return groups.actions
.getGroupAppIds(group)
.map(role => apps.extractAppId(role))
.includes(app.appId)
})
} else {
return Object.keys($auth.user?.roles)
.map(x => apps.extractAppId(x))
.includes(app.appId)
}
})
} }
function getUrl(app) { function getUrl(app) {

View File

@ -1,11 +1,12 @@
<script> <script>
import { redirect } from "@roxi/routify" import { redirect } from "@roxi/routify"
import { auth } from "stores/portal" import { auth } from "stores/portal"
import { sdk } from "@budibase/shared-core"
auth.checkQueryString() auth.checkQueryString()
$: { $: {
if ($auth.user?.builder?.global) { if (sdk.users.hasBuilderPermissions($auth.user)) {
$redirect(`./portal`) $redirect(`./portal`)
} else if ($auth.user) { } else if ($auth.user) {
$redirect(`./apps`) $redirect(`./apps`)

View File

@ -8,6 +8,7 @@
import Logo from "./_components/Logo.svelte" import Logo from "./_components/Logo.svelte"
import UserDropdown from "./_components/UserDropdown.svelte" import UserDropdown from "./_components/UserDropdown.svelte"
import HelpMenu from "components/common/HelpMenu.svelte" import HelpMenu from "components/common/HelpMenu.svelte"
import { sdk } from "@budibase/shared-core"
let loaded = false let loaded = false
let mobileMenuVisible = false let mobileMenuVisible = false
@ -33,7 +34,7 @@
onMount(async () => { onMount(async () => {
// Prevent non-builders from accessing the portal // Prevent non-builders from accessing the portal
if ($auth.user) { if ($auth.user) {
if (!$auth.user?.builder?.global) { if (!sdk.users.hasBuilderPermissions($auth.user)) {
$redirect("../") $redirect("../")
} else { } else {
try { try {

View File

@ -31,6 +31,7 @@
import AppNameTableRenderer from "./_components/AppNameTableRenderer.svelte" import AppNameTableRenderer from "./_components/AppNameTableRenderer.svelte"
import AppRoleTableRenderer from "./_components/AppRoleTableRenderer.svelte" import AppRoleTableRenderer from "./_components/AppRoleTableRenderer.svelte"
import ScimBanner from "../_components/SCIMBanner.svelte" import ScimBanner from "../_components/SCIMBanner.svelte"
import { sdk } from "@budibase/shared-core"
export let userId export let userId
@ -88,7 +89,7 @@
$: scimEnabled = $features.isScimEnabled $: scimEnabled = $features.isScimEnabled
$: isSSO = !!user?.provider $: isSSO = !!user?.provider
$: readonly = !$auth.isAdmin || scimEnabled $: readonly = !$auth.isAdmin || scimEnabled
$: privileged = user?.admin?.global || user?.builder?.global $: privileged = sdk.users.isAdminOrBuilder(user)
$: nameLabel = getNameLabel(user) $: nameLabel = getNameLabel(user)
$: filteredGroups = getFilteredGroups($groups, searchTerm) $: filteredGroups = getFilteredGroups($groups, searchTerm)
$: availableApps = getAvailableApps($apps, privileged, user?.roles) $: availableApps = getAvailableApps($apps, privileged, user?.roles)
@ -97,9 +98,9 @@
return y._id === userId return y._id === userId
}) })
}) })
$: globalRole = user?.admin?.global $: globalRole = sdk.users.isAdmin(user)
? "admin" ? "admin"
: user?.builder?.global : sdk.users.isBuilder(user)
? "developer" ? "developer"
: "appUser" : "appUser"

View File

@ -1,11 +1,12 @@
<script> <script>
import { Icon } from "@budibase/bbui" import { Icon } from "@budibase/bbui"
import { apps } from "stores/portal" import { apps } from "stores/portal"
import { sdk } from "@budibase/shared-core"
export let value export let value
export let row export let row
$: priviliged = row?.admin?.global || row?.builder?.global $: priviliged = sdk.users.isAdminOrBuilder(row)
$: count = priviliged ? $apps.length : value?.length || 0 $: count = priviliged ? $apps.length : value?.length || 0
</script> </script>

View File

@ -2,6 +2,7 @@
import { createEventDispatcher } from "svelte" import { createEventDispatcher } from "svelte"
import { Body, Select, ModalContent, notifications } from "@budibase/bbui" import { Body, Select, ModalContent, notifications } from "@budibase/bbui"
import { users } from "stores/portal" import { users } from "stores/portal"
import { sdk } from "@budibase/shared-core"
export let app export let app
export let user export let user
@ -15,7 +16,7 @@
.filter(role => role._id !== "PUBLIC") .filter(role => role._id !== "PUBLIC")
.map(role => ({ value: role._id, label: role.name })) .map(role => ({ value: role._id, label: role.name }))
if (!user?.builder?.global) { if (!sdk.users.isBuilder(user, app?.appId)) {
options.push({ value: NO_ACCESS, label: "No Access" }) options.push({ value: NO_ACCESS, label: "No Access" })
} }
let selectedRole = user?.roles?.[app?._id] let selectedRole = user?.roles?.[app?._id]

View File

@ -2,6 +2,7 @@ import { derived, writable, get } from "svelte/store"
import { API } from "api" import { API } from "api"
import { admin } from "stores/portal" import { admin } from "stores/portal"
import analytics from "analytics" import analytics from "analytics"
import { sdk } from "@budibase/shared-core"
export function createAuthStore() { export function createAuthStore() {
const auth = writable({ const auth = writable({
@ -17,8 +18,8 @@ export function createAuthStore() {
let isBuilder = false let isBuilder = false
if ($store.user) { if ($store.user) {
const user = $store.user const user = $store.user
isAdmin = !!user.admin?.global isAdmin = sdk.users.isAdmin(user)
isBuilder = !!user.builder?.global isBuilder = sdk.users.isBuilder(user)
} }
return { return {
user: $store.user, user: $store.user,
@ -57,8 +58,8 @@ export function createAuthStore() {
name: user.account?.name, name: user.account?.name,
user_id: user._id, user_id: user._id,
tenant: user.tenantId, tenant: user.tenantId,
admin: user?.admin?.global, admin: sdk.users.isAdmin(user),
builder: user?.builder?.global, builder: sdk.users.isBuilder(user),
"Company size": user.account?.size, "Company size": user.account?.size,
"Job role": user.account?.profession, "Job role": user.account?.profession,
}, },

View File

@ -2,6 +2,7 @@ import { writable } from "svelte/store"
import { API } from "api" import { API } from "api"
import { update } from "lodash" import { update } from "lodash"
import { licensing } from "." import { licensing } from "."
import { sdk } from "@budibase/shared-core"
export function createUsersStore() { export function createUsersStore() {
const { subscribe, set } = writable({}) const { subscribe, set } = writable({})
@ -111,8 +112,12 @@ export function createUsersStore() {
return await API.saveUser(user) return await API.saveUser(user)
} }
const getUserRole = ({ admin, builder }) => const getUserRole = user =>
admin?.global ? "admin" : builder?.global ? "developer" : "appUser" sdk.users.isAdmin(user)
? "admin"
: sdk.users.isBuilder(user)
? "developer"
: "appUser"
const refreshUsage = const refreshUsage =
fn => fn =>

View File

@ -18,6 +18,10 @@ export function isAdmin(user: User | ContextUser) {
return hasAdminPermissions(user) return hasAdminPermissions(user)
} }
export function isAdminOrBuilder(user: User | ContextUser, appId?: string) {
return isBuilder(user, appId) || isAdmin(user)
}
// checks if a user is capable of building any app // checks if a user is capable of building any app
export function hasBuilderPermissions(user?: User | ContextUser) { export function hasBuilderPermissions(user?: User | ContextUser) {
if (!user) { if (!user) {