prisma-rls
Version:
Prisma client extension for row-level security on any database
135 lines (134 loc) • 4.91 kB
JavaScript
;
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);
}