UNPKG

prisma-rls

Version:

Prisma client extension for row-level security on any database

135 lines (134 loc) 4.91 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.buildFieldsMap = buildFieldsMap; exports.getTransactionClient = getTransactionClient; exports.generateImpossibleWhere = generateImpossibleWhere; exports.isFunction = isFunction; exports.resolvePermissionDefinition = resolvePermissionDefinition; exports.isUniqueField = isUniqueField; exports.getUniqueField = getUniqueField; exports.mergeWhere = mergeWhere; exports.mergeWhereUnique = mergeWhereUnique; exports.mapObjectValues = mapObjectValues; exports.transformValue = transformValue; exports.isObject = isObject; exports.pickByPath = pickByPath; exports.uniqueArray = uniqueArray; exports.lowerFirst = lowerFirst; function buildFieldsMap(dmmf) { const fieldsMap = {}; for (const model of dmmf.datamodel.models) { fieldsMap[model.name] = {}; for (const field of model.fields) { fieldsMap[model.name][field.name] = field; } } return fieldsMap; } function getTransactionClient(prismaClient, allOperationsArgs) { const transaction = allOperationsArgs.__internalParams.transaction; if (transaction && transaction.kind === "itx") { return prismaClient._createItxClient(transaction); } return prismaClient; } function generateImpossibleWhere(fields) { const uniqueField = getUniqueField(fields); switch (uniqueField.type) { case "Boolean": return { [uniqueField.name]: { equals: true, not: { equals: false } } }; case "BigInt": case "Decimal": case "Float": case "Int": return { [uniqueField.name]: { equals: 0, not: { equals: 0 } } }; case "String": return { [uniqueField.name]: { equals: "", not: { equals: "" } } }; case "Bytes": const buffer = Buffer.from([]); return { [uniqueField.name]: { equals: buffer, not: { equals: buffer } } }; case "DateTime": const date = new Date(); return { [uniqueField.name]: { equals: date, not: { equals: date } } }; case "JSON": return { [uniqueField.name]: { equals: 0, not: 0 } }; default: throw new Error(`Couldn't generate impossible where for field type '${uniqueField.type}'`); } } function isFunction(value) { return typeof value === "function"; } async function resolvePermissionDefinition(permissionDefinition, context) { return isFunction(permissionDefinition) ? permissionDefinition(context) : permissionDefinition; } function isUniqueField(fieldDef) { return fieldDef.isId || fieldDef.isUnique; } function getUniqueField(fields) { const fieldDef = Object.values(fields).find(isUniqueField); if (!fieldDef) { throw new Error("Couldn't find primary key or other unique field"); } return fieldDef; } function mergeWhere(first, second) { return first ? { AND: [first, second] } : second; } function mergeWhereUnique(fields, firstUnique, second) { const unique = {}; const rest = {}; for (const [fieldName, fieldValue] of Object.entries(firstUnique)) { const fieldDef = fields[fieldName]; if (isUniqueField(fieldDef)) { unique[fieldName] = fieldValue; } else { rest[fieldName] = fieldValue; } } return { ...unique, AND: [rest, second] }; } async function mapObjectValues(object, iteratee) { const entries = Object.entries(object); const transformedEntries = await Promise.all(entries.map(async ([key, value]) => { return [key, await iteratee([key, value])]; })); return Object.fromEntries(transformedEntries); } async function transformValue(value, callback) { return Array.isArray(value) ? Promise.all(value.map(callback)) : callback(value); } function isObject(value) { return typeof value === "object" && value !== null; } function pickByPath(value, pathExpression) { const result = []; const traverse = (currentValue, pathSegments) => { if (!pathSegments.length) { result.push(currentValue); return; } else if (!isObject(currentValue)) { return; } const [currentSegment, ...restSegments] = pathSegments; if (currentSegment === "*" && Array.isArray(currentValue)) { currentValue.map((item) => traverse(item, restSegments)); } else if (currentSegment === "*") { throw new Error("Wildcards are supported only for arrays"); } else if (currentSegment in currentValue) { traverse(currentValue[currentSegment], restSegments); } }; traverse(value, pathExpression.replace(/^\$\./, "").split(".")); return result; } function uniqueArray(values) { return [...new Set(values)]; } function lowerFirst(string) { return string.charAt(0).toLowerCase() + string.slice(1); }