import _ from "lodash"; import { APIPathsCrudParams, APIPathsParamsAllowedTable } from "../../types"; export default async function checks< T extends { [k: string]: any } = { [k: string]: any } >({ table, allowedTables, query, body, method, getMiddleware, postMiddleware, putMiddleware, deleteMiddleware, crudMiddleware, }: APIPathsCrudParams): Promise< Pick, "query" | "body"> & { allowedTable: APIPathsParamsAllowedTable; } > { const allowedTable = allowedTables.find((tbl) => tbl.table == table); if (!allowedTable) { throw new Error(`Can't Access this table: \`${table}\``); } let newQuery = _.cloneDeep(query); let newBody = _.cloneDeep(body); const searchFields = Object.keys(newQuery?.searchQuery?.query || {}); const selectFields = ( newQuery?.searchQuery?.selectFields ? newQuery.searchQuery.selectFields.map((f) => typeof f == "string" ? f : typeof f == "object" ? f.fieldName : undefined ) : undefined )?.filter((f) => typeof f == "string"); const targetFields = [...(searchFields || []), ...(selectFields || [])]; if (method == "GET" && allowedTable.allowedFields) { for (let i = 0; i < targetFields.length; i++) { const fld = targetFields[i]; const allowedFld = allowedTable.allowedFields.find((f) => typeof f == "string" ? f == fld : fld.match(f) ); if (!allowedFld) { throw new Error(`\`${allowedFld}\` field not allowed`); } } } if (method == "GET" && allowedTable.disallowedFields) { for (let i = 0; i < targetFields.length; i++) { const fld = targetFields[i]; const disallowedFld = allowedTable.disallowedFields.find((f) => typeof f == "string" ? f == fld : fld.match(f) ); if (disallowedFld) { throw new Error(`\`${disallowedFld}\` field not allowed`); } } } if (method == "GET" && getMiddleware) { newQuery = await getMiddleware({ query: newQuery || ({} as any) }); } if (method !== "GET" && crudMiddleware) { const middRes = await crudMiddleware({ body: newBody || ({} as any), query: newQuery || {}, }); newBody = _.merge(newBody, middRes); } if (method == "POST" && postMiddleware) { const middRes = await postMiddleware({ body: newBody || ({} as any), query: newQuery || {}, }); newBody = _.merge(newBody, middRes); } if (method == "PUT" && putMiddleware) { const middRes = await putMiddleware({ body: newBody || ({} as any), query: newQuery || {}, }); newBody = _.merge(newBody, middRes); } if (method == "DELETE" && deleteMiddleware) { const middRes = await deleteMiddleware({ body: newBody || ({} as any), query: newQuery || {}, }); newBody = _.merge(newBody, middRes); } if (newQuery?.searchQuery?.join) { for (let i = 0; i < newQuery.searchQuery.join.length; i++) { const join = newQuery.searchQuery.join[i]; const joinTableName = join.tableName; const selectFields = join.selectFields; if (allowedTables?.[0]) { const allowedJoinTable = allowedTables.find( (t) => t.table == joinTableName ); if (!allowedJoinTable?.table) { throw new Error(`Can't joint \`${joinTableName}\` table`); } const allowedFields = allowedJoinTable.allowedFields; const disallowedFields = allowedJoinTable.disallowedFields; if (selectFields?.[0]) { for (let j = 0; j < selectFields.length; j++) { const selectField = selectFields[j]; const selectFieldName = typeof selectField == "object" ? selectField.field : String(selectField); if ( allowedFields?.[0] && !allowedFields.find( (f) => String(f) == selectFieldName ) ) { throw new Error(`Can't Select this Field!`); } if ( disallowedFields?.[0] && disallowedFields.find( (f) => String(f) == selectFieldName ) ) { throw new Error(`Disallowed Field Selected!`); } } } } } } return { query: newQuery, body: newBody, allowedTable, }; }