Validate and return csv
This commit is contained in:
parent
2f9843bd4c
commit
f1a1cf74bc
3 changed files with 64 additions and 21 deletions
|
@ -1,27 +1,34 @@
|
|||
import { cache } from "@budibase/backend-core"
|
||||
import { utils } from "@budibase/shared-core"
|
||||
import { FieldSubtype } from "@budibase/types"
|
||||
import { Document, FieldSubtype } from "@budibase/types"
|
||||
import { InvalidBBRefError } from "./errors"
|
||||
|
||||
export async function processInputBBReferences(
|
||||
value: string,
|
||||
value: string | string[] | { _id: string } | { _id: string }[],
|
||||
subtype: FieldSubtype
|
||||
) {
|
||||
const result = []
|
||||
const ids = value.split(",").map((id: string) => id.trim())
|
||||
): Promise<string> {
|
||||
const result: string[] = []
|
||||
|
||||
switch (subtype) {
|
||||
case FieldSubtype.USER:
|
||||
for (const id of ids) {
|
||||
result.push(await cache.user.getUser(id))
|
||||
if (Array.isArray(value)) {
|
||||
result.push(...value.map(x => (typeof x === "string" ? x : x._id)))
|
||||
} else if (typeof value !== "string") {
|
||||
result.push(value._id)
|
||||
} else {
|
||||
result.push(...value.split(",").map((id: string) => id.trim()))
|
||||
}
|
||||
|
||||
for (const id of result) {
|
||||
const user = await cache.user.getUser(id)
|
||||
if (!user) {
|
||||
throw new InvalidBBRefError(id, FieldSubtype.USER)
|
||||
}
|
||||
}
|
||||
break
|
||||
default:
|
||||
utils.unreachable(subtype)
|
||||
throw utils.unreachable(subtype)
|
||||
}
|
||||
|
||||
if (result.length > 1) {
|
||||
return result
|
||||
}
|
||||
|
||||
return result[0]
|
||||
return result.join(",")
|
||||
}
|
||||
|
|
7
packages/server/src/utilities/rowProcessor/errors.ts
Normal file
7
packages/server/src/utilities/rowProcessor/errors.ts
Normal file
|
@ -0,0 +1,7 @@
|
|||
import { FieldSubtype } from "@budibase/types"
|
||||
|
||||
export class InvalidBBRefError extends Error {
|
||||
constructor(id: string, subtype: FieldSubtype) {
|
||||
super(`Id "${id}" is not valid for the subtype "${subtype}"`)
|
||||
}
|
||||
}
|
|
@ -2,6 +2,7 @@ import * as backendCore from "@budibase/backend-core"
|
|||
import { FieldSubtype, User } from "@budibase/types"
|
||||
import { processInputBBReferences } from "../bbReferenceProcessor"
|
||||
import { generator, structures } from "@budibase/backend-core/tests"
|
||||
import { InvalidBBRefError } from "../errors"
|
||||
|
||||
jest.mock("@budibase/backend-core", (): typeof backendCore => {
|
||||
const actual = jest.requireActual("@budibase/backend-core")
|
||||
|
@ -26,7 +27,7 @@ describe("bbReferenceProcessor", () => {
|
|||
|
||||
describe("processInputBBReferences", () => {
|
||||
describe("subtype user", () => {
|
||||
it("fetches by user id", async () => {
|
||||
it("validate valid string id", async () => {
|
||||
const input = generator.guid()
|
||||
|
||||
const userFromCache = structures.users.user()
|
||||
|
@ -34,29 +35,57 @@ describe("bbReferenceProcessor", () => {
|
|||
|
||||
const result = await processInputBBReferences(input, FieldSubtype.USER)
|
||||
|
||||
expect(result).toEqual(userFromCache)
|
||||
expect(result).toEqual(input)
|
||||
expect(mockedCacheGetUser).toBeCalledTimes(1)
|
||||
expect(mockedCacheGetUser).toBeCalledWith(input)
|
||||
})
|
||||
|
||||
it("fetches by user id when send as csv", async () => {
|
||||
const users: Record<string, User> = {}
|
||||
it("throws an error given an invalid id", async () => {
|
||||
const input = generator.guid()
|
||||
|
||||
await expect(
|
||||
processInputBBReferences(input, FieldSubtype.USER)
|
||||
).rejects.toThrowError(new InvalidBBRefError(input, FieldSubtype.USER))
|
||||
})
|
||||
|
||||
it("validates valid user ids as csv", async () => {
|
||||
const userIds: string[] = []
|
||||
for (let i = 0; i < 5; i++) {
|
||||
const userId = generator.guid()
|
||||
const user = structures.users.user({ _id: userId, userId })
|
||||
mockedCacheGetUser.mockResolvedValueOnce(user)
|
||||
users[userId] = user
|
||||
userIds.push(userId)
|
||||
}
|
||||
|
||||
const input = Object.keys(users).join(" , ")
|
||||
const input = userIds.join(" , ")
|
||||
const result = await processInputBBReferences(input, FieldSubtype.USER)
|
||||
|
||||
expect(result).toEqual(Object.values(users))
|
||||
expect(result).toEqual(userIds.join(","))
|
||||
expect(mockedCacheGetUser).toBeCalledTimes(5)
|
||||
Object.keys(users).forEach(userId => {
|
||||
userIds.forEach(userId => {
|
||||
expect(mockedCacheGetUser).toBeCalledWith(userId)
|
||||
})
|
||||
})
|
||||
|
||||
it("throws an error given an invalid id in a csv", async () => {
|
||||
const userId1 = generator.guid()
|
||||
const userId2 = generator.guid()
|
||||
const userId3 = generator.guid()
|
||||
mockedCacheGetUser.mockResolvedValueOnce(
|
||||
structures.users.user({ _id: userId1 })
|
||||
)
|
||||
mockedCacheGetUser.mockResolvedValueOnce(
|
||||
structures.users.user({ _id: userId2 })
|
||||
)
|
||||
|
||||
const input = [userId1, userId2, userId3].join(" , ")
|
||||
|
||||
await expect(
|
||||
processInputBBReferences(input, FieldSubtype.USER)
|
||||
).rejects.toThrowError(
|
||||
new InvalidBBRefError(userId3, FieldSubtype.USER)
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
Loading…
Reference in a new issue