mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-09-22 13:39:35 +00:00
144 lines
4.8 KiB
TypeScript
144 lines
4.8 KiB
TypeScript
import { Knex } from "knex";
|
|
import { Compare, Filter, parse } from "scim2-parse-filter";
|
|
|
|
import { TableName } from "@app/db/schemas";
|
|
|
|
const appendParentToGroupingOperator = (parentPath: string, filter: Filter) => {
|
|
if (filter.op !== "[]" && filter.op !== "and" && filter.op !== "or" && filter.op !== "not") {
|
|
return { ...filter, attrPath: `${parentPath}.${(filter as Compare).attrPath}` };
|
|
}
|
|
return filter;
|
|
};
|
|
|
|
const processDynamicQuery = (
|
|
rootQuery: Knex.QueryBuilder,
|
|
scimRootFilterAst: Filter,
|
|
getAttributeField: (attr: string) => string | null,
|
|
depth = 0
|
|
) => {
|
|
if (depth > 20) return;
|
|
|
|
const stack = [
|
|
{
|
|
scimFilterAst: scimRootFilterAst,
|
|
query: rootQuery
|
|
}
|
|
];
|
|
|
|
while (stack.length) {
|
|
const { scimFilterAst, query } = stack.pop()!;
|
|
switch (scimFilterAst.op) {
|
|
case "eq": {
|
|
let sanitizedValue = scimFilterAst.compValue;
|
|
const attrPath = getAttributeField(scimFilterAst.attrPath);
|
|
if (attrPath === `${TableName.Users}.email` && typeof sanitizedValue === "string") {
|
|
sanitizedValue = sanitizedValue.toLowerCase();
|
|
}
|
|
if (attrPath) void query.where(attrPath, sanitizedValue);
|
|
break;
|
|
}
|
|
case "pr": {
|
|
const attrPath = getAttributeField(scimFilterAst.attrPath);
|
|
if (attrPath) void query.whereNotNull(attrPath);
|
|
break;
|
|
}
|
|
case "gt": {
|
|
const attrPath = getAttributeField(scimFilterAst.attrPath);
|
|
if (attrPath) void query.where(attrPath, ">", scimFilterAst.compValue);
|
|
break;
|
|
}
|
|
case "ge": {
|
|
const attrPath = getAttributeField(scimFilterAst.attrPath);
|
|
if (attrPath) void query.where(attrPath, ">=", scimFilterAst.compValue);
|
|
break;
|
|
}
|
|
case "lt": {
|
|
const attrPath = getAttributeField(scimFilterAst.attrPath);
|
|
if (attrPath) void query.where(attrPath, "<", scimFilterAst.compValue);
|
|
break;
|
|
}
|
|
case "le": {
|
|
const attrPath = getAttributeField(scimFilterAst.attrPath);
|
|
if (attrPath) void query.where(attrPath, "<=", scimFilterAst.compValue);
|
|
break;
|
|
}
|
|
case "sw": {
|
|
const attrPath = getAttributeField(scimFilterAst.attrPath);
|
|
if (attrPath) void query.whereILike(attrPath, `${scimFilterAst.compValue}%`);
|
|
break;
|
|
}
|
|
case "ew": {
|
|
let sanitizedValue = scimFilterAst.compValue;
|
|
const attrPath = getAttributeField(scimFilterAst.attrPath);
|
|
if (attrPath === `${TableName.Users}.email` && typeof sanitizedValue === "string") {
|
|
sanitizedValue = sanitizedValue.toLowerCase();
|
|
}
|
|
if (attrPath) void query.whereILike(attrPath, `%${sanitizedValue}`);
|
|
break;
|
|
}
|
|
case "co": {
|
|
let sanitizedValue = scimFilterAst.compValue;
|
|
const attrPath = getAttributeField(scimFilterAst.attrPath);
|
|
if (attrPath === `${TableName.Users}.email` && typeof sanitizedValue === "string") {
|
|
sanitizedValue = sanitizedValue.toLowerCase();
|
|
}
|
|
if (attrPath) void query.whereILike(attrPath, `%${sanitizedValue}%`);
|
|
break;
|
|
}
|
|
case "ne": {
|
|
let sanitizedValue = scimFilterAst.compValue;
|
|
const attrPath = getAttributeField(scimFilterAst.attrPath);
|
|
if (attrPath === `${TableName.Users}.email` && typeof sanitizedValue === "string") {
|
|
sanitizedValue = sanitizedValue.toLowerCase();
|
|
}
|
|
if (attrPath) void query.whereNot(attrPath, "=", sanitizedValue);
|
|
break;
|
|
}
|
|
case "and": {
|
|
scimFilterAst.filters.forEach((el) => {
|
|
void query.andWhere((subQueryBuilder) => {
|
|
processDynamicQuery(subQueryBuilder, el, getAttributeField, depth + 1);
|
|
});
|
|
});
|
|
break;
|
|
}
|
|
case "or": {
|
|
scimFilterAst.filters.forEach((el) => {
|
|
void query.orWhere((subQueryBuilder) => {
|
|
processDynamicQuery(subQueryBuilder, el, getAttributeField, depth + 1);
|
|
});
|
|
});
|
|
break;
|
|
}
|
|
case "not": {
|
|
void query.whereNot((subQueryBuilder) => {
|
|
processDynamicQuery(subQueryBuilder, scimFilterAst.filter, getAttributeField, depth + 1);
|
|
});
|
|
break;
|
|
}
|
|
case "[]": {
|
|
void query.where((subQueryBuilder) => {
|
|
processDynamicQuery(
|
|
subQueryBuilder,
|
|
appendParentToGroupingOperator(scimFilterAst.attrPath, scimFilterAst.valFilter),
|
|
getAttributeField,
|
|
depth + 1
|
|
);
|
|
});
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
};
|
|
|
|
export const generateKnexQueryFromScim = (
|
|
rootQuery: Knex.QueryBuilder,
|
|
rootScimFilter: string,
|
|
getAttributeField: (attr: string) => string | null
|
|
) => {
|
|
const scimRootFilterAst = parse(rootScimFilter);
|
|
return processDynamicQuery(rootQuery, scimRootFilterAst, getAttributeField);
|
|
};
|