update handling of group roles

This commit is contained in:
Peter Clement 2022-07-19 14:20:57 +01:00
parent ca41e88045
commit ba74fa9500
11 changed files with 14582 additions and 28 deletions

View File

@ -8,7 +8,7 @@
"editor.defaultFormatter": "vscode.json-language-features"
},
"[javascript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
"editor.defaultFormatter": "vscode.typescript-language-features"
},
"debug.javascript.terminalOptions": {
"skipFiles": [
@ -16,4 +16,7 @@
"<node_internals>/**"
]
},
"[typescript]": {
"editor.defaultFormatter": "vscode.typescript-language-features"
},
}

View File

@ -13,7 +13,7 @@
notifications,
} from "@budibase/bbui"
import { onMount } from "svelte"
import { apps, organisation, auth } from "stores/portal"
import { apps, organisation, auth, groups } from "stores/portal"
import { goto } from "@roxi/routify"
import { AppStatus } from "constants"
import { gradient } from "actions"
@ -30,20 +30,37 @@
try {
await organisation.init()
await apps.load()
await groups.actions.init()
} catch (error) {
notifications.error("Error loading apps")
}
loaded = true
})
const publishedAppsOnly = app => app.status === AppStatus.DEPLOYED
$: userGroups = $groups.filter(group =>
group.users.find(user => user._id === $auth.user?._id)
)
let userApps = []
$: publishedApps = $apps.filter(publishedAppsOnly)
$: userApps = $auth.user?.builder?.global
? publishedApps
: publishedApps.filter(app =>
Object.keys($auth.user?.roles).includes(app.prodId)
)
$: {
if (!Object.keys($auth.user?.roles).length) {
userApps = $auth.user?.builder?.global
? publishedApps
: publishedApps.filter(app => {
return userGroups.find(group => {
return Object.keys(group.roles).includes(app.prodId)
})
})
} else {
userApps = $auth.user?.builder?.global
? publishedApps
: publishedApps.filter(app =>
Object.keys($auth.user?.roles).includes(app.prodId)
)
}
}
function getUrl(app) {
if (app.url) {

View File

@ -31,7 +31,7 @@
$: page = $pageInfo.page
$: fetchUsers(page, search)
$: group = $groups.find(x => x._id === groupId)
$: console.log(group.users)
async function addAll() {
group.users = selectedUsers
await groups.actions.save(group)
@ -175,9 +175,11 @@
iconBackground={app?.icon?.color || ""}
>
<div class="title ">
<StatusLight color={RoleUtils.getRoleColour(group.role)} />
<StatusLight
color={RoleUtils.getRoleColour(group.roles[app.prodId])}
/>
<div style="margin-left: var(--spacing-s);">
<Body size="XS">{group.role}</Body>
<Body size="XS">{group.roles[app.prodId]}</Body>
</div>
</div>
</ListItem>

View File

@ -40,6 +40,7 @@
let selectedGroups = []
let allAppList = []
$: user = users.get(userId)
$: isProPlan = $auth.user?.license.plan.type !== Constants.PlanType.FREE
$: allAppList = $apps
@ -69,7 +70,7 @@
selectedGroups &&
group?.name?.toLowerCase().includes(searchTerm.toLowerCase())
)
$: console.log($groups)
$: userGroups = $groups.filter(x => {
return x.users?.find(y => {
return y._id === userId
@ -133,16 +134,15 @@
async function addGroup(groupId) {
let selectedGroup = selectedGroups.includes(groupId)
let newUser = $users.find(user => user._id === userId)
let group = $groups.find(group => group._id === groupId)
if (selectedGroup) {
selectedGroups = selectedGroups.filter(id => id === selectedGroup)
let newUsers = group.users.filter(user => user._id !== newUser._id)
let newUsers = group.users.filter(groupUser => user._id !== groupUser._id)
group.users = newUsers
} else {
selectedGroups = [...selectedGroups, groupId]
group.users.push(newUser)
group.users.push(user)
}
await groups.actions.save(group)

View File

@ -9,6 +9,7 @@
Modal,
notifications,
Pagination,
Icon,
} from "@budibase/bbui"
import { onMount } from "svelte"
@ -31,7 +32,7 @@
$: fetchUsers(page, search)
$: isProPlan = $auth.user?.license.plan.type !== Constants.PlanType.FREE
$: console.log($users.data)
$: appUsers =
$users.data?.filter(x => {
return Object.keys(x.roles).find(y => {
@ -48,7 +49,6 @@
async function addData(appData) {
let gr_prefix = "gr"
let us_prefix = "us"
console.log(appData)
appData.forEach(async data => {
if (data.id.startsWith(gr_prefix)) {
let matchedGroup = $groups.find(group => {
@ -75,6 +75,35 @@
await users.search({ page, appId: app.prodId })
}
async function removeUser(user) {
// Remove the user role
const filteredRoles = { ...user.roles }
delete filteredRoles[app?.prodId]
await users.save({
...user,
roles: {
...filteredRoles,
},
})
await users.search({ page, appId: app.prodId })
}
async function removeGroup(group) {
// Remove the user role
let filteredApps = group.apps.filter(x => x.appId !== app.appId)
const filteredRoles = { ...group.roles }
delete filteredRoles[app?.prodId]
await groups.actions.save({
...group,
apps: filteredApps,
roles: { ...filteredRoles },
})
await users.search({ page, appId: app.prodId })
}
async function updateUserRole(role, user) {
user.roles[app.prodId] = role
users.save(user)
@ -145,6 +174,12 @@
Object.keys(group.roles).find(x => x === app.prodId)
]}
/>
<Icon
on:click={() => removeGroup(group)}
hoverable
size="S"
name="Close"
/>
</ListItem>
{/each}
</List>
@ -161,6 +196,12 @@
Object.keys(user.roles).find(x => x === app.prodId)
]}
/>
<Icon
on:click={() => removeUser(user)}
hoverable
size="S"
name="Close"
/>
</ListItem>
{/each}
</List>

View File

@ -17,7 +17,8 @@ export function createUsersStore() {
async function get(userId) {
try {
return await API.getUser(userId)
let user = await API.getUser(userId)
return user
} catch (err) {
return null
}

View File

@ -31,9 +31,9 @@ exports.updateAppRole = async (user, { appId } = {}) => {
// if a role wasn't found then either set as admin (builder) or public (everyone else)
if (!user.roleId && user.builder && user.builder.global) {
user.roleId = BUILTIN_ROLE_IDS.ADMIN
} else if (!user.roleId) {
} else if (!user.roleId && !user?.userGroups?.length) {
user.roleId = BUILTIN_ROLE_IDS.PUBLIC
} else if (user?.userGroups?.length) {
} else if (!user.roleId && user?.userGroups?.length) {
let roleId = await groups.getGroupRoleId(user, appId)
user.roleId = roleId
}

14447
packages/server/yarn.lock Normal file

File diff suppressed because it is too large Load Diff

View File

@ -14,7 +14,8 @@ export interface User extends Document {
password?: string
status?: string
createdAt?: number // override the default createdAt behaviour - users sdk historically set this to Date.now()
createdAt?: number
userGroups?: string[] // override the default createdAt behaviour - users sdk historically set this to Date.now()
}
export interface UserRoles {

View File

@ -18,6 +18,12 @@ export interface GroupUsersAddedEvent extends BaseEvent {
groupId: string
}
export interface GroupUsersDeletedEvent extends BaseEvent {
emails: string[]
count: number
groupId: string
}
export interface GroupsAddedOnboarding extends BaseEvent {
groupId: string
onboarding: boolean

View File

@ -47,13 +47,15 @@ export const bulkSave = async (ctx: any) => {
}
try {
let response = []
let response: any[] = []
for (const user of newUsers) {
response = await users.save(user, {
hashPassword: true,
requirePassword: user.requirePassword,
bulkCreate: false,
})
response.push(
await users.save(user, {
hashPassword: true,
requirePassword: user.requirePassword,
bulkCreate: false,
})
)
}
// delete passwords and add to group
@ -63,7 +65,7 @@ export const bulkSave = async (ctx: any) => {
if (groupsToSave.length) {
groupsToSave.forEach(async (userGroup: UserGroup) => {
userGroup.users = [...userGroup.users, ...newUsers]
userGroup.users = [...userGroup.users, ...response]
await db.put(userGroup)
events.group.usersAdded(
newUsers.map(u => u.email),
@ -141,7 +143,24 @@ export const adminUser = async (ctx: any) => {
export const destroy = async (ctx: any) => {
const id = ctx.params.id
const db = tenancy.getGlobalDB()
let user: User = await db.get(id)
let groups = user.userGroups
await users.destroy(id, ctx.user)
// Remove asssosicated groups
if (groups) {
for (const groupId of groups) {
let group = await db.get(groupId)
let updatedUsersGroup = group.users.filter(
(groupUser: any) => groupUser.email !== user.email
)
group.users = updatedUsersGroup
await db.put(group)
}
}
ctx.body = {
message: `User ${id} deleted.`,
}
@ -149,10 +168,27 @@ export const destroy = async (ctx: any) => {
export const bulkDelete = async (ctx: any) => {
const { userIds } = ctx.request.body
const db = tenancy.getGlobalDB()
let deleted = 0
for (const id of userIds) {
let user: User = await db.get(id)
let groups = user.userGroups
await users.destroy(id, ctx.user)
if (groups) {
for (const groupId of groups) {
let group = await db.get(groupId)
let updatedUsersGroup = group.users.filter(
(groupUser: any) => groupUser.email !== user.email
)
console.log(updatedUsersGroup)
group.users = updatedUsersGroup
await db.put(group)
}
}
deleted++
}