Validate user column
This commit is contained in:
parent
a514358e57
commit
f22467fa53
|
@ -45,6 +45,11 @@ export function generateGlobalUserID(id?: any) {
|
||||||
return `${DocumentType.USER}${SEPARATOR}${id || newid()}`
|
return `${DocumentType.USER}${SEPARATOR}${id || newid()}`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const isGlobalUserIDRegex = new RegExp(`^${DocumentType.USER}${SEPARATOR}.+`)
|
||||||
|
export function isGlobalUserID(id: string) {
|
||||||
|
return isGlobalUserIDRegex.test(id)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates a new user ID based on the passed in global ID.
|
* Generates a new user ID based on the passed in global ID.
|
||||||
* @param {string} globalId The ID of the global user.
|
* @param {string} globalId The ID of the global user.
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
import { FIELDS } from "constants/backend"
|
import { FIELDS } from "constants/backend"
|
||||||
import { API } from "api"
|
import { API } from "api"
|
||||||
import { parseFile } from "./utils"
|
import { parseFile } from "./utils"
|
||||||
|
import { FieldType } from "@budibase/types"
|
||||||
|
|
||||||
export let rows = []
|
export let rows = []
|
||||||
export let schema = {}
|
export let schema = {}
|
||||||
|
@ -86,10 +87,35 @@
|
||||||
let validateHash = ""
|
let validateHash = ""
|
||||||
let errors = {}
|
let errors = {}
|
||||||
let selectedColumnTypes = {}
|
let selectedColumnTypes = {}
|
||||||
|
let rawRows = []
|
||||||
|
|
||||||
$: displayColumnOptions = Object.keys(schema || {}).filter(column => {
|
$: displayColumnOptions = Object.keys(schema || {}).filter(column => {
|
||||||
return validation[column]
|
return validation[column]
|
||||||
})
|
})
|
||||||
|
|
||||||
|
$: {
|
||||||
|
rows = []
|
||||||
|
|
||||||
|
for (const row of rawRows) {
|
||||||
|
const castedRow = { ...row }
|
||||||
|
for (const fieldSchema of Object.values(schema || {})) {
|
||||||
|
if (fieldSchema.type === FieldType.BB_REFERENCE) {
|
||||||
|
try {
|
||||||
|
castedRow[fieldSchema.name] = JSON.parse(
|
||||||
|
row[fieldSchema.name].replace(/'/g, '"')
|
||||||
|
)
|
||||||
|
} catch {
|
||||||
|
console.warn("Not a valid json", {
|
||||||
|
field: fieldSchema.name,
|
||||||
|
data: row[fieldSchema.name],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rows.push(castedRow)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$: {
|
$: {
|
||||||
// binding in consumer is causing double renders here
|
// binding in consumer is causing double renders here
|
||||||
const newValidateHash = JSON.stringify(rows) + JSON.stringify(schema)
|
const newValidateHash = JSON.stringify(rows) + JSON.stringify(schema)
|
||||||
|
@ -107,7 +133,7 @@
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await parseFile(e)
|
const response = await parseFile(e)
|
||||||
rows = response.rows
|
rawRows = response.rows
|
||||||
schema = response.schema
|
schema = response.schema
|
||||||
fileName = response.fileName
|
fileName = response.fileName
|
||||||
selectedColumnTypes = Object.entries(response.schema).reduce(
|
selectedColumnTypes = Object.entries(response.schema).reduce(
|
||||||
|
|
|
@ -1,9 +1,12 @@
|
||||||
|
import { FieldSubtype } from "@budibase/types"
|
||||||
import { FieldTypes } from "../constants"
|
import { FieldTypes } from "../constants"
|
||||||
import { ValidColumnNameRegex } from "@budibase/shared-core"
|
import { ValidColumnNameRegex, utils } from "@budibase/shared-core"
|
||||||
|
import { db } from "@budibase/backend-core"
|
||||||
|
|
||||||
interface SchemaColumn {
|
interface SchemaColumn {
|
||||||
readonly name: string
|
readonly name: string
|
||||||
readonly type: FieldTypes
|
readonly type: FieldTypes
|
||||||
|
readonly subtype: FieldSubtype
|
||||||
readonly autocolumn?: boolean
|
readonly autocolumn?: boolean
|
||||||
readonly constraints?: {
|
readonly constraints?: {
|
||||||
presence: boolean
|
presence: boolean
|
||||||
|
@ -77,8 +80,14 @@ export function validate(rows: Rows, schema: Schema): ValidationResults {
|
||||||
rows.forEach(row => {
|
rows.forEach(row => {
|
||||||
Object.entries(row).forEach(([columnName, columnData]) => {
|
Object.entries(row).forEach(([columnName, columnData]) => {
|
||||||
const columnType = schema[columnName]?.type
|
const columnType = schema[columnName]?.type
|
||||||
|
const columnSubtype = schema[columnName]?.subtype
|
||||||
const isAutoColumn = schema[columnName]?.autocolumn
|
const isAutoColumn = schema[columnName]?.autocolumn
|
||||||
|
|
||||||
|
// If the column had an invalid value we don't want to override it
|
||||||
|
if (results.schemaValidation[columnName] === false) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// If the columnType is not a string, then it's not present in the schema, and should be added to the invalid columns array
|
// If the columnType is not a string, then it's not present in the schema, and should be added to the invalid columns array
|
||||||
if (typeof columnType !== "string") {
|
if (typeof columnType !== "string") {
|
||||||
results.invalidColumns.push(columnName)
|
results.invalidColumns.push(columnName)
|
||||||
|
@ -112,6 +121,11 @@ export function validate(rows: Rows, schema: Schema): ValidationResults {
|
||||||
isNaN(new Date(columnData).getTime())
|
isNaN(new Date(columnData).getTime())
|
||||||
) {
|
) {
|
||||||
results.schemaValidation[columnName] = false
|
results.schemaValidation[columnName] = false
|
||||||
|
} else if (
|
||||||
|
columnType === FieldTypes.BB_REFERENCE &&
|
||||||
|
!isValidBBReference(columnData, columnSubtype)
|
||||||
|
) {
|
||||||
|
results.schemaValidation[columnName] = false
|
||||||
} else {
|
} else {
|
||||||
results.schemaValidation[columnName] = true
|
results.schemaValidation[columnName] = true
|
||||||
}
|
}
|
||||||
|
@ -155,3 +169,37 @@ export function parse(rows: Rows, schema: Schema): Rows {
|
||||||
return parsedRow
|
return parsedRow
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isValidBBReference(
|
||||||
|
columnData: any,
|
||||||
|
columnSubtype: FieldSubtype
|
||||||
|
): boolean {
|
||||||
|
switch (columnSubtype) {
|
||||||
|
case FieldSubtype.USER:
|
||||||
|
case FieldSubtype.USERS:
|
||||||
|
if (!columnData) {
|
||||||
|
// Empty columns are valid by default
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Array.isArray(columnData)) {
|
||||||
|
// It must be an array field
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (columnSubtype === FieldSubtype.USER && columnData.length > 1) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const d of columnData) {
|
||||||
|
if (!db.isGlobalUserID(d._id)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw utils.unreachable(columnSubtype)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue