Updating user API to user a single bulk endpoint rather than case sensitive named endpoints.
This commit is contained in:
parent
4d9de7f658
commit
f07ea5cc7e
|
@ -86,14 +86,17 @@ export const buildUserEndpoints = API => ({
|
||||||
/**
|
/**
|
||||||
* Creates multiple users.
|
* Creates multiple users.
|
||||||
* @param users the array of user objects to create
|
* @param users the array of user objects to create
|
||||||
|
* @param groups the array of group ids to add all users to
|
||||||
*/
|
*/
|
||||||
createUsers: async ({ users, groups }) => {
|
createUsers: async ({ users, groups }) => {
|
||||||
return await API.post({
|
return await API.post({
|
||||||
url: "/api/global/users/bulkCreate",
|
url: "/api/global/users/bulk",
|
||||||
body: {
|
body: {
|
||||||
|
create: {
|
||||||
users,
|
users,
|
||||||
groups,
|
groups,
|
||||||
},
|
},
|
||||||
|
},
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -109,14 +112,16 @@ export const buildUserEndpoints = API => ({
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes multiple users
|
* Deletes multiple users
|
||||||
* @param userId the ID of the user to delete
|
* @param userIds the ID of the user to delete
|
||||||
*/
|
*/
|
||||||
deleteUsers: async userIds => {
|
deleteUsers: async userIds => {
|
||||||
return await API.post({
|
return await API.post({
|
||||||
url: `/api/global/users/bulkDelete`,
|
url: `/api/global/users/bulk`,
|
||||||
body: {
|
body: {
|
||||||
|
delete: {
|
||||||
userIds,
|
userIds,
|
||||||
},
|
},
|
||||||
|
},
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -6,29 +6,32 @@ export interface CreateUserResponse {
|
||||||
email: string
|
email: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface BulkCreateUsersRequest {
|
|
||||||
users: User[]
|
|
||||||
groups: any[]
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface UserDetails {
|
export interface UserDetails {
|
||||||
_id: string
|
_id: string
|
||||||
email: string
|
email: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface BulkCreateUsersResponse {
|
export interface BulkUserRequest {
|
||||||
|
delete?: {
|
||||||
|
userIds: string[]
|
||||||
|
}
|
||||||
|
create?: {
|
||||||
|
users: User[]
|
||||||
|
groups: any[]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface BulkUserResponse {
|
||||||
|
created?: {
|
||||||
successful: UserDetails[]
|
successful: UserDetails[]
|
||||||
unsuccessful: { email: string; reason: string }[]
|
unsuccessful: { email: string; reason: string }[]
|
||||||
}
|
}
|
||||||
|
deleted?: {
|
||||||
export interface BulkDeleteUsersRequest {
|
|
||||||
userIds: string[]
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface BulkDeleteUsersResponse {
|
|
||||||
successful: UserDetails[]
|
successful: UserDetails[]
|
||||||
unsuccessful: { _id: string; email: string; reason: string }[]
|
unsuccessful: { _id: string; email: string; reason: string }[]
|
||||||
}
|
}
|
||||||
|
message?: string
|
||||||
|
}
|
||||||
|
|
||||||
export interface InviteUserRequest {
|
export interface InviteUserRequest {
|
||||||
email: string
|
email: string
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
import { checkInviteCode } from "../../../utilities/redis"
|
import { checkInviteCode } from "../../../utilities/redis"
|
||||||
import { users } from "../../../sdk"
|
import { users as userSdk } from "../../../sdk"
|
||||||
import env from "../../../environment"
|
import env from "../../../environment"
|
||||||
import {
|
import {
|
||||||
BulkDeleteUsersRequest,
|
BulkUserRequest,
|
||||||
|
BulkUserResponse,
|
||||||
CloudAccount,
|
CloudAccount,
|
||||||
InviteUserRequest,
|
InviteUserRequest,
|
||||||
InviteUsersRequest,
|
InviteUsersRequest,
|
||||||
|
@ -21,27 +22,43 @@ const MAX_USERS_UPLOAD_LIMIT = 1000
|
||||||
|
|
||||||
export const save = async (ctx: any) => {
|
export const save = async (ctx: any) => {
|
||||||
try {
|
try {
|
||||||
ctx.body = await users.save(ctx.request.body)
|
ctx.body = await userSdk.save(ctx.request.body)
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
ctx.throw(err.status || 400, err)
|
ctx.throw(err.status || 400, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const bulkCreate = async (ctx: any) => {
|
const bulkDelete = async (userIds: string[], currentUserId: string) => {
|
||||||
let { users: newUsersRequested, groups } = ctx.request.body
|
if (userIds?.indexOf(currentUserId) !== -1) {
|
||||||
|
throw new Error("Unable to delete self.")
|
||||||
|
}
|
||||||
|
return await userSdk.bulkDelete(userIds)
|
||||||
|
}
|
||||||
|
|
||||||
if (!env.SELF_HOSTED && newUsersRequested.length > MAX_USERS_UPLOAD_LIMIT) {
|
const bulkCreate = async (users: User[], groupIds: string[]) => {
|
||||||
ctx.throw(
|
if (!env.SELF_HOSTED && users.length > MAX_USERS_UPLOAD_LIMIT) {
|
||||||
400,
|
throw new Error(
|
||||||
"Max limit for upload is 1000 users. Please reduce file size and try again."
|
"Max limit for upload is 1000 users. Please reduce file size and try again."
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
return await userSdk.bulkCreate(users, groupIds)
|
||||||
try {
|
|
||||||
ctx.body = await users.bulkCreate(newUsersRequested, groups)
|
|
||||||
} catch (err: any) {
|
|
||||||
ctx.throw(err.status || 400, err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const bulkUpdate = async (ctx: any) => {
|
||||||
|
const currentUserId = ctx.user._id
|
||||||
|
const input = ctx.request.body as BulkUserRequest
|
||||||
|
let created, deleted
|
||||||
|
try {
|
||||||
|
if (input.create) {
|
||||||
|
created = await bulkCreate(input.create.users, input.create.groups)
|
||||||
|
}
|
||||||
|
if (input.delete) {
|
||||||
|
deleted = await bulkDelete(input.delete.userIds, currentUserId)
|
||||||
|
}
|
||||||
|
} catch (err: any) {
|
||||||
|
ctx.throw(400, err?.message || err)
|
||||||
|
}
|
||||||
|
ctx.body = { created, deleted } as BulkUserResponse
|
||||||
}
|
}
|
||||||
|
|
||||||
const parseBooleanParam = (param: any) => {
|
const parseBooleanParam = (param: any) => {
|
||||||
|
@ -85,7 +102,7 @@ export const adminUser = async (ctx: any) => {
|
||||||
// always bust checklist beforehand, if an error occurs but can proceed, don't get
|
// always bust checklist beforehand, if an error occurs but can proceed, don't get
|
||||||
// stuck in a cycle
|
// stuck in a cycle
|
||||||
await cache.bustCache(cache.CacheKeys.CHECKLIST)
|
await cache.bustCache(cache.CacheKeys.CHECKLIST)
|
||||||
const finalUser = await users.save(user, {
|
const finalUser = await userSdk.save(user, {
|
||||||
hashPassword,
|
hashPassword,
|
||||||
requirePassword,
|
requirePassword,
|
||||||
})
|
})
|
||||||
|
@ -107,7 +124,7 @@ export const adminUser = async (ctx: any) => {
|
||||||
export const countByApp = async (ctx: any) => {
|
export const countByApp = async (ctx: any) => {
|
||||||
const appId = ctx.params.appId
|
const appId = ctx.params.appId
|
||||||
try {
|
try {
|
||||||
ctx.body = await users.countUsersByApp(appId)
|
ctx.body = await userSdk.countUsersByApp(appId)
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
ctx.throw(err.status || 400, err)
|
ctx.throw(err.status || 400, err)
|
||||||
}
|
}
|
||||||
|
@ -119,28 +136,15 @@ export const destroy = async (ctx: any) => {
|
||||||
ctx.throw(400, "Unable to delete self.")
|
ctx.throw(400, "Unable to delete self.")
|
||||||
}
|
}
|
||||||
|
|
||||||
await users.destroy(id, ctx.user)
|
await userSdk.destroy(id, ctx.user)
|
||||||
|
|
||||||
ctx.body = {
|
ctx.body = {
|
||||||
message: `User ${id} deleted.`,
|
message: `User ${id} deleted.`,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const bulkDelete = async (ctx: any) => {
|
|
||||||
const { userIds } = ctx.request.body as BulkDeleteUsersRequest
|
|
||||||
if (userIds?.indexOf(ctx.user._id) !== -1) {
|
|
||||||
ctx.throw(400, "Unable to delete self.")
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
ctx.body = await users.bulkDelete(userIds)
|
|
||||||
} catch (err) {
|
|
||||||
ctx.throw(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const search = async (ctx: any) => {
|
export const search = async (ctx: any) => {
|
||||||
const paginated = await users.paginatedUsers(ctx.request.body)
|
const paginated = await userSdk.paginatedUsers(ctx.request.body)
|
||||||
// user hashed password shouldn't ever be returned
|
// user hashed password shouldn't ever be returned
|
||||||
for (let user of paginated.data) {
|
for (let user of paginated.data) {
|
||||||
if (user) {
|
if (user) {
|
||||||
|
@ -152,7 +156,7 @@ export const search = async (ctx: any) => {
|
||||||
|
|
||||||
// called internally by app server user fetch
|
// called internally by app server user fetch
|
||||||
export const fetch = async (ctx: any) => {
|
export const fetch = async (ctx: any) => {
|
||||||
const all = await users.allUsers()
|
const all = await userSdk.allUsers()
|
||||||
// user hashed password shouldn't ever be returned
|
// user hashed password shouldn't ever be returned
|
||||||
for (let user of all) {
|
for (let user of all) {
|
||||||
if (user) {
|
if (user) {
|
||||||
|
@ -164,7 +168,7 @@ export const fetch = async (ctx: any) => {
|
||||||
|
|
||||||
// called internally by app server user find
|
// called internally by app server user find
|
||||||
export const find = async (ctx: any) => {
|
export const find = async (ctx: any) => {
|
||||||
ctx.body = await users.getUser(ctx.params.id)
|
ctx.body = await userSdk.getUser(ctx.params.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const tenantUserLookup = async (ctx: any) => {
|
export const tenantUserLookup = async (ctx: any) => {
|
||||||
|
@ -179,7 +183,7 @@ export const tenantUserLookup = async (ctx: any) => {
|
||||||
|
|
||||||
export const invite = async (ctx: any) => {
|
export const invite = async (ctx: any) => {
|
||||||
const request = ctx.request.body as InviteUserRequest
|
const request = ctx.request.body as InviteUserRequest
|
||||||
const response = await users.invite([request])
|
const response = await userSdk.invite([request])
|
||||||
|
|
||||||
// explicitly throw for single user invite
|
// explicitly throw for single user invite
|
||||||
if (response.unsuccessful.length) {
|
if (response.unsuccessful.length) {
|
||||||
|
@ -198,7 +202,7 @@ export const invite = async (ctx: any) => {
|
||||||
|
|
||||||
export const inviteMultiple = async (ctx: any) => {
|
export const inviteMultiple = async (ctx: any) => {
|
||||||
const request = ctx.request.body as InviteUsersRequest
|
const request = ctx.request.body as InviteUsersRequest
|
||||||
ctx.body = await users.invite(request)
|
ctx.body = await userSdk.invite(request)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const inviteAccept = async (ctx: any) => {
|
export const inviteAccept = async (ctx: any) => {
|
||||||
|
@ -207,7 +211,7 @@ export const inviteAccept = async (ctx: any) => {
|
||||||
// info is an extension of the user object that was stored by global
|
// info is an extension of the user object that was stored by global
|
||||||
const { email, info }: any = await checkInviteCode(inviteCode)
|
const { email, info }: any = await checkInviteCode(inviteCode)
|
||||||
ctx.body = await tenancy.doInTenant(info.tenantId, async () => {
|
ctx.body = await tenancy.doInTenant(info.tenantId, async () => {
|
||||||
const saved = await users.save({
|
const saved = await userSdk.save({
|
||||||
firstName,
|
firstName,
|
||||||
lastName,
|
lastName,
|
||||||
password,
|
password,
|
||||||
|
|
|
@ -97,16 +97,16 @@ describe("/api/global/users", () => {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe("bulkCreate", () => {
|
describe("bulk (create)", () => {
|
||||||
it("should ignore users existing in the same tenant", async () => {
|
it("should ignore users existing in the same tenant", async () => {
|
||||||
const user = await config.createUser()
|
const user = await config.createUser()
|
||||||
jest.clearAllMocks()
|
jest.clearAllMocks()
|
||||||
|
|
||||||
const response = await api.users.bulkCreateUsers([user])
|
const response = await api.users.bulkCreateUsers([user])
|
||||||
|
|
||||||
expect(response.successful.length).toBe(0)
|
expect(response.created?.successful.length).toBe(0)
|
||||||
expect(response.unsuccessful.length).toBe(1)
|
expect(response.created?.unsuccessful.length).toBe(1)
|
||||||
expect(response.unsuccessful[0].email).toBe(user.email)
|
expect(response.created?.unsuccessful[0].email).toBe(user.email)
|
||||||
expect(events.user.created).toBeCalledTimes(0)
|
expect(events.user.created).toBeCalledTimes(0)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -117,9 +117,9 @@ describe("/api/global/users", () => {
|
||||||
await tenancy.doInTenant(TENANT_1, async () => {
|
await tenancy.doInTenant(TENANT_1, async () => {
|
||||||
const response = await api.users.bulkCreateUsers([user])
|
const response = await api.users.bulkCreateUsers([user])
|
||||||
|
|
||||||
expect(response.successful.length).toBe(0)
|
expect(response.created?.successful.length).toBe(0)
|
||||||
expect(response.unsuccessful.length).toBe(1)
|
expect(response.created?.unsuccessful.length).toBe(1)
|
||||||
expect(response.unsuccessful[0].email).toBe(user.email)
|
expect(response.created?.unsuccessful[0].email).toBe(user.email)
|
||||||
expect(events.user.created).toBeCalledTimes(0)
|
expect(events.user.created).toBeCalledTimes(0)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -132,24 +132,24 @@ describe("/api/global/users", () => {
|
||||||
|
|
||||||
const response = await api.users.bulkCreateUsers([user])
|
const response = await api.users.bulkCreateUsers([user])
|
||||||
|
|
||||||
expect(response.successful.length).toBe(0)
|
expect(response.created?.successful.length).toBe(0)
|
||||||
expect(response.unsuccessful.length).toBe(1)
|
expect(response.created?.unsuccessful.length).toBe(1)
|
||||||
expect(response.unsuccessful[0].email).toBe(user.email)
|
expect(response.created?.unsuccessful[0].email).toBe(user.email)
|
||||||
expect(events.user.created).toBeCalledTimes(0)
|
expect(events.user.created).toBeCalledTimes(0)
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should be able to bulkCreate users", async () => {
|
it("should be able to bulk create users", async () => {
|
||||||
const builder = structures.users.builderUser()
|
const builder = structures.users.builderUser()
|
||||||
const admin = structures.users.adminUser()
|
const admin = structures.users.adminUser()
|
||||||
const user = structures.users.user()
|
const user = structures.users.user()
|
||||||
|
|
||||||
const response = await api.users.bulkCreateUsers([builder, admin, user])
|
const response = await api.users.bulkCreateUsers([builder, admin, user])
|
||||||
|
|
||||||
expect(response.successful.length).toBe(3)
|
expect(response.created?.successful.length).toBe(3)
|
||||||
expect(response.successful[0].email).toBe(builder.email)
|
expect(response.created?.successful[0].email).toBe(builder.email)
|
||||||
expect(response.successful[1].email).toBe(admin.email)
|
expect(response.created?.successful[1].email).toBe(admin.email)
|
||||||
expect(response.successful[2].email).toBe(user.email)
|
expect(response.created?.successful[2].email).toBe(user.email)
|
||||||
expect(response.unsuccessful.length).toBe(0)
|
expect(response.created?.unsuccessful.length).toBe(0)
|
||||||
expect(events.user.created).toBeCalledTimes(3)
|
expect(events.user.created).toBeCalledTimes(3)
|
||||||
expect(events.user.permissionAdminAssigned).toBeCalledTimes(1)
|
expect(events.user.permissionAdminAssigned).toBeCalledTimes(1)
|
||||||
expect(events.user.permissionBuilderAssigned).toBeCalledTimes(2)
|
expect(events.user.permissionBuilderAssigned).toBeCalledTimes(2)
|
||||||
|
@ -420,33 +420,30 @@ describe("/api/global/users", () => {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe("bulkDelete", () => {
|
describe("bulk (delete)", () => {
|
||||||
it("should not be able to bulkDelete current user", async () => {
|
it("should not be able to bulk delete current user", async () => {
|
||||||
const user = await config.defaultUser!
|
const user = await config.defaultUser!
|
||||||
const request = { userIds: [user._id!] }
|
|
||||||
|
|
||||||
const response = await api.users.bulkDeleteUsers(request, 400)
|
const response = await api.users.bulkDeleteUsers([user._id!], 400)
|
||||||
|
|
||||||
expect(response.body.message).toBe("Unable to delete self.")
|
expect(response.message).toBe("Unable to delete self.")
|
||||||
expect(events.user.deleted).not.toBeCalled()
|
expect(events.user.deleted).not.toBeCalled()
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should not be able to bulkDelete account owner", async () => {
|
it("should not be able to bulk delete account owner", async () => {
|
||||||
const user = await config.createUser()
|
const user = await config.createUser()
|
||||||
const account = structures.accounts.cloudAccount()
|
const account = structures.accounts.cloudAccount()
|
||||||
account.budibaseUserId = user._id!
|
account.budibaseUserId = user._id!
|
||||||
mocks.accounts.getAccountByTenantId.mockReturnValue(account)
|
mocks.accounts.getAccountByTenantId.mockReturnValue(account)
|
||||||
|
|
||||||
const request = { userIds: [user._id!] }
|
const response = await api.users.bulkDeleteUsers([user._id!])
|
||||||
|
|
||||||
const response = await api.users.bulkDeleteUsers(request)
|
expect(response.deleted?.successful.length).toBe(0)
|
||||||
|
expect(response.deleted?.unsuccessful.length).toBe(1)
|
||||||
expect(response.body.successful.length).toBe(0)
|
expect(response.deleted?.unsuccessful[0].reason).toBe(
|
||||||
expect(response.body.unsuccessful.length).toBe(1)
|
|
||||||
expect(response.body.unsuccessful[0].reason).toBe(
|
|
||||||
"Account holder cannot be deleted"
|
"Account holder cannot be deleted"
|
||||||
)
|
)
|
||||||
expect(response.body.unsuccessful[0]._id).toBe(user._id)
|
expect(response.deleted?.unsuccessful[0]._id).toBe(user._id)
|
||||||
expect(events.user.deleted).not.toBeCalled()
|
expect(events.user.deleted).not.toBeCalled()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -462,12 +459,14 @@ describe("/api/global/users", () => {
|
||||||
admin,
|
admin,
|
||||||
user,
|
user,
|
||||||
])
|
])
|
||||||
const request = { userIds: createdUsers.successful.map(u => u._id!) }
|
|
||||||
|
|
||||||
const response = await api.users.bulkDeleteUsers(request)
|
const toDelete = createdUsers.created?.successful.map(
|
||||||
|
u => u._id!
|
||||||
|
) as string[]
|
||||||
|
const response = await api.users.bulkDeleteUsers(toDelete)
|
||||||
|
|
||||||
expect(response.body.successful.length).toBe(3)
|
expect(response.deleted?.successful.length).toBe(3)
|
||||||
expect(response.body.unsuccessful.length).toBe(0)
|
expect(response.deleted?.unsuccessful.length).toBe(0)
|
||||||
expect(events.user.deleted).toBeCalledTimes(3)
|
expect(events.user.deleted).toBeCalledTimes(3)
|
||||||
expect(events.user.permissionAdminRemoved).toBeCalledTimes(1)
|
expect(events.user.permissionAdminRemoved).toBeCalledTimes(1)
|
||||||
expect(events.user.permissionBuilderRemoved).toBeCalledTimes(2)
|
expect(events.user.permissionBuilderRemoved).toBeCalledTimes(2)
|
||||||
|
|
|
@ -56,16 +56,15 @@ router
|
||||||
controller.save
|
controller.save
|
||||||
)
|
)
|
||||||
.post(
|
.post(
|
||||||
"/api/global/users/bulkCreate",
|
"/api/global/users/bulk",
|
||||||
adminOnly,
|
adminOnly,
|
||||||
users.buildUserBulkSaveValidation(),
|
users.buildUserBulkUserValidation(),
|
||||||
controller.bulkCreate
|
controller.bulkUpdate
|
||||||
)
|
)
|
||||||
|
|
||||||
.get("/api/global/users", builderOrAdmin, controller.fetch)
|
.get("/api/global/users", builderOrAdmin, controller.fetch)
|
||||||
.post("/api/global/users/search", builderOrAdmin, controller.search)
|
.post("/api/global/users/search", builderOrAdmin, controller.search)
|
||||||
.delete("/api/global/users/:id", adminOnly, controller.destroy)
|
.delete("/api/global/users/:id", adminOnly, controller.destroy)
|
||||||
.post("/api/global/users/bulkDelete", adminOnly, controller.bulkDelete)
|
|
||||||
.get("/api/global/users/count/:appId", builderOrAdmin, controller.countByApp)
|
.get("/api/global/users/count/:appId", builderOrAdmin, controller.countByApp)
|
||||||
.get("/api/global/roles/:appId")
|
.get("/api/global/roles/:appId")
|
||||||
.post(
|
.post(
|
||||||
|
|
|
@ -28,7 +28,7 @@ export const buildUserSaveValidation = (isSelf = false) => {
|
||||||
return joiValidator.body(Joi.object(schema).required().unknown(true))
|
return joiValidator.body(Joi.object(schema).required().unknown(true))
|
||||||
}
|
}
|
||||||
|
|
||||||
export const buildUserBulkSaveValidation = (isSelf = false) => {
|
export const buildUserBulkUserValidation = (isSelf = false) => {
|
||||||
if (!isSelf) {
|
if (!isSelf) {
|
||||||
schema = {
|
schema = {
|
||||||
...schema,
|
...schema,
|
||||||
|
@ -36,10 +36,15 @@ export const buildUserBulkSaveValidation = (isSelf = false) => {
|
||||||
_rev: Joi.string(),
|
_rev: Joi.string(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let bulkSaveSchema = {
|
let bulkSchema = {
|
||||||
|
create: Joi.object({
|
||||||
groups: Joi.array().optional(),
|
groups: Joi.array().optional(),
|
||||||
users: Joi.array().items(Joi.object(schema).required().unknown(true)),
|
users: Joi.array().items(Joi.object(schema).required().unknown(true)),
|
||||||
|
}),
|
||||||
|
delete: Joi.object({
|
||||||
|
userIds: Joi.array().items(Joi.string()),
|
||||||
|
}),
|
||||||
}
|
}
|
||||||
|
|
||||||
return joiValidator.body(Joi.object(bulkSaveSchema).required().unknown(true))
|
return joiValidator.body(Joi.object(bulkSchema).required().unknown(true))
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,8 +19,7 @@ import {
|
||||||
import {
|
import {
|
||||||
AccountMetadata,
|
AccountMetadata,
|
||||||
AllDocsResponse,
|
AllDocsResponse,
|
||||||
BulkCreateUsersResponse,
|
BulkUserResponse,
|
||||||
BulkDeleteUsersResponse,
|
|
||||||
CloudAccount,
|
CloudAccount,
|
||||||
CreateUserResponse,
|
CreateUserResponse,
|
||||||
InviteUsersRequest,
|
InviteUsersRequest,
|
||||||
|
@ -347,7 +346,7 @@ const searchExistingEmails = async (emails: string[]) => {
|
||||||
export const bulkCreate = async (
|
export const bulkCreate = async (
|
||||||
newUsersRequested: User[],
|
newUsersRequested: User[],
|
||||||
groups: string[]
|
groups: string[]
|
||||||
): Promise<BulkCreateUsersResponse> => {
|
): Promise<BulkUserResponse["created"]> => {
|
||||||
const db = tenancy.getGlobalDB()
|
const db = tenancy.getGlobalDB()
|
||||||
const tenantId = tenancy.getTenantId()
|
const tenantId = tenancy.getTenantId()
|
||||||
|
|
||||||
|
@ -436,10 +435,10 @@ const getAccountHolderFromUserIds = async (
|
||||||
|
|
||||||
export const bulkDelete = async (
|
export const bulkDelete = async (
|
||||||
userIds: string[]
|
userIds: string[]
|
||||||
): Promise<BulkDeleteUsersResponse> => {
|
): Promise<BulkUserResponse["deleted"]> => {
|
||||||
const db = tenancy.getGlobalDB()
|
const db = tenancy.getGlobalDB()
|
||||||
|
|
||||||
const response: BulkDeleteUsersResponse = {
|
const response: BulkUserResponse["deleted"] = {
|
||||||
successful: [],
|
successful: [],
|
||||||
unsuccessful: [],
|
unsuccessful: [],
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
import {
|
import {
|
||||||
BulkCreateUsersRequest,
|
BulkUserResponse,
|
||||||
BulkCreateUsersResponse,
|
BulkUserRequest,
|
||||||
BulkDeleteUsersRequest,
|
|
||||||
BulkDeleteUsersResponse,
|
|
||||||
InviteUsersRequest,
|
InviteUsersRequest,
|
||||||
User,
|
User,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
|
@ -69,24 +67,26 @@ export class UserAPI {
|
||||||
// BULK
|
// BULK
|
||||||
|
|
||||||
bulkCreateUsers = async (users: User[], groups: any[] = []) => {
|
bulkCreateUsers = async (users: User[], groups: any[] = []) => {
|
||||||
const body: BulkCreateUsersRequest = { users, groups }
|
const body: BulkUserRequest = { create: { users, groups } }
|
||||||
const res = await this.request
|
const res = await this.request
|
||||||
.post(`/api/global/users/bulkCreate`)
|
.post(`/api/global/users/bulk`)
|
||||||
.send(body)
|
.send(body)
|
||||||
.set(this.config.defaultHeaders())
|
.set(this.config.defaultHeaders())
|
||||||
.expect("Content-Type", /json/)
|
.expect("Content-Type", /json/)
|
||||||
.expect(200)
|
.expect(200)
|
||||||
|
|
||||||
return res.body as BulkCreateUsersResponse
|
return res.body as BulkUserResponse
|
||||||
}
|
}
|
||||||
|
|
||||||
bulkDeleteUsers = (body: BulkDeleteUsersRequest, status?: number) => {
|
bulkDeleteUsers = async (userIds: string[], status?: number) => {
|
||||||
return this.request
|
const body: BulkUserRequest = { delete: { userIds } }
|
||||||
.post(`/api/global/users/bulkDelete`)
|
const res = await this.request
|
||||||
|
.post(`/api/global/users/bulk`)
|
||||||
.send(body)
|
.send(body)
|
||||||
.set(this.config.defaultHeaders())
|
.set(this.config.defaultHeaders())
|
||||||
.expect("Content-Type", /json/)
|
.expect("Content-Type", /json/)
|
||||||
.expect(status ? status : 200)
|
.expect(status ? status : 200)
|
||||||
|
return res.body as BulkUserResponse
|
||||||
}
|
}
|
||||||
|
|
||||||
// USER
|
// USER
|
||||||
|
|
Loading…
Reference in New Issue