lint
This commit is contained in:
parent
25a395972c
commit
dfdee4d271
|
@ -0,0 +1,64 @@
|
|||
import { publishEvent } from "../events"
|
||||
import {
|
||||
Event,
|
||||
UserGroup,
|
||||
GroupCreatedEvent,
|
||||
GroupDeletedEvent,
|
||||
GroupUpdatedEvent,
|
||||
GroupUsersAddedEvent,
|
||||
GroupUsersDeletedEvent,
|
||||
GroupsAddedOnboarding,
|
||||
UserGroupRoles,
|
||||
} from "@budibase/types"
|
||||
|
||||
export async function created(group: UserGroup, timestamp?: number) {
|
||||
const properties: GroupCreatedEvent = {
|
||||
groupId: group._id as string,
|
||||
}
|
||||
await publishEvent(Event.USER_GROUP_CREATED, properties, timestamp)
|
||||
}
|
||||
|
||||
export async function updated(group: UserGroup) {
|
||||
const properties: GroupUpdatedEvent = {
|
||||
groupId: group._id as string,
|
||||
}
|
||||
await publishEvent(Event.USER_GROUP_UPDATED, properties)
|
||||
}
|
||||
|
||||
export async function deleted(group: UserGroup) {
|
||||
const properties: GroupDeletedEvent = {
|
||||
groupId: group._id as string,
|
||||
}
|
||||
await publishEvent(Event.USER_GROUP_DELETED, properties)
|
||||
}
|
||||
|
||||
export async function usersAdded(emails: string[], group: UserGroup) {
|
||||
const properties: GroupUsersAddedEvent = {
|
||||
emails,
|
||||
count: emails.length,
|
||||
groupId: group._id as string,
|
||||
}
|
||||
await publishEvent(Event.USER_GROUP_USER_ADDED, properties)
|
||||
}
|
||||
|
||||
export async function usersDeleted(emails: string[], group: UserGroup) {
|
||||
const properties: GroupUsersDeletedEvent = {
|
||||
emails,
|
||||
count: emails.length,
|
||||
groupId: group._id as string,
|
||||
}
|
||||
await publishEvent(Event.USER_GROUP_USER_REMOVED, properties)
|
||||
}
|
||||
|
||||
export async function createdOnboarding(groupId: string) {
|
||||
const properties: GroupsAddedOnboarding = {
|
||||
groupId: groupId,
|
||||
onboarding: true,
|
||||
}
|
||||
await publishEvent(Event.USER_GROUP_ONBOARDING, properties)
|
||||
}
|
||||
|
||||
export async function permissionsEdited(roles: UserGroupRoles) {
|
||||
const properties: UserGroupRoles = roles
|
||||
await publishEvent(Event.USER_GROUP_PERMISSIONS_EDITED, properties)
|
||||
}
|
|
@ -17,3 +17,4 @@ export * as user from "./user"
|
|||
export * as view from "./view"
|
||||
export * as installation from "./installation"
|
||||
export * as backfill from "./backfill"
|
||||
export * as group from "./group"
|
||||
|
|
|
@ -53,7 +53,7 @@
|
|||
|
||||
let user = await users.get(id)
|
||||
|
||||
let userGroups = user.groups || []
|
||||
let userGroups = user.userGroups || []
|
||||
userGroups.push(groupId)
|
||||
await users.save({
|
||||
...user,
|
||||
|
|
|
@ -1,2 +1,3 @@
|
|||
export * from "./config"
|
||||
export * from "./user"
|
||||
export * from "./userGroup"
|
||||
|
|
|
@ -13,6 +13,7 @@ export interface User extends Document {
|
|||
providerType?: string
|
||||
password?: string
|
||||
status?: string
|
||||
|
||||
createdAt?: number // override the default createdAt behaviour - users sdk historically set this to Date.now()
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
import { Document } from "../document"
|
||||
import { User } from "./user"
|
||||
export interface UserGroup extends Document {
|
||||
name: string
|
||||
icon: string
|
||||
color: string
|
||||
users: User[]
|
||||
apps: any
|
||||
roles: UserGroupRoles
|
||||
createdAt?: number
|
||||
}
|
||||
|
||||
export interface UserGroupRoles {
|
||||
[key: string]: string
|
||||
}
|
|
@ -150,6 +150,15 @@ export enum Event {
|
|||
TENANT_BACKFILL_FAILED = "tenant:backfill:failed",
|
||||
INSTALLATION_BACKFILL_SUCCEEDED = "installation:backfill:succeeded",
|
||||
INSTALLATION_BACKFILL_FAILED = "installation:backfill:failed",
|
||||
|
||||
// USER
|
||||
USER_GROUP_CREATED = "user_group:created",
|
||||
USER_GROUP_UPDATED = "user_group:updated",
|
||||
USER_GROUP_DELETED = "user_group:deleted",
|
||||
USER_GROUP_USER_ADDED = "user_group_user:added",
|
||||
USER_GROUP_USER_REMOVED = "user_group_user:deleted",
|
||||
USER_GROUP_PERMISSIONS_EDITED = "user_group_permissions:edited",
|
||||
USER_GROUP_ONBOARDING = "user_group_onboarding:added",
|
||||
}
|
||||
|
||||
// properties added at the final stage of the event pipeline
|
||||
|
|
|
@ -18,3 +18,4 @@ export * from "./view"
|
|||
export * from "./account"
|
||||
export * from "./backfill"
|
||||
export * from "./identification"
|
||||
export * from "./userGroup"
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
import { BaseEvent } from "./event"
|
||||
|
||||
export interface GroupCreatedEvent extends BaseEvent {
|
||||
groupId: string
|
||||
}
|
||||
|
||||
export interface GroupUpdatedEvent extends BaseEvent {
|
||||
groupId: string
|
||||
}
|
||||
|
||||
export interface GroupDeletedEvent extends BaseEvent {
|
||||
groupId: string
|
||||
}
|
||||
|
||||
export interface GroupUsersAddedEvent extends BaseEvent {
|
||||
emails: string[]
|
||||
count: number
|
||||
groupId: string
|
||||
}
|
||||
|
||||
export interface GroupsAddedOnboarding extends BaseEvent {
|
||||
groupId: string
|
||||
onboarding: boolean
|
||||
}
|
|
@ -1,24 +1,64 @@
|
|||
const { Configs } = require("../../../constants")
|
||||
const email = require("../../../utilities/email")
|
||||
const { getGlobalDB, getTenantId } = require("@budibase/backend-core/tenancy")
|
||||
const env = require("../../../environment")
|
||||
const {
|
||||
withCache,
|
||||
CacheKeys,
|
||||
bustCache,
|
||||
} = require("@budibase/backend-core/cache")
|
||||
import { UserGroup } from "@budibase/types"
|
||||
const { difference } = require("lodash/fp")
|
||||
|
||||
const { events } = require("@budibase/backend-core")
|
||||
const { getGlobalDB } = require("@budibase/backend-core/tenancy")
|
||||
const { groups } = require("@budibase/pro")
|
||||
|
||||
exports.save = async function (ctx: any) {
|
||||
const db = getGlobalDB()
|
||||
let group: UserGroup = ctx.request.body
|
||||
const oldGroup: UserGroup = await db.get(group._id)
|
||||
|
||||
let eventFns = []
|
||||
// Config does not exist yet
|
||||
if (!ctx.request.body._id) {
|
||||
ctx.request.body._id = groups.generateUserGroupID(ctx.request.body.name)
|
||||
if (!group._id) {
|
||||
group._id = groups.generateUserGroupID(ctx.request.body.name)
|
||||
eventFns.push(() => events.group.created(group))
|
||||
} else {
|
||||
// Get the diff between the old users and new users for
|
||||
// event processing purposes
|
||||
let uniqueOld = group.users.filter(g => {
|
||||
return !oldGroup.users.some(og => {
|
||||
return g._id == og._id
|
||||
})
|
||||
})
|
||||
|
||||
let uniqueNew = oldGroup.users.filter(g => {
|
||||
return !group.users.some(og => {
|
||||
return g._id == og._id
|
||||
})
|
||||
})
|
||||
let newUsers = uniqueOld.concat(uniqueNew)
|
||||
|
||||
eventFns.push(() => events.group.updated(group))
|
||||
|
||||
if (group.users.length < oldGroup.users.length) {
|
||||
eventFns.push(() =>
|
||||
events.group.usersDeleted(
|
||||
newUsers.map(u => u.email),
|
||||
group
|
||||
)
|
||||
)
|
||||
} else if (group.users.length > oldGroup.users.length) {
|
||||
eventFns.push(() =>
|
||||
events.group.usersAdded(
|
||||
newUsers.map(u => u.email),
|
||||
group
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
if (JSON.stringify(oldGroup.roles) !== JSON.stringify(group.roles)) {
|
||||
eventFns.push(() => events.group.permissionsEdited(group.roles))
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await db.put(ctx.request.body)
|
||||
for (const fn of eventFns) {
|
||||
await fn()
|
||||
}
|
||||
const response = await db.put(group)
|
||||
ctx.body = {
|
||||
_id: response.id,
|
||||
_rev: response.rev,
|
||||
|
@ -41,9 +81,10 @@ exports.fetch = async function (ctx: any) {
|
|||
exports.destroy = async function (ctx: any) {
|
||||
const db = getGlobalDB()
|
||||
const { id, rev } = ctx.params
|
||||
|
||||
const group = await db.get(id)
|
||||
try {
|
||||
await db.remove(id, rev)
|
||||
await events.group.deleted(group)
|
||||
ctx.body = { message: "Group deleted successfully" }
|
||||
} catch (err: any) {
|
||||
ctx.throw(err.status, err)
|
||||
|
|
|
@ -3,7 +3,7 @@ import { checkInviteCode } from "../../../utilities/redis"
|
|||
import { sendEmail } from "../../../utilities/email"
|
||||
import { users } from "../../../sdk"
|
||||
import env from "../../../environment"
|
||||
import { User, CloudAccount } from "@budibase/types"
|
||||
import { User, CloudAccount, UserGroup } from "@budibase/types"
|
||||
import {
|
||||
events,
|
||||
errors,
|
||||
|
@ -24,53 +24,54 @@ export const save = async (ctx: any) => {
|
|||
|
||||
export const bulkSave = async (ctx: any) => {
|
||||
let { users: newUsersRequested, groups } = ctx.request.body
|
||||
let usersToSave: any[] = []
|
||||
let groupsToSave: any[] = []
|
||||
const newUsers: any[] = []
|
||||
const db = tenancy.getGlobalDB()
|
||||
const currentUserEmails =
|
||||
(await users.allUsers())?.map((x: any) => x.email) || []
|
||||
|
||||
for (const newUser of newUsersRequested) {
|
||||
if (
|
||||
newUsers.find((x: any) => x.email === newUser.email) ||
|
||||
currentUserEmails.includes(newUser.email)
|
||||
)
|
||||
continue
|
||||
|
||||
newUser.userGroups = groups
|
||||
newUsers.push(newUser)
|
||||
}
|
||||
|
||||
newUsers.forEach((user: any) => {
|
||||
usersToSave.push(
|
||||
users.save(user, {
|
||||
hashPassword: true,
|
||||
requirePassword: user.requirePassword,
|
||||
bulkCreate: true,
|
||||
})
|
||||
)
|
||||
|
||||
if (groups.length) {
|
||||
groups.forEach(async (groupId: string) => {
|
||||
let oldGroup = await db.get(groupId)
|
||||
groupsToSave.push(oldGroup)
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
try {
|
||||
const allUsers = await Promise.all(usersToSave)
|
||||
let response = await db.bulkDocs(allUsers)
|
||||
let response = []
|
||||
for (const user of newUsers) {
|
||||
response = await users.save(user, {
|
||||
hashPassword: true,
|
||||
requirePassword: user.requirePassword,
|
||||
bulkCreate: false,
|
||||
})
|
||||
}
|
||||
|
||||
// delete passwords and add to group
|
||||
allUsers.forEach(user => {
|
||||
newUsers.forEach(user => {
|
||||
delete user.password
|
||||
})
|
||||
|
||||
if (groupsToSave.length)
|
||||
groupsToSave.forEach(async group => {
|
||||
group.users = [...group.users, ...allUsers]
|
||||
await db.put(group)
|
||||
if (groupsToSave.length) {
|
||||
groupsToSave.forEach(async (userGroup: UserGroup) => {
|
||||
userGroup.users = [...userGroup.users, ...newUsers]
|
||||
await db.put(userGroup)
|
||||
events.group.usersAdded(
|
||||
newUsers.map(u => u.email),
|
||||
userGroup
|
||||
)
|
||||
events.group.createdOnboarding(userGroup._id as string)
|
||||
})
|
||||
}
|
||||
|
||||
ctx.body = response
|
||||
} catch (err: any) {
|
||||
|
|
|
@ -31,9 +31,8 @@ export const allUsers = async () => {
|
|||
|
||||
export const paginatedUsers = async ({
|
||||
page,
|
||||
email,
|
||||
appId,
|
||||
}: { page?: string; email?: string; appId?: string } = {}) => {
|
||||
search,
|
||||
}: { page?: string; search?: string } = {}) => {
|
||||
const db = tenancy.getGlobalDB()
|
||||
// get one extra document, to have the next page
|
||||
const opts: any = {
|
||||
|
@ -45,24 +44,19 @@ export const paginatedUsers = async ({
|
|||
opts.startkey = page
|
||||
}
|
||||
// property specifies what to use for the page/anchor
|
||||
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 {
|
||||
let userList, property
|
||||
// no search, query allDocs
|
||||
if (!search) {
|
||||
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,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue