node_modules ignore

This commit is contained in:
2025-05-08 23:43:47 +02:00
parent e19d52f172
commit 4574544c9f
65041 changed files with 10593536 additions and 0 deletions

View File

@@ -0,0 +1,33 @@
import { CurriedFunction1 } from 'lodash';
import * as visitors from './visitors';
import * as sanitizers from './sanitizers';
import type { Model, Data } from '../types';
export interface Options {
auth?: unknown;
}
export interface Sanitizer {
(schema: Model): CurriedFunction1<Data, Promise<Data>>;
}
export interface SanitizeFunc {
(data: unknown, schema: Model, options?: Options): Promise<unknown>;
}
export interface APIOptions {
sanitizers?: Sanitizers;
getModel: (model: string) => Model;
}
export interface Sanitizers {
input?: Sanitizer[];
output?: Sanitizer[];
}
declare const createAPISanitizers: (opts: APIOptions) => {
input: SanitizeFunc;
output: SanitizeFunc;
query: (query: Record<string, unknown>, schema: Model, { auth }?: Options) => Promise<Record<string, unknown>>;
filters: SanitizeFunc;
sort: SanitizeFunc;
fields: SanitizeFunc;
populate: SanitizeFunc;
};
export { createAPISanitizers, sanitizers, visitors };
export type APISanitiers = ReturnType<typeof createAPISanitizers>;
//# sourceMappingURL=index.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/sanitize/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,QAAQ,CAAC;AAM1C,OAAO,KAAK,QAAQ,MAAM,YAAY,CAAC;AACvC,OAAO,KAAK,UAAU,MAAM,cAAc,CAAC;AAI3C,OAAO,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAE5C,MAAM,WAAW,OAAO;IACtB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,SAAS;IACxB,CAAC,MAAM,EAAE,KAAK,GAAG,gBAAgB,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;CACxD;AACD,MAAM,WAAW,YAAY;IAC3B,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CACrE;AAED,MAAM,WAAW,UAAU;IACzB,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,KAAK,CAAC;CACpC;AAED,MAAM,WAAW,UAAU;IACzB,KAAK,CAAC,EAAE,SAAS,EAAE,CAAC;IACpB,MAAM,CAAC,EAAE,SAAS,EAAE,CAAC;CACtB;AAED,QAAA,MAAM,mBAAmB,SAAU,UAAU;;;mBA+DlC,OAAO,MAAM,EAAE,OAAO,CAAC,UACtB,KAAK,aACH,OAAO;;;;;CA+FpB,CAAC;AAEF,OAAO,EAAE,mBAAmB,EAAE,UAAU,EAAE,QAAQ,EAAE,CAAC;AAErD,MAAM,MAAM,YAAY,GAAG,UAAU,CAAC,OAAO,mBAAmB,CAAC,CAAC"}

View File

@@ -0,0 +1,195 @@
'use strict';
var fp = require('lodash/fp');
var contentTypes = require('../content-types.js');
var async = require('../async.js');
var index = require('./visitors/index.js');
var sanitizers = require('./sanitizers.js');
var traverseEntity = require('../traverse-entity.js');
var queryFilters = require('../traverse/query-filters.js');
var querySort = require('../traverse/query-sort.js');
var queryPopulate = require('../traverse/query-populate.js');
require('../traverse/query-fields.js');
var removeRestrictedFields = require('./visitors/remove-restricted-fields.js');
var removeRestrictedRelations = require('./visitors/remove-restricted-relations.js');
const createAPISanitizers = (opts)=>{
const { getModel } = opts;
const sanitizeInput = (data, schema, { auth } = {})=>{
if (!schema) {
throw new Error('Missing schema in sanitizeInput');
}
if (fp.isArray(data)) {
return Promise.all(data.map((entry)=>sanitizeInput(entry, schema, {
auth
})));
}
const nonWritableAttributes = contentTypes.getNonWritableAttributes(schema);
const transforms = [
// Remove first level ID in inputs
fp.omit(contentTypes.constants.ID_ATTRIBUTE),
fp.omit(contentTypes.constants.DOC_ID_ATTRIBUTE),
// Remove non-writable attributes
traverseEntity(removeRestrictedFields(nonWritableAttributes), {
schema,
getModel
})
];
if (auth) {
// Remove restricted relations
transforms.push(traverseEntity(removeRestrictedRelations(auth), {
schema,
getModel
}));
}
// Apply sanitizers from registry if exists
opts?.sanitizers?.input?.forEach((sanitizer)=>transforms.push(sanitizer(schema)));
return async.pipe(...transforms)(data);
};
const sanitizeOutput = async (data, schema, { auth } = {})=>{
if (!schema) {
throw new Error('Missing schema in sanitizeOutput');
}
if (fp.isArray(data)) {
const res = new Array(data.length);
for(let i = 0; i < data.length; i += 1){
res[i] = await sanitizeOutput(data[i], schema, {
auth
});
}
return res;
}
const transforms = [
(data)=>sanitizers.defaultSanitizeOutput({
schema,
getModel
}, data)
];
if (auth) {
transforms.push(traverseEntity(removeRestrictedRelations(auth), {
schema,
getModel
}));
}
// Apply sanitizers from registry if exists
opts?.sanitizers?.output?.forEach((sanitizer)=>transforms.push(sanitizer(schema)));
return async.pipe(...transforms)(data);
};
const sanitizeQuery = async (query, schema, { auth } = {})=>{
if (!schema) {
throw new Error('Missing schema in sanitizeQuery');
}
const { filters, sort, fields, populate } = query;
const sanitizedQuery = fp.cloneDeep(query);
if (filters) {
Object.assign(sanitizedQuery, {
filters: await sanitizeFilters(filters, schema, {
auth
})
});
}
if (sort) {
Object.assign(sanitizedQuery, {
sort: await sanitizeSort(sort, schema, {
auth
})
});
}
if (fields) {
Object.assign(sanitizedQuery, {
fields: await sanitizeFields(fields, schema)
});
}
if (populate) {
Object.assign(sanitizedQuery, {
populate: await sanitizePopulate(populate, schema)
});
}
return sanitizedQuery;
};
const sanitizeFilters = (filters, schema, { auth } = {})=>{
if (!schema) {
throw new Error('Missing schema in sanitizeFilters');
}
if (fp.isArray(filters)) {
return Promise.all(filters.map((filter)=>sanitizeFilters(filter, schema, {
auth
})));
}
const transforms = [
sanitizers.defaultSanitizeFilters({
schema,
getModel
})
];
if (auth) {
transforms.push(queryFilters(removeRestrictedRelations(auth), {
schema,
getModel
}));
}
return async.pipe(...transforms)(filters);
};
const sanitizeSort = (sort, schema, { auth } = {})=>{
if (!schema) {
throw new Error('Missing schema in sanitizeSort');
}
const transforms = [
sanitizers.defaultSanitizeSort({
schema,
getModel
})
];
if (auth) {
transforms.push(querySort(removeRestrictedRelations(auth), {
schema,
getModel
}));
}
return async.pipe(...transforms)(sort);
};
const sanitizeFields = (fields, schema)=>{
if (!schema) {
throw new Error('Missing schema in sanitizeFields');
}
const transforms = [
sanitizers.defaultSanitizeFields({
schema,
getModel
})
];
return async.pipe(...transforms)(fields);
};
const sanitizePopulate = (populate, schema, { auth } = {})=>{
if (!schema) {
throw new Error('Missing schema in sanitizePopulate');
}
const transforms = [
sanitizers.defaultSanitizePopulate({
schema,
getModel
})
];
if (auth) {
transforms.push(queryPopulate(removeRestrictedRelations(auth), {
schema,
getModel
}));
}
return async.pipe(...transforms)(populate);
};
return {
input: sanitizeInput,
output: sanitizeOutput,
query: sanitizeQuery,
filters: sanitizeFilters,
sort: sanitizeSort,
fields: sanitizeFields,
populate: sanitizePopulate
};
};
exports.visitors = index;
exports.sanitizers = sanitizers;
exports.createAPISanitizers = createAPISanitizers;
//# sourceMappingURL=index.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,194 @@
import { isArray, omit, cloneDeep } from 'lodash/fp';
import { getNonWritableAttributes, constants } from '../content-types.mjs';
import { pipe } from '../async.mjs';
import * as index from './visitors/index.mjs';
export { index as visitors };
import { defaultSanitizeFilters, defaultSanitizeSort, defaultSanitizeFields, defaultSanitizePopulate, defaultSanitizeOutput } from './sanitizers.mjs';
import * as sanitizers from './sanitizers.mjs';
export { sanitizers };
import traverseEntity from '../traverse-entity.mjs';
import traverseQueryFilters from '../traverse/query-filters.mjs';
import traverseQuerySort from '../traverse/query-sort.mjs';
import traverseQueryPopulate from '../traverse/query-populate.mjs';
import '../traverse/query-fields.mjs';
import removeRestrictedFields from './visitors/remove-restricted-fields.mjs';
import removeRestrictedRelations from './visitors/remove-restricted-relations.mjs';
const createAPISanitizers = (opts)=>{
const { getModel } = opts;
const sanitizeInput = (data, schema, { auth } = {})=>{
if (!schema) {
throw new Error('Missing schema in sanitizeInput');
}
if (isArray(data)) {
return Promise.all(data.map((entry)=>sanitizeInput(entry, schema, {
auth
})));
}
const nonWritableAttributes = getNonWritableAttributes(schema);
const transforms = [
// Remove first level ID in inputs
omit(constants.ID_ATTRIBUTE),
omit(constants.DOC_ID_ATTRIBUTE),
// Remove non-writable attributes
traverseEntity(removeRestrictedFields(nonWritableAttributes), {
schema,
getModel
})
];
if (auth) {
// Remove restricted relations
transforms.push(traverseEntity(removeRestrictedRelations(auth), {
schema,
getModel
}));
}
// Apply sanitizers from registry if exists
opts?.sanitizers?.input?.forEach((sanitizer)=>transforms.push(sanitizer(schema)));
return pipe(...transforms)(data);
};
const sanitizeOutput = async (data, schema, { auth } = {})=>{
if (!schema) {
throw new Error('Missing schema in sanitizeOutput');
}
if (isArray(data)) {
const res = new Array(data.length);
for(let i = 0; i < data.length; i += 1){
res[i] = await sanitizeOutput(data[i], schema, {
auth
});
}
return res;
}
const transforms = [
(data)=>defaultSanitizeOutput({
schema,
getModel
}, data)
];
if (auth) {
transforms.push(traverseEntity(removeRestrictedRelations(auth), {
schema,
getModel
}));
}
// Apply sanitizers from registry if exists
opts?.sanitizers?.output?.forEach((sanitizer)=>transforms.push(sanitizer(schema)));
return pipe(...transforms)(data);
};
const sanitizeQuery = async (query, schema, { auth } = {})=>{
if (!schema) {
throw new Error('Missing schema in sanitizeQuery');
}
const { filters, sort, fields, populate } = query;
const sanitizedQuery = cloneDeep(query);
if (filters) {
Object.assign(sanitizedQuery, {
filters: await sanitizeFilters(filters, schema, {
auth
})
});
}
if (sort) {
Object.assign(sanitizedQuery, {
sort: await sanitizeSort(sort, schema, {
auth
})
});
}
if (fields) {
Object.assign(sanitizedQuery, {
fields: await sanitizeFields(fields, schema)
});
}
if (populate) {
Object.assign(sanitizedQuery, {
populate: await sanitizePopulate(populate, schema)
});
}
return sanitizedQuery;
};
const sanitizeFilters = (filters, schema, { auth } = {})=>{
if (!schema) {
throw new Error('Missing schema in sanitizeFilters');
}
if (isArray(filters)) {
return Promise.all(filters.map((filter)=>sanitizeFilters(filter, schema, {
auth
})));
}
const transforms = [
defaultSanitizeFilters({
schema,
getModel
})
];
if (auth) {
transforms.push(traverseQueryFilters(removeRestrictedRelations(auth), {
schema,
getModel
}));
}
return pipe(...transforms)(filters);
};
const sanitizeSort = (sort, schema, { auth } = {})=>{
if (!schema) {
throw new Error('Missing schema in sanitizeSort');
}
const transforms = [
defaultSanitizeSort({
schema,
getModel
})
];
if (auth) {
transforms.push(traverseQuerySort(removeRestrictedRelations(auth), {
schema,
getModel
}));
}
return pipe(...transforms)(sort);
};
const sanitizeFields = (fields, schema)=>{
if (!schema) {
throw new Error('Missing schema in sanitizeFields');
}
const transforms = [
defaultSanitizeFields({
schema,
getModel
})
];
return pipe(...transforms)(fields);
};
const sanitizePopulate = (populate, schema, { auth } = {})=>{
if (!schema) {
throw new Error('Missing schema in sanitizePopulate');
}
const transforms = [
defaultSanitizePopulate({
schema,
getModel
})
];
if (auth) {
transforms.push(traverseQueryPopulate(removeRestrictedRelations(auth), {
schema,
getModel
}));
}
return pipe(...transforms)(populate);
};
return {
input: sanitizeInput,
output: sanitizeOutput,
query: sanitizeQuery,
filters: sanitizeFilters,
sort: sanitizeSort,
fields: sanitizeFields,
populate: sanitizePopulate
};
};
export { createAPISanitizers };
//# sourceMappingURL=index.mjs.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,16 @@
/// <reference types="lodash" />
import type { Model, Data } from '../types';
import type { Parent } from '../traverse/factory';
interface Context {
schema: Model;
getModel: (model: string) => Model;
parent?: Parent;
}
declare const sanitizePasswords: (ctx: Context) => (entity: Data) => Promise<Data>;
declare const defaultSanitizeOutput: (ctx: Context, entity: Data) => Promise<Data>;
declare const defaultSanitizeFilters: import("lodash").CurriedFunction2<Context, unknown, Promise<unknown>>;
declare const defaultSanitizeSort: import("lodash").CurriedFunction2<Context, unknown, Promise<unknown>>;
declare const defaultSanitizeFields: import("lodash").CurriedFunction2<Context, unknown, Promise<unknown>>;
declare const defaultSanitizePopulate: import("lodash").CurriedFunction2<Context, unknown, Promise<unknown>>;
export { sanitizePasswords, defaultSanitizeOutput, defaultSanitizeFilters, defaultSanitizeSort, defaultSanitizeFields, defaultSanitizePopulate, };
//# sourceMappingURL=sanitizers.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"sanitizers.d.ts","sourceRoot":"","sources":["../../src/sanitize/sanitizers.ts"],"names":[],"mappings":";AAsBA,OAAO,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAC5C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAElD,UAAU,OAAO;IACf,MAAM,EAAE,KAAK,CAAC;IACd,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,KAAK,CAAC;IACnC,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAID,QAAA,MAAM,iBAAiB,QAAS,OAAO,cAAoB,IAAI,kBAM9D,CAAC;AAEF,QAAA,MAAM,qBAAqB,QAAe,OAAO,UAAU,IAAI,kBAa9D,CAAC;AAEF,QAAA,MAAM,sBAAsB,uEAmC1B,CAAC;AAEH,QAAA,MAAM,mBAAmB,uEAuCvB,CAAC;AAEH,QAAA,MAAM,qBAAqB,uEAyBzB,CAAC;AAEH,QAAA,MAAM,uBAAuB,uEAiC3B,CAAC;AAEH,OAAO,EACL,iBAAiB,EACjB,qBAAqB,EACrB,sBAAsB,EACtB,mBAAmB,EACnB,qBAAqB,EACrB,uBAAuB,GACxB,CAAC"}

View File

@@ -0,0 +1,173 @@
'use strict';
var fp = require('lodash/fp');
var async = require('../async.js');
var traverseEntity = require('../traverse-entity.js');
var contentTypes = require('../content-types.js');
var queryFilters = require('../traverse/query-filters.js');
var querySort = require('../traverse/query-sort.js');
var queryPopulate = require('../traverse/query-populate.js');
var queryFields = require('../traverse/query-fields.js');
var removePassword = require('./visitors/remove-password.js');
var removePrivate = require('./visitors/remove-private.js');
var removeMorphToRelations = require('./visitors/remove-morph-to-relations.js');
var removeDynamicZones = require('./visitors/remove-dynamic-zones.js');
var expandWildcardPopulate = require('./visitors/expand-wildcard-populate.js');
var operators = require('../operators.js');
const { ID_ATTRIBUTE, DOC_ID_ATTRIBUTE } = contentTypes.constants;
const sanitizePasswords = (ctx)=>async (entity)=>{
if (!ctx.schema) {
throw new Error('Missing schema in sanitizePasswords');
}
return traverseEntity(removePassword, ctx, entity);
};
const defaultSanitizeOutput = async (ctx, entity)=>{
if (!ctx.schema) {
throw new Error('Missing schema in defaultSanitizeOutput');
}
return traverseEntity((...args)=>{
removePassword(...args);
removePrivate(...args);
}, ctx, entity);
};
const defaultSanitizeFilters = fp.curry((ctx, filters)=>{
if (!ctx.schema) {
throw new Error('Missing schema in defaultSanitizeFilters');
}
return async.pipe(// Remove keys that are not attributes or valid operators
queryFilters(({ key, attribute }, { remove })=>{
const isAttribute = !!attribute;
// ID is not an attribute per se, so we need to make
// an extra check to ensure we're not checking it
if ([
ID_ATTRIBUTE,
DOC_ID_ATTRIBUTE
].includes(key)) {
return;
}
if (!isAttribute && !operators.isOperator(key)) {
remove(key);
}
}, ctx), // Remove dynamic zones from filters
queryFilters(removeDynamicZones, ctx), // Remove morpTo relations from filters
queryFilters(removeMorphToRelations, ctx), // Remove passwords from filters
queryFilters(removePassword, ctx), // Remove private from filters
queryFilters(removePrivate, ctx), // Remove empty objects
queryFilters(({ key, value }, { remove })=>{
if (fp.isObject(value) && fp.isEmpty(value)) {
remove(key);
}
}, ctx))(filters);
});
const defaultSanitizeSort = fp.curry((ctx, sort)=>{
if (!ctx.schema) {
throw new Error('Missing schema in defaultSanitizeSort');
}
return async.pipe(// Remove non attribute keys
querySort(({ key, attribute }, { remove })=>{
// ID is not an attribute per se, so we need to make
// an extra check to ensure we're not checking it
if ([
ID_ATTRIBUTE,
DOC_ID_ATTRIBUTE
].includes(key)) {
return;
}
if (!attribute) {
remove(key);
}
}, ctx), // Remove dynamic zones from sort
querySort(removeDynamicZones, ctx), // Remove morpTo relations from sort
querySort(removeMorphToRelations, ctx), // Remove private from sort
querySort(removePrivate, ctx), // Remove passwords from filters
querySort(removePassword, ctx), // Remove keys for empty non-scalar values
querySort(({ key, attribute, value }, { remove })=>{
// ID is not an attribute per se, so we need to make
// an extra check to ensure we're not removing it
if ([
ID_ATTRIBUTE,
DOC_ID_ATTRIBUTE
].includes(key)) {
return;
}
if (!contentTypes.isScalarAttribute(attribute) && fp.isEmpty(value)) {
remove(key);
}
}, ctx))(sort);
});
const defaultSanitizeFields = fp.curry((ctx, fields)=>{
if (!ctx.schema) {
throw new Error('Missing schema in defaultSanitizeFields');
}
return async.pipe(// Only keep scalar attributes
queryFields(({ key, attribute }, { remove })=>{
// ID is not an attribute per se, so we need to make
// an extra check to ensure we're not checking it
if ([
ID_ATTRIBUTE,
DOC_ID_ATTRIBUTE
].includes(key)) {
return;
}
if (fp.isNil(attribute) || !contentTypes.isScalarAttribute(attribute)) {
remove(key);
}
}, ctx), // Remove private fields
queryFields(removePrivate, ctx), // Remove password fields
queryFields(removePassword, ctx), // Remove nil values from fields array
(value)=>fp.isArray(value) ? value.filter((field)=>!fp.isNil(field)) : value)(fields);
});
const defaultSanitizePopulate = fp.curry((ctx, populate)=>{
if (!ctx.schema) {
throw new Error('Missing schema in defaultSanitizePopulate');
}
return async.pipe(queryPopulate(expandWildcardPopulate, ctx), queryPopulate(async ({ key, value, schema, attribute, getModel, path }, { set })=>{
if (attribute) {
return;
}
const parent = {
key,
path,
schema,
attribute
};
if (key === 'sort') {
set(key, await defaultSanitizeSort({
schema,
getModel,
parent
}, value));
}
if (key === 'filters') {
set(key, await defaultSanitizeFilters({
schema,
getModel,
parent
}, value));
}
if (key === 'fields') {
set(key, await defaultSanitizeFields({
schema,
getModel,
parent
}, value));
}
if (key === 'populate') {
set(key, await defaultSanitizePopulate({
schema,
getModel,
parent
}, value));
}
}, ctx), // Remove private fields
queryPopulate(removePrivate, ctx))(populate);
});
exports.defaultSanitizeFields = defaultSanitizeFields;
exports.defaultSanitizeFilters = defaultSanitizeFilters;
exports.defaultSanitizeOutput = defaultSanitizeOutput;
exports.defaultSanitizePopulate = defaultSanitizePopulate;
exports.defaultSanitizeSort = defaultSanitizeSort;
exports.sanitizePasswords = sanitizePasswords;
//# sourceMappingURL=sanitizers.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,166 @@
import { curry, isObject, isEmpty, isNil, isArray } from 'lodash/fp';
import { pipe } from '../async.mjs';
import traverseEntity from '../traverse-entity.mjs';
import { isScalarAttribute, constants } from '../content-types.mjs';
import traverseQueryFilters from '../traverse/query-filters.mjs';
import traverseQuerySort from '../traverse/query-sort.mjs';
import traverseQueryPopulate from '../traverse/query-populate.mjs';
import traverseQueryFields from '../traverse/query-fields.mjs';
import visitor$1 from './visitors/remove-password.mjs';
import visitor from './visitors/remove-private.mjs';
import visitor$2 from './visitors/remove-morph-to-relations.mjs';
import visitor$3 from './visitors/remove-dynamic-zones.mjs';
import visitor$4 from './visitors/expand-wildcard-populate.mjs';
import { isOperator } from '../operators.mjs';
const { ID_ATTRIBUTE, DOC_ID_ATTRIBUTE } = constants;
const sanitizePasswords = (ctx)=>async (entity)=>{
if (!ctx.schema) {
throw new Error('Missing schema in sanitizePasswords');
}
return traverseEntity(visitor$1, ctx, entity);
};
const defaultSanitizeOutput = async (ctx, entity)=>{
if (!ctx.schema) {
throw new Error('Missing schema in defaultSanitizeOutput');
}
return traverseEntity((...args)=>{
visitor$1(...args);
visitor(...args);
}, ctx, entity);
};
const defaultSanitizeFilters = curry((ctx, filters)=>{
if (!ctx.schema) {
throw new Error('Missing schema in defaultSanitizeFilters');
}
return pipe(// Remove keys that are not attributes or valid operators
traverseQueryFilters(({ key, attribute }, { remove })=>{
const isAttribute = !!attribute;
// ID is not an attribute per se, so we need to make
// an extra check to ensure we're not checking it
if ([
ID_ATTRIBUTE,
DOC_ID_ATTRIBUTE
].includes(key)) {
return;
}
if (!isAttribute && !isOperator(key)) {
remove(key);
}
}, ctx), // Remove dynamic zones from filters
traverseQueryFilters(visitor$3, ctx), // Remove morpTo relations from filters
traverseQueryFilters(visitor$2, ctx), // Remove passwords from filters
traverseQueryFilters(visitor$1, ctx), // Remove private from filters
traverseQueryFilters(visitor, ctx), // Remove empty objects
traverseQueryFilters(({ key, value }, { remove })=>{
if (isObject(value) && isEmpty(value)) {
remove(key);
}
}, ctx))(filters);
});
const defaultSanitizeSort = curry((ctx, sort)=>{
if (!ctx.schema) {
throw new Error('Missing schema in defaultSanitizeSort');
}
return pipe(// Remove non attribute keys
traverseQuerySort(({ key, attribute }, { remove })=>{
// ID is not an attribute per se, so we need to make
// an extra check to ensure we're not checking it
if ([
ID_ATTRIBUTE,
DOC_ID_ATTRIBUTE
].includes(key)) {
return;
}
if (!attribute) {
remove(key);
}
}, ctx), // Remove dynamic zones from sort
traverseQuerySort(visitor$3, ctx), // Remove morpTo relations from sort
traverseQuerySort(visitor$2, ctx), // Remove private from sort
traverseQuerySort(visitor, ctx), // Remove passwords from filters
traverseQuerySort(visitor$1, ctx), // Remove keys for empty non-scalar values
traverseQuerySort(({ key, attribute, value }, { remove })=>{
// ID is not an attribute per se, so we need to make
// an extra check to ensure we're not removing it
if ([
ID_ATTRIBUTE,
DOC_ID_ATTRIBUTE
].includes(key)) {
return;
}
if (!isScalarAttribute(attribute) && isEmpty(value)) {
remove(key);
}
}, ctx))(sort);
});
const defaultSanitizeFields = curry((ctx, fields)=>{
if (!ctx.schema) {
throw new Error('Missing schema in defaultSanitizeFields');
}
return pipe(// Only keep scalar attributes
traverseQueryFields(({ key, attribute }, { remove })=>{
// ID is not an attribute per se, so we need to make
// an extra check to ensure we're not checking it
if ([
ID_ATTRIBUTE,
DOC_ID_ATTRIBUTE
].includes(key)) {
return;
}
if (isNil(attribute) || !isScalarAttribute(attribute)) {
remove(key);
}
}, ctx), // Remove private fields
traverseQueryFields(visitor, ctx), // Remove password fields
traverseQueryFields(visitor$1, ctx), // Remove nil values from fields array
(value)=>isArray(value) ? value.filter((field)=>!isNil(field)) : value)(fields);
});
const defaultSanitizePopulate = curry((ctx, populate)=>{
if (!ctx.schema) {
throw new Error('Missing schema in defaultSanitizePopulate');
}
return pipe(traverseQueryPopulate(visitor$4, ctx), traverseQueryPopulate(async ({ key, value, schema, attribute, getModel, path }, { set })=>{
if (attribute) {
return;
}
const parent = {
key,
path,
schema,
attribute
};
if (key === 'sort') {
set(key, await defaultSanitizeSort({
schema,
getModel,
parent
}, value));
}
if (key === 'filters') {
set(key, await defaultSanitizeFilters({
schema,
getModel,
parent
}, value));
}
if (key === 'fields') {
set(key, await defaultSanitizeFields({
schema,
getModel,
parent
}, value));
}
if (key === 'populate') {
set(key, await defaultSanitizePopulate({
schema,
getModel,
parent
}, value));
}
}, ctx), // Remove private fields
traverseQueryPopulate(visitor, ctx))(populate);
});
export { defaultSanitizeFields, defaultSanitizeFilters, defaultSanitizeOutput, defaultSanitizePopulate, defaultSanitizeSort, sanitizePasswords };
//# sourceMappingURL=sanitizers.mjs.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,4 @@
import type { Visitor } from '../../traverse/factory';
declare const visitor: Visitor;
export default visitor;
//# sourceMappingURL=expand-wildcard-populate.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"expand-wildcard-populate.d.ts","sourceRoot":"","sources":["../../../src/sanitize/visitors/expand-wildcard-populate.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AAEtD,QAAA,MAAM,OAAO,EAAE,OAYd,CAAC;AAEF,eAAe,OAAO,CAAC"}

View File

@@ -0,0 +1,20 @@
'use strict';
const visitor = ({ schema, key, value }, { set })=>{
if (key === '' && value === '*') {
const { attributes } = schema;
const newPopulateQuery = Object.entries(attributes).filter(([, attribute])=>[
'relation',
'component',
'media',
'dynamiczone'
].includes(attribute.type)).reduce((acc, [key])=>({
...acc,
[key]: true
}), {});
set('', newPopulateQuery);
}
};
module.exports = visitor;
//# sourceMappingURL=expand-wildcard-populate.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"expand-wildcard-populate.js","sources":["../../../src/sanitize/visitors/expand-wildcard-populate.ts"],"sourcesContent":["import type { Visitor } from '../../traverse/factory';\n\nconst visitor: Visitor = ({ schema, key, value }, { set }) => {\n if (key === '' && value === '*') {\n const { attributes } = schema;\n\n const newPopulateQuery = Object.entries(attributes)\n .filter(([, attribute]) =>\n ['relation', 'component', 'media', 'dynamiczone'].includes(attribute.type)\n )\n .reduce<Record<string, true>>((acc, [key]) => ({ ...acc, [key]: true }), {});\n\n set('', newPopulateQuery);\n }\n};\n\nexport default visitor;\n"],"names":["visitor","schema","key","value","set","attributes","newPopulateQuery","Object","entries","filter","attribute","includes","type","reduce","acc"],"mappings":";;AAEA,MAAMA,OAAmB,GAAA,CAAC,EAAEC,MAAM,EAAEC,GAAG,EAAEC,KAAK,EAAE,EAAE,EAAEC,GAAG,EAAE,GAAA;IACvD,IAAIF,GAAAA,KAAQ,EAAMC,IAAAA,KAAAA,KAAU,GAAK,EAAA;QAC/B,MAAM,EAAEE,UAAU,EAAE,GAAGJ,MAAAA;QAEvB,MAAMK,gBAAAA,GAAmBC,MAAOC,CAAAA,OAAO,CAACH,UAAAA,CAAAA,CACrCI,MAAM,CAAC,CAAC,GAAGC,SAAAA,CAAU,GACpB;AAAC,gBAAA,UAAA;AAAY,gBAAA,WAAA;AAAa,gBAAA,OAAA;AAAS,gBAAA;AAAc,aAAA,CAACC,QAAQ,CAACD,SAAUE,CAAAA,IAAI,CAE1EC,CAAAA,CAAAA,MAAM,CAAuB,CAACC,GAAK,EAAA,CAACZ,GAAI,CAAA,IAAM;AAAE,gBAAA,GAAGY,GAAG;AAAE,gBAAA,CAACZ,MAAM;AAAK,aAAA,GAAI,EAAC,CAAA;AAE5EE,QAAAA,GAAAA,CAAI,EAAIE,EAAAA,gBAAAA,CAAAA;AACV;AACF;;;;"}

View File

@@ -0,0 +1,18 @@
const visitor = ({ schema, key, value }, { set })=>{
if (key === '' && value === '*') {
const { attributes } = schema;
const newPopulateQuery = Object.entries(attributes).filter(([, attribute])=>[
'relation',
'component',
'media',
'dynamiczone'
].includes(attribute.type)).reduce((acc, [key])=>({
...acc,
[key]: true
}), {});
set('', newPopulateQuery);
}
};
export { visitor as default };
//# sourceMappingURL=expand-wildcard-populate.mjs.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"expand-wildcard-populate.mjs","sources":["../../../src/sanitize/visitors/expand-wildcard-populate.ts"],"sourcesContent":["import type { Visitor } from '../../traverse/factory';\n\nconst visitor: Visitor = ({ schema, key, value }, { set }) => {\n if (key === '' && value === '*') {\n const { attributes } = schema;\n\n const newPopulateQuery = Object.entries(attributes)\n .filter(([, attribute]) =>\n ['relation', 'component', 'media', 'dynamiczone'].includes(attribute.type)\n )\n .reduce<Record<string, true>>((acc, [key]) => ({ ...acc, [key]: true }), {});\n\n set('', newPopulateQuery);\n }\n};\n\nexport default visitor;\n"],"names":["visitor","schema","key","value","set","attributes","newPopulateQuery","Object","entries","filter","attribute","includes","type","reduce","acc"],"mappings":"AAEA,MAAMA,OAAmB,GAAA,CAAC,EAAEC,MAAM,EAAEC,GAAG,EAAEC,KAAK,EAAE,EAAE,EAAEC,GAAG,EAAE,GAAA;IACvD,IAAIF,GAAAA,KAAQ,EAAMC,IAAAA,KAAAA,KAAU,GAAK,EAAA;QAC/B,MAAM,EAAEE,UAAU,EAAE,GAAGJ,MAAAA;QAEvB,MAAMK,gBAAAA,GAAmBC,MAAOC,CAAAA,OAAO,CAACH,UAAAA,CAAAA,CACrCI,MAAM,CAAC,CAAC,GAAGC,SAAAA,CAAU,GACpB;AAAC,gBAAA,UAAA;AAAY,gBAAA,WAAA;AAAa,gBAAA,OAAA;AAAS,gBAAA;AAAc,aAAA,CAACC,QAAQ,CAACD,SAAUE,CAAAA,IAAI,CAE1EC,CAAAA,CAAAA,MAAM,CAAuB,CAACC,GAAK,EAAA,CAACZ,GAAI,CAAA,IAAM;AAAE,gBAAA,GAAGY,GAAG;AAAE,gBAAA,CAACZ,MAAM;AAAK,aAAA,GAAI,EAAC,CAAA;AAE5EE,QAAAA,GAAAA,CAAI,EAAIE,EAAAA,gBAAAA,CAAAA;AACV;AACF;;;;"}

View File

@@ -0,0 +1,9 @@
export { default as removePassword } from './remove-password';
export { default as removePrivate } from './remove-private';
export { default as removeRestrictedRelations } from './remove-restricted-relations';
export { default as removeMorphToRelations } from './remove-morph-to-relations';
export { default as removeDynamicZones } from './remove-dynamic-zones';
export { default as removeDisallowedFields } from './remove-disallowed-fields';
export { default as removeRestrictedFields } from './remove-restricted-fields';
export { default as expandWildcardPopulate } from './expand-wildcard-populate';
//# sourceMappingURL=index.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/sanitize/visitors/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAC9D,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAC5D,OAAO,EAAE,OAAO,IAAI,yBAAyB,EAAE,MAAM,+BAA+B,CAAC;AACrF,OAAO,EAAE,OAAO,IAAI,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AAChF,OAAO,EAAE,OAAO,IAAI,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AACvE,OAAO,EAAE,OAAO,IAAI,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AAC/E,OAAO,EAAE,OAAO,IAAI,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AAC/E,OAAO,EAAE,OAAO,IAAI,sBAAsB,EAAE,MAAM,4BAA4B,CAAC"}

View File

@@ -0,0 +1,22 @@
'use strict';
var removePassword = require('./remove-password.js');
var removePrivate = require('./remove-private.js');
var removeRestrictedRelations = require('./remove-restricted-relations.js');
var removeMorphToRelations = require('./remove-morph-to-relations.js');
var removeDynamicZones = require('./remove-dynamic-zones.js');
var removeDisallowedFields = require('./remove-disallowed-fields.js');
var removeRestrictedFields = require('./remove-restricted-fields.js');
var expandWildcardPopulate = require('./expand-wildcard-populate.js');
exports.removePassword = removePassword;
exports.removePrivate = removePrivate;
exports.removeRestrictedRelations = removeRestrictedRelations;
exports.removeMorphToRelations = removeMorphToRelations;
exports.removeDynamicZones = removeDynamicZones;
exports.removeDisallowedFields = removeDisallowedFields;
exports.removeRestrictedFields = removeRestrictedFields;
exports.expandWildcardPopulate = expandWildcardPopulate;
//# sourceMappingURL=index.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;"}

View File

@@ -0,0 +1,9 @@
export { default as removePassword } from './remove-password.mjs';
export { default as removePrivate } from './remove-private.mjs';
export { default as removeRestrictedRelations } from './remove-restricted-relations.mjs';
export { default as removeMorphToRelations } from './remove-morph-to-relations.mjs';
export { default as removeDynamicZones } from './remove-dynamic-zones.mjs';
export { default as removeDisallowedFields } from './remove-disallowed-fields.mjs';
export { default as removeRestrictedFields } from './remove-restricted-fields.mjs';
export { default as expandWildcardPopulate } from './expand-wildcard-populate.mjs';
//# sourceMappingURL=index.mjs.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"index.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;"}

View File

@@ -0,0 +1,4 @@
import type { Visitor } from '../../traverse/factory';
declare const _default: (allowedFields?: string[] | null) => Visitor;
export default _default;
//# sourceMappingURL=remove-disallowed-fields.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"remove-disallowed-fields.d.ts","sourceRoot":"","sources":["../../../src/sanitize/visitors/remove-disallowed-fields.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;yCAEvB,MAAM,EAAE,GAAG,IAAI,KAAU,OAAO;AAA/D,wBAoEI"}

View File

@@ -0,0 +1,87 @@
'use strict';
var fp = require('lodash/fp');
var removeDisallowedFields = ((allowedFields = null)=>({ key, path: { attribute: path } }, { remove })=>{
// All fields are allowed
if (allowedFields === null) {
return;
}
// Throw on invalid formats
if (!(fp.isArray(allowedFields) && allowedFields.every(fp.isString))) {
throw new TypeError(`Expected array of strings for allowedFields but got "${typeof allowedFields}"`);
}
if (fp.isNil(path)) {
return;
}
const containedPaths = getContainedPaths(path);
/**
* Tells if the current path should be kept or not based
* on the success of the check functions for any of the allowed paths.
*
* The check functions are defined as follow:
*
* `containedPaths.includes(p)`
* @example
* ```js
* const path = 'foo.bar.field';
* const p = 'foo.bar';
* // it should match
*
* const path = 'foo.bar.field';
* const p = 'bar.foo';
* // it shouldn't match
*
* const path = 'foo.bar';
* const p = 'foo.bar.field';
* // it should match but isn't handled by this check
* ```
*
* `p.startsWith(`${path}.`)`
* @example
* ```js
* const path = 'foo.bar';
* const p = 'foo.bar.field';
* // it should match
*
* const path = 'foo.bar.field';
* const p = 'bar.foo';
* // it shouldn't match
*
* const path = 'foo.bar.field';
* const p = 'foo.bar';
* // it should match but isn't handled by this check
* ```
*/ const isPathAllowed = allowedFields.some((p)=>containedPaths.includes(p) || p.startsWith(`${path}.`));
if (isPathAllowed) {
return;
}
// Remove otherwise
remove(key);
});
/**
* Retrieve the list of allowed paths based on the given path
*
* @example
* ```js
* const containedPaths = getContainedPaths('foo');
* // ['foo']
*
* * const containedPaths = getContainedPaths('foo.bar');
* // ['foo', 'foo.bar']
*
* * const containedPaths = getContainedPaths('foo.bar.field');
* // ['foo', 'foo.bar', 'foo.bar.field']
* ```
*/ const getContainedPaths = (path)=>{
const parts = fp.toPath(path);
return parts.reduce((acc, value, index, list)=>{
return [
...acc,
list.slice(0, index + 1).join('.')
];
}, []);
};
module.exports = removeDisallowedFields;
//# sourceMappingURL=remove-disallowed-fields.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"remove-disallowed-fields.js","sources":["../../../src/sanitize/visitors/remove-disallowed-fields.ts"],"sourcesContent":["import { isArray, isNil, isString, toPath } from 'lodash/fp';\nimport type { Visitor } from '../../traverse/factory';\n\nexport default (allowedFields: string[] | null = null): Visitor =>\n ({ key, path: { attribute: path } }, { remove }) => {\n // All fields are allowed\n if (allowedFields === null) {\n return;\n }\n\n // Throw on invalid formats\n if (!(isArray(allowedFields) && allowedFields.every(isString))) {\n throw new TypeError(\n `Expected array of strings for allowedFields but got \"${typeof allowedFields}\"`\n );\n }\n\n if (isNil(path)) {\n return;\n }\n\n const containedPaths = getContainedPaths(path);\n\n /**\n * Tells if the current path should be kept or not based\n * on the success of the check functions for any of the allowed paths.\n *\n * The check functions are defined as follow:\n *\n * `containedPaths.includes(p)`\n * @example\n * ```js\n * const path = 'foo.bar.field';\n * const p = 'foo.bar';\n * // it should match\n *\n * const path = 'foo.bar.field';\n * const p = 'bar.foo';\n * // it shouldn't match\n *\n * const path = 'foo.bar';\n * const p = 'foo.bar.field';\n * // it should match but isn't handled by this check\n * ```\n *\n * `p.startsWith(`${path}.`)`\n * @example\n * ```js\n * const path = 'foo.bar';\n * const p = 'foo.bar.field';\n * // it should match\n *\n * const path = 'foo.bar.field';\n * const p = 'bar.foo';\n * // it shouldn't match\n *\n * const path = 'foo.bar.field';\n * const p = 'foo.bar';\n * // it should match but isn't handled by this check\n * ```\n */\n const isPathAllowed = allowedFields.some(\n (p) => containedPaths.includes(p) || p.startsWith(`${path}.`)\n );\n\n if (isPathAllowed) {\n return;\n }\n\n // Remove otherwise\n remove(key);\n };\n\n/**\n * Retrieve the list of allowed paths based on the given path\n *\n * @example\n * ```js\n * const containedPaths = getContainedPaths('foo');\n * // ['foo']\n *\n * * const containedPaths = getContainedPaths('foo.bar');\n * // ['foo', 'foo.bar']\n *\n * * const containedPaths = getContainedPaths('foo.bar.field');\n * // ['foo', 'foo.bar', 'foo.bar.field']\n * ```\n */\nconst getContainedPaths = (path: string) => {\n const parts = toPath(path);\n\n return parts.reduce((acc, value, index, list) => {\n return [...acc, list.slice(0, index + 1).join('.')];\n }, [] as string[]);\n};\n"],"names":["allowedFields","key","path","attribute","remove","isArray","every","isString","TypeError","isNil","containedPaths","getContainedPaths","isPathAllowed","some","p","includes","startsWith","parts","toPath","reduce","acc","value","index","list","slice","join"],"mappings":";;;;AAGA,6BAAe,CAAA,CAACA,aAAAA,GAAiC,IAAI,GACnD,CAAC,EAAEC,GAAG,EAAEC,IAAM,EAAA,EAAEC,WAAWD,IAAI,EAAE,EAAE,EAAE,EAAEE,MAAM,EAAE,GAAA;;AAE7C,QAAA,IAAIJ,kBAAkB,IAAM,EAAA;AAC1B,YAAA;AACF;;QAGA,IAAI,EAAEK,UAAQL,CAAAA,aAAAA,CAAAA,IAAkBA,cAAcM,KAAK,CAACC,YAAQ,CAAI,EAAA;YAC9D,MAAM,IAAIC,UACR,CAAC,qDAAqD,EAAE,OAAOR,aAAAA,CAAc,CAAC,CAAC,CAAA;AAEnF;AAEA,QAAA,IAAIS,SAAMP,IAAO,CAAA,EAAA;AACf,YAAA;AACF;AAEA,QAAA,MAAMQ,iBAAiBC,iBAAkBT,CAAAA,IAAAA,CAAAA;AAEzC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqCC,QACD,MAAMU,aAAgBZ,GAAAA,aAAAA,CAAca,IAAI,CACtC,CAACC,IAAMJ,cAAeK,CAAAA,QAAQ,CAACD,CAAAA,CAAAA,IAAMA,EAAEE,UAAU,CAAC,CAAC,EAAEd,IAAAA,CAAK,CAAC,CAAC,CAAA,CAAA;AAG9D,QAAA,IAAIU,aAAe,EAAA;AACjB,YAAA;AACF;;QAGAR,MAAOH,CAAAA,GAAAA,CAAAA;AACT,KAAA;AAEF;;;;;;;;;;;;;;IAeA,MAAMU,oBAAoB,CAACT,IAAAA,GAAAA;AACzB,IAAA,MAAMe,QAAQC,SAAOhB,CAAAA,IAAAA,CAAAA;AAErB,IAAA,OAAOe,MAAME,MAAM,CAAC,CAACC,GAAAA,EAAKC,OAAOC,KAAOC,EAAAA,IAAAA,GAAAA;QACtC,OAAO;AAAIH,YAAAA,GAAAA,GAAAA;AAAKG,YAAAA,IAAAA,CAAKC,KAAK,CAAC,CAAA,EAAGF,KAAQ,GAAA,CAAA,CAAA,CAAGG,IAAI,CAAC,GAAA;AAAK,SAAA;AACrD,KAAA,EAAG,EAAE,CAAA;AACP,CAAA;;;;"}

View File

@@ -0,0 +1,85 @@
import { isArray, isString, isNil, toPath } from 'lodash/fp';
var removeDisallowedFields = ((allowedFields = null)=>({ key, path: { attribute: path } }, { remove })=>{
// All fields are allowed
if (allowedFields === null) {
return;
}
// Throw on invalid formats
if (!(isArray(allowedFields) && allowedFields.every(isString))) {
throw new TypeError(`Expected array of strings for allowedFields but got "${typeof allowedFields}"`);
}
if (isNil(path)) {
return;
}
const containedPaths = getContainedPaths(path);
/**
* Tells if the current path should be kept or not based
* on the success of the check functions for any of the allowed paths.
*
* The check functions are defined as follow:
*
* `containedPaths.includes(p)`
* @example
* ```js
* const path = 'foo.bar.field';
* const p = 'foo.bar';
* // it should match
*
* const path = 'foo.bar.field';
* const p = 'bar.foo';
* // it shouldn't match
*
* const path = 'foo.bar';
* const p = 'foo.bar.field';
* // it should match but isn't handled by this check
* ```
*
* `p.startsWith(`${path}.`)`
* @example
* ```js
* const path = 'foo.bar';
* const p = 'foo.bar.field';
* // it should match
*
* const path = 'foo.bar.field';
* const p = 'bar.foo';
* // it shouldn't match
*
* const path = 'foo.bar.field';
* const p = 'foo.bar';
* // it should match but isn't handled by this check
* ```
*/ const isPathAllowed = allowedFields.some((p)=>containedPaths.includes(p) || p.startsWith(`${path}.`));
if (isPathAllowed) {
return;
}
// Remove otherwise
remove(key);
});
/**
* Retrieve the list of allowed paths based on the given path
*
* @example
* ```js
* const containedPaths = getContainedPaths('foo');
* // ['foo']
*
* * const containedPaths = getContainedPaths('foo.bar');
* // ['foo', 'foo.bar']
*
* * const containedPaths = getContainedPaths('foo.bar.field');
* // ['foo', 'foo.bar', 'foo.bar.field']
* ```
*/ const getContainedPaths = (path)=>{
const parts = toPath(path);
return parts.reduce((acc, value, index, list)=>{
return [
...acc,
list.slice(0, index + 1).join('.')
];
}, []);
};
export { removeDisallowedFields as default };
//# sourceMappingURL=remove-disallowed-fields.mjs.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"remove-disallowed-fields.mjs","sources":["../../../src/sanitize/visitors/remove-disallowed-fields.ts"],"sourcesContent":["import { isArray, isNil, isString, toPath } from 'lodash/fp';\nimport type { Visitor } from '../../traverse/factory';\n\nexport default (allowedFields: string[] | null = null): Visitor =>\n ({ key, path: { attribute: path } }, { remove }) => {\n // All fields are allowed\n if (allowedFields === null) {\n return;\n }\n\n // Throw on invalid formats\n if (!(isArray(allowedFields) && allowedFields.every(isString))) {\n throw new TypeError(\n `Expected array of strings for allowedFields but got \"${typeof allowedFields}\"`\n );\n }\n\n if (isNil(path)) {\n return;\n }\n\n const containedPaths = getContainedPaths(path);\n\n /**\n * Tells if the current path should be kept or not based\n * on the success of the check functions for any of the allowed paths.\n *\n * The check functions are defined as follow:\n *\n * `containedPaths.includes(p)`\n * @example\n * ```js\n * const path = 'foo.bar.field';\n * const p = 'foo.bar';\n * // it should match\n *\n * const path = 'foo.bar.field';\n * const p = 'bar.foo';\n * // it shouldn't match\n *\n * const path = 'foo.bar';\n * const p = 'foo.bar.field';\n * // it should match but isn't handled by this check\n * ```\n *\n * `p.startsWith(`${path}.`)`\n * @example\n * ```js\n * const path = 'foo.bar';\n * const p = 'foo.bar.field';\n * // it should match\n *\n * const path = 'foo.bar.field';\n * const p = 'bar.foo';\n * // it shouldn't match\n *\n * const path = 'foo.bar.field';\n * const p = 'foo.bar';\n * // it should match but isn't handled by this check\n * ```\n */\n const isPathAllowed = allowedFields.some(\n (p) => containedPaths.includes(p) || p.startsWith(`${path}.`)\n );\n\n if (isPathAllowed) {\n return;\n }\n\n // Remove otherwise\n remove(key);\n };\n\n/**\n * Retrieve the list of allowed paths based on the given path\n *\n * @example\n * ```js\n * const containedPaths = getContainedPaths('foo');\n * // ['foo']\n *\n * * const containedPaths = getContainedPaths('foo.bar');\n * // ['foo', 'foo.bar']\n *\n * * const containedPaths = getContainedPaths('foo.bar.field');\n * // ['foo', 'foo.bar', 'foo.bar.field']\n * ```\n */\nconst getContainedPaths = (path: string) => {\n const parts = toPath(path);\n\n return parts.reduce((acc, value, index, list) => {\n return [...acc, list.slice(0, index + 1).join('.')];\n }, [] as string[]);\n};\n"],"names":["allowedFields","key","path","attribute","remove","isArray","every","isString","TypeError","isNil","containedPaths","getContainedPaths","isPathAllowed","some","p","includes","startsWith","parts","toPath","reduce","acc","value","index","list","slice","join"],"mappings":";;AAGA,6BAAe,CAAA,CAACA,aAAAA,GAAiC,IAAI,GACnD,CAAC,EAAEC,GAAG,EAAEC,IAAM,EAAA,EAAEC,WAAWD,IAAI,EAAE,EAAE,EAAE,EAAEE,MAAM,EAAE,GAAA;;AAE7C,QAAA,IAAIJ,kBAAkB,IAAM,EAAA;AAC1B,YAAA;AACF;;QAGA,IAAI,EAAEK,OAAQL,CAAAA,aAAAA,CAAAA,IAAkBA,cAAcM,KAAK,CAACC,SAAQ,CAAI,EAAA;YAC9D,MAAM,IAAIC,UACR,CAAC,qDAAqD,EAAE,OAAOR,aAAAA,CAAc,CAAC,CAAC,CAAA;AAEnF;AAEA,QAAA,IAAIS,MAAMP,IAAO,CAAA,EAAA;AACf,YAAA;AACF;AAEA,QAAA,MAAMQ,iBAAiBC,iBAAkBT,CAAAA,IAAAA,CAAAA;AAEzC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqCC,QACD,MAAMU,aAAgBZ,GAAAA,aAAAA,CAAca,IAAI,CACtC,CAACC,IAAMJ,cAAeK,CAAAA,QAAQ,CAACD,CAAAA,CAAAA,IAAMA,EAAEE,UAAU,CAAC,CAAC,EAAEd,IAAAA,CAAK,CAAC,CAAC,CAAA,CAAA;AAG9D,QAAA,IAAIU,aAAe,EAAA;AACjB,YAAA;AACF;;QAGAR,MAAOH,CAAAA,GAAAA,CAAAA;AACT,KAAA;AAEF;;;;;;;;;;;;;;IAeA,MAAMU,oBAAoB,CAACT,IAAAA,GAAAA;AACzB,IAAA,MAAMe,QAAQC,MAAOhB,CAAAA,IAAAA,CAAAA;AAErB,IAAA,OAAOe,MAAME,MAAM,CAAC,CAACC,GAAAA,EAAKC,OAAOC,KAAOC,EAAAA,IAAAA,GAAAA;QACtC,OAAO;AAAIH,YAAAA,GAAAA,GAAAA;AAAKG,YAAAA,IAAAA,CAAKC,KAAK,CAAC,CAAA,EAAGF,KAAQ,GAAA,CAAA,CAAA,CAAGG,IAAI,CAAC,GAAA;AAAK,SAAA;AACrD,KAAA,EAAG,EAAE,CAAA;AACP,CAAA;;;;"}

View File

@@ -0,0 +1,4 @@
import type { Visitor } from '../../traverse/factory';
declare const visitor: Visitor;
export default visitor;
//# sourceMappingURL=remove-dynamic-zones.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"remove-dynamic-zones.d.ts","sourceRoot":"","sources":["../../../src/sanitize/visitors/remove-dynamic-zones.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AAEtD,QAAA,MAAM,OAAO,EAAE,OAId,CAAC;AAEF,eAAe,OAAO,CAAC"}

View File

@@ -0,0 +1,12 @@
'use strict';
var contentTypes = require('../../content-types.js');
const visitor = ({ key, attribute }, { remove })=>{
if (contentTypes.isDynamicZoneAttribute(attribute)) {
remove(key);
}
};
module.exports = visitor;
//# sourceMappingURL=remove-dynamic-zones.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"remove-dynamic-zones.js","sources":["../../../src/sanitize/visitors/remove-dynamic-zones.ts"],"sourcesContent":["import { isDynamicZoneAttribute } from '../../content-types';\nimport type { Visitor } from '../../traverse/factory';\n\nconst visitor: Visitor = ({ key, attribute }, { remove }) => {\n if (isDynamicZoneAttribute(attribute)) {\n remove(key);\n }\n};\n\nexport default visitor;\n"],"names":["visitor","key","attribute","remove","isDynamicZoneAttribute"],"mappings":";;;;AAGMA,MAAAA,OAAAA,GAAmB,CAAC,EAAEC,GAAG,EAAEC,SAAS,EAAE,EAAE,EAAEC,MAAM,EAAE,GAAA;AACtD,IAAA,IAAIC,oCAAuBF,SAAY,CAAA,EAAA;QACrCC,MAAOF,CAAAA,GAAAA,CAAAA;AACT;AACF;;;;"}

View File

@@ -0,0 +1,10 @@
import { isDynamicZoneAttribute } from '../../content-types.mjs';
const visitor = ({ key, attribute }, { remove })=>{
if (isDynamicZoneAttribute(attribute)) {
remove(key);
}
};
export { visitor as default };
//# sourceMappingURL=remove-dynamic-zones.mjs.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"remove-dynamic-zones.mjs","sources":["../../../src/sanitize/visitors/remove-dynamic-zones.ts"],"sourcesContent":["import { isDynamicZoneAttribute } from '../../content-types';\nimport type { Visitor } from '../../traverse/factory';\n\nconst visitor: Visitor = ({ key, attribute }, { remove }) => {\n if (isDynamicZoneAttribute(attribute)) {\n remove(key);\n }\n};\n\nexport default visitor;\n"],"names":["visitor","key","attribute","remove","isDynamicZoneAttribute"],"mappings":";;AAGMA,MAAAA,OAAAA,GAAmB,CAAC,EAAEC,GAAG,EAAEC,SAAS,EAAE,EAAE,EAAEC,MAAM,EAAE,GAAA;AACtD,IAAA,IAAIC,uBAAuBF,SAAY,CAAA,EAAA;QACrCC,MAAOF,CAAAA,GAAAA,CAAAA;AACT;AACF;;;;"}

View File

@@ -0,0 +1,4 @@
import type { Visitor } from '../../traverse/factory';
declare const visitor: Visitor;
export default visitor;
//# sourceMappingURL=remove-morph-to-relations.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"remove-morph-to-relations.d.ts","sourceRoot":"","sources":["../../../src/sanitize/visitors/remove-morph-to-relations.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AAEtD,QAAA,MAAM,OAAO,EAAE,OAId,CAAC;AAEF,eAAe,OAAO,CAAC"}

View File

@@ -0,0 +1,12 @@
'use strict';
var contentTypes = require('../../content-types.js');
const visitor = ({ key, attribute }, { remove })=>{
if (contentTypes.isMorphToRelationalAttribute(attribute)) {
remove(key);
}
};
module.exports = visitor;
//# sourceMappingURL=remove-morph-to-relations.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"remove-morph-to-relations.js","sources":["../../../src/sanitize/visitors/remove-morph-to-relations.ts"],"sourcesContent":["import { isMorphToRelationalAttribute } from '../../content-types';\nimport type { Visitor } from '../../traverse/factory';\n\nconst visitor: Visitor = ({ key, attribute }, { remove }) => {\n if (isMorphToRelationalAttribute(attribute)) {\n remove(key);\n }\n};\n\nexport default visitor;\n"],"names":["visitor","key","attribute","remove","isMorphToRelationalAttribute"],"mappings":";;;;AAGMA,MAAAA,OAAAA,GAAmB,CAAC,EAAEC,GAAG,EAAEC,SAAS,EAAE,EAAE,EAAEC,MAAM,EAAE,GAAA;AACtD,IAAA,IAAIC,0CAA6BF,SAAY,CAAA,EAAA;QAC3CC,MAAOF,CAAAA,GAAAA,CAAAA;AACT;AACF;;;;"}

View File

@@ -0,0 +1,10 @@
import { isMorphToRelationalAttribute } from '../../content-types.mjs';
const visitor = ({ key, attribute }, { remove })=>{
if (isMorphToRelationalAttribute(attribute)) {
remove(key);
}
};
export { visitor as default };
//# sourceMappingURL=remove-morph-to-relations.mjs.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"remove-morph-to-relations.mjs","sources":["../../../src/sanitize/visitors/remove-morph-to-relations.ts"],"sourcesContent":["import { isMorphToRelationalAttribute } from '../../content-types';\nimport type { Visitor } from '../../traverse/factory';\n\nconst visitor: Visitor = ({ key, attribute }, { remove }) => {\n if (isMorphToRelationalAttribute(attribute)) {\n remove(key);\n }\n};\n\nexport default visitor;\n"],"names":["visitor","key","attribute","remove","isMorphToRelationalAttribute"],"mappings":";;AAGMA,MAAAA,OAAAA,GAAmB,CAAC,EAAEC,GAAG,EAAEC,SAAS,EAAE,EAAE,EAAEC,MAAM,EAAE,GAAA;AACtD,IAAA,IAAIC,6BAA6BF,SAAY,CAAA,EAAA;QAC3CC,MAAOF,CAAAA,GAAAA,CAAAA;AACT;AACF;;;;"}

View File

@@ -0,0 +1,4 @@
import type { Visitor } from '../../traverse/factory';
declare const visitor: Visitor;
export default visitor;
//# sourceMappingURL=remove-password.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"remove-password.d.ts","sourceRoot":"","sources":["../../../src/sanitize/visitors/remove-password.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AAEtD,QAAA,MAAM,OAAO,EAAE,OAId,CAAC;AAEF,eAAe,OAAO,CAAC"}

View File

@@ -0,0 +1,10 @@
'use strict';
const visitor = ({ key, attribute }, { remove })=>{
if (attribute?.type === 'password') {
remove(key);
}
};
module.exports = visitor;
//# sourceMappingURL=remove-password.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"remove-password.js","sources":["../../../src/sanitize/visitors/remove-password.ts"],"sourcesContent":["import type { Visitor } from '../../traverse/factory';\n\nconst visitor: Visitor = ({ key, attribute }, { remove }) => {\n if (attribute?.type === 'password') {\n remove(key);\n }\n};\n\nexport default visitor;\n"],"names":["visitor","key","attribute","remove","type"],"mappings":";;AAEMA,MAAAA,OAAAA,GAAmB,CAAC,EAAEC,GAAG,EAAEC,SAAS,EAAE,EAAE,EAAEC,MAAM,EAAE,GAAA;IACtD,IAAID,SAAAA,EAAWE,SAAS,UAAY,EAAA;QAClCD,MAAOF,CAAAA,GAAAA,CAAAA;AACT;AACF;;;;"}

View File

@@ -0,0 +1,8 @@
const visitor = ({ key, attribute }, { remove })=>{
if (attribute?.type === 'password') {
remove(key);
}
};
export { visitor as default };
//# sourceMappingURL=remove-password.mjs.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"remove-password.mjs","sources":["../../../src/sanitize/visitors/remove-password.ts"],"sourcesContent":["import type { Visitor } from '../../traverse/factory';\n\nconst visitor: Visitor = ({ key, attribute }, { remove }) => {\n if (attribute?.type === 'password') {\n remove(key);\n }\n};\n\nexport default visitor;\n"],"names":["visitor","key","attribute","remove","type"],"mappings":"AAEMA,MAAAA,OAAAA,GAAmB,CAAC,EAAEC,GAAG,EAAEC,SAAS,EAAE,EAAE,EAAEC,MAAM,EAAE,GAAA;IACtD,IAAID,SAAAA,EAAWE,SAAS,UAAY,EAAA;QAClCD,MAAOF,CAAAA,GAAAA,CAAAA;AACT;AACF;;;;"}

View File

@@ -0,0 +1,4 @@
import type { Visitor } from '../../traverse/factory';
declare const visitor: Visitor;
export default visitor;
//# sourceMappingURL=remove-private.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"remove-private.d.ts","sourceRoot":"","sources":["../../../src/sanitize/visitors/remove-private.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AAEtD,QAAA,MAAM,OAAO,EAAE,OAUd,CAAC;AAEF,eAAe,OAAO,CAAC"}

View File

@@ -0,0 +1,16 @@
'use strict';
var contentTypes = require('../../content-types.js');
const visitor = ({ schema, key, attribute }, { remove })=>{
if (!attribute) {
return;
}
const isPrivate = attribute.private === true || contentTypes.isPrivateAttribute(schema, key);
if (isPrivate) {
remove(key);
}
};
module.exports = visitor;
//# sourceMappingURL=remove-private.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"remove-private.js","sources":["../../../src/sanitize/visitors/remove-private.ts"],"sourcesContent":["import { isPrivateAttribute } from '../../content-types';\nimport type { Visitor } from '../../traverse/factory';\n\nconst visitor: Visitor = ({ schema, key, attribute }, { remove }) => {\n if (!attribute) {\n return;\n }\n\n const isPrivate = attribute.private === true || isPrivateAttribute(schema, key);\n\n if (isPrivate) {\n remove(key);\n }\n};\n\nexport default visitor;\n"],"names":["visitor","schema","key","attribute","remove","isPrivate","private","isPrivateAttribute"],"mappings":";;;;AAGA,MAAMA,OAAmB,GAAA,CAAC,EAAEC,MAAM,EAAEC,GAAG,EAAEC,SAAS,EAAE,EAAE,EAAEC,MAAM,EAAE,GAAA;AAC9D,IAAA,IAAI,CAACD,SAAW,EAAA;AACd,QAAA;AACF;AAEA,IAAA,MAAME,YAAYF,SAAUG,CAAAA,OAAO,KAAK,IAAA,IAAQC,gCAAmBN,MAAQC,EAAAA,GAAAA,CAAAA;AAE3E,IAAA,IAAIG,SAAW,EAAA;QACbD,MAAOF,CAAAA,GAAAA,CAAAA;AACT;AACF;;;;"}

View File

@@ -0,0 +1,14 @@
import { isPrivateAttribute } from '../../content-types.mjs';
const visitor = ({ schema, key, attribute }, { remove })=>{
if (!attribute) {
return;
}
const isPrivate = attribute.private === true || isPrivateAttribute(schema, key);
if (isPrivate) {
remove(key);
}
};
export { visitor as default };
//# sourceMappingURL=remove-private.mjs.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"remove-private.mjs","sources":["../../../src/sanitize/visitors/remove-private.ts"],"sourcesContent":["import { isPrivateAttribute } from '../../content-types';\nimport type { Visitor } from '../../traverse/factory';\n\nconst visitor: Visitor = ({ schema, key, attribute }, { remove }) => {\n if (!attribute) {\n return;\n }\n\n const isPrivate = attribute.private === true || isPrivateAttribute(schema, key);\n\n if (isPrivate) {\n remove(key);\n }\n};\n\nexport default visitor;\n"],"names":["visitor","schema","key","attribute","remove","isPrivate","private","isPrivateAttribute"],"mappings":";;AAGA,MAAMA,OAAmB,GAAA,CAAC,EAAEC,MAAM,EAAEC,GAAG,EAAEC,SAAS,EAAE,EAAE,EAAEC,MAAM,EAAE,GAAA;AAC9D,IAAA,IAAI,CAACD,SAAW,EAAA;AACd,QAAA;AACF;AAEA,IAAA,MAAME,YAAYF,SAAUG,CAAAA,OAAO,KAAK,IAAA,IAAQC,mBAAmBN,MAAQC,EAAAA,GAAAA,CAAAA;AAE3E,IAAA,IAAIG,SAAW,EAAA;QACbD,MAAOF,CAAAA,GAAAA,CAAAA;AACT;AACF;;;;"}

View File

@@ -0,0 +1,4 @@
import type { Visitor } from '../../traverse/factory';
declare const _default: (restrictedFields?: string[] | null) => Visitor;
export default _default;
//# sourceMappingURL=remove-restricted-fields.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"remove-restricted-fields.d.ts","sourceRoot":"","sources":["../../../src/sanitize/visitors/remove-restricted-fields.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;4CAEpB,MAAM,EAAE,GAAG,IAAI,KAAU,OAAO;AAAlE,wBA4BI"}

View File

@@ -0,0 +1,28 @@
'use strict';
var fp = require('lodash/fp');
var removeRestrictedFields = ((restrictedFields = null)=>({ key, path: { attribute: path } }, { remove })=>{
// Remove all fields
if (restrictedFields === null) {
remove(key);
return;
}
// Throw on invalid formats
if (!(fp.isArray(restrictedFields) && restrictedFields.every(fp.isString))) {
throw new TypeError(`Expected array of strings for restrictedFields but got "${typeof restrictedFields}"`);
}
// Remove if an exact match was found
if (restrictedFields.includes(path)) {
remove(key);
return;
}
// Remove nested matches
const isRestrictedNested = restrictedFields.some((allowedPath)=>path?.toString().startsWith(`${allowedPath}.`));
if (isRestrictedNested) {
remove(key);
}
});
module.exports = removeRestrictedFields;
//# sourceMappingURL=remove-restricted-fields.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"remove-restricted-fields.js","sources":["../../../src/sanitize/visitors/remove-restricted-fields.ts"],"sourcesContent":["import { isArray, isString } from 'lodash/fp';\nimport type { Visitor } from '../../traverse/factory';\n\nexport default (restrictedFields: string[] | null = null): Visitor =>\n ({ key, path: { attribute: path } }, { remove }) => {\n // Remove all fields\n if (restrictedFields === null) {\n remove(key);\n return;\n }\n\n // Throw on invalid formats\n if (!(isArray(restrictedFields) && restrictedFields.every(isString))) {\n throw new TypeError(\n `Expected array of strings for restrictedFields but got \"${typeof restrictedFields}\"`\n );\n }\n\n // Remove if an exact match was found\n if (restrictedFields.includes(path as string)) {\n remove(key);\n return;\n }\n\n // Remove nested matches\n const isRestrictedNested = restrictedFields.some((allowedPath) =>\n path?.toString().startsWith(`${allowedPath}.`)\n );\n if (isRestrictedNested) {\n remove(key);\n }\n };\n"],"names":["restrictedFields","key","path","attribute","remove","isArray","every","isString","TypeError","includes","isRestrictedNested","some","allowedPath","toString","startsWith"],"mappings":";;;;AAGA,6BAAe,CAAA,CAACA,gBAAAA,GAAoC,IAAI,GACtD,CAAC,EAAEC,GAAG,EAAEC,IAAM,EAAA,EAAEC,WAAWD,IAAI,EAAE,EAAE,EAAE,EAAEE,MAAM,EAAE,GAAA;;AAE7C,QAAA,IAAIJ,qBAAqB,IAAM,EAAA;YAC7BI,MAAOH,CAAAA,GAAAA,CAAAA;AACP,YAAA;AACF;;QAGA,IAAI,EAAEI,UAAQL,CAAAA,gBAAAA,CAAAA,IAAqBA,iBAAiBM,KAAK,CAACC,YAAQ,CAAI,EAAA;YACpE,MAAM,IAAIC,UACR,CAAC,wDAAwD,EAAE,OAAOR,gBAAAA,CAAiB,CAAC,CAAC,CAAA;AAEzF;;QAGA,IAAIA,gBAAAA,CAAiBS,QAAQ,CAACP,IAAiB,CAAA,EAAA;YAC7CE,MAAOH,CAAAA,GAAAA,CAAAA;AACP,YAAA;AACF;;AAGA,QAAA,MAAMS,kBAAqBV,GAAAA,gBAAAA,CAAiBW,IAAI,CAAC,CAACC,WAAAA,GAChDV,IAAMW,EAAAA,QAAAA,EAAAA,CAAWC,UAAW,CAAA,CAAC,EAAEF,WAAAA,CAAY,CAAC,CAAC,CAAA,CAAA;AAE/C,QAAA,IAAIF,kBAAoB,EAAA;YACtBN,MAAOH,CAAAA,GAAAA,CAAAA;AACT;AACF,KAAA;;;;"}

View File

@@ -0,0 +1,26 @@
import { isArray, isString } from 'lodash/fp';
var removeRestrictedFields = ((restrictedFields = null)=>({ key, path: { attribute: path } }, { remove })=>{
// Remove all fields
if (restrictedFields === null) {
remove(key);
return;
}
// Throw on invalid formats
if (!(isArray(restrictedFields) && restrictedFields.every(isString))) {
throw new TypeError(`Expected array of strings for restrictedFields but got "${typeof restrictedFields}"`);
}
// Remove if an exact match was found
if (restrictedFields.includes(path)) {
remove(key);
return;
}
// Remove nested matches
const isRestrictedNested = restrictedFields.some((allowedPath)=>path?.toString().startsWith(`${allowedPath}.`));
if (isRestrictedNested) {
remove(key);
}
});
export { removeRestrictedFields as default };
//# sourceMappingURL=remove-restricted-fields.mjs.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"remove-restricted-fields.mjs","sources":["../../../src/sanitize/visitors/remove-restricted-fields.ts"],"sourcesContent":["import { isArray, isString } from 'lodash/fp';\nimport type { Visitor } from '../../traverse/factory';\n\nexport default (restrictedFields: string[] | null = null): Visitor =>\n ({ key, path: { attribute: path } }, { remove }) => {\n // Remove all fields\n if (restrictedFields === null) {\n remove(key);\n return;\n }\n\n // Throw on invalid formats\n if (!(isArray(restrictedFields) && restrictedFields.every(isString))) {\n throw new TypeError(\n `Expected array of strings for restrictedFields but got \"${typeof restrictedFields}\"`\n );\n }\n\n // Remove if an exact match was found\n if (restrictedFields.includes(path as string)) {\n remove(key);\n return;\n }\n\n // Remove nested matches\n const isRestrictedNested = restrictedFields.some((allowedPath) =>\n path?.toString().startsWith(`${allowedPath}.`)\n );\n if (isRestrictedNested) {\n remove(key);\n }\n };\n"],"names":["restrictedFields","key","path","attribute","remove","isArray","every","isString","TypeError","includes","isRestrictedNested","some","allowedPath","toString","startsWith"],"mappings":";;AAGA,6BAAe,CAAA,CAACA,gBAAAA,GAAoC,IAAI,GACtD,CAAC,EAAEC,GAAG,EAAEC,IAAM,EAAA,EAAEC,WAAWD,IAAI,EAAE,EAAE,EAAE,EAAEE,MAAM,EAAE,GAAA;;AAE7C,QAAA,IAAIJ,qBAAqB,IAAM,EAAA;YAC7BI,MAAOH,CAAAA,GAAAA,CAAAA;AACP,YAAA;AACF;;QAGA,IAAI,EAAEI,OAAQL,CAAAA,gBAAAA,CAAAA,IAAqBA,iBAAiBM,KAAK,CAACC,SAAQ,CAAI,EAAA;YACpE,MAAM,IAAIC,UACR,CAAC,wDAAwD,EAAE,OAAOR,gBAAAA,CAAiB,CAAC,CAAC,CAAA;AAEzF;;QAGA,IAAIA,gBAAAA,CAAiBS,QAAQ,CAACP,IAAiB,CAAA,EAAA;YAC7CE,MAAOH,CAAAA,GAAAA,CAAAA;AACP,YAAA;AACF;;AAGA,QAAA,MAAMS,kBAAqBV,GAAAA,gBAAAA,CAAiBW,IAAI,CAAC,CAACC,WAAAA,GAChDV,IAAMW,EAAAA,QAAAA,EAAAA,CAAWC,UAAW,CAAA,CAAC,EAAEF,WAAAA,CAAY,CAAC,CAAC,CAAA,CAAA;AAE/C,QAAA,IAAIF,kBAAoB,EAAA;YACtBN,MAAOH,CAAAA,GAAAA,CAAAA;AACT;AACF,KAAA;;;;"}

View File

@@ -0,0 +1,4 @@
import type { Visitor } from '../../traverse/factory';
declare const _default: (auth: unknown) => Visitor;
export default _default;
//# sourceMappingURL=remove-restricted-relations.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"remove-restricted-relations.d.ts","sourceRoot":"","sources":["../../../src/sanitize/visitors/remove-restricted-relations.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;+BAShC,OAAO,KAAG,OAAO;AAAvC,wBAsHI"}

View File

@@ -0,0 +1,116 @@
'use strict';
var fp = require('lodash/fp');
var contentTypes = require('../../content-types.js');
var relations = require('../../relations.js');
const ACTIONS_TO_VERIFY = [
'find'
];
const { CREATED_BY_ATTRIBUTE, UPDATED_BY_ATTRIBUTE } = contentTypes.constants;
var removeRestrictedRelations = ((auth)=>async ({ data, key, attribute, schema }, { remove, set })=>{
if (!attribute) {
return;
}
const isRelation = attribute.type === 'relation';
if (!isRelation) {
return;
}
const handleMorphRelation = async ()=>{
const elements = data[key];
if ('connect' in elements || 'set' in elements || 'disconnect' in elements) {
const newValue = {};
const connect = await handleMorphElements(elements.connect || []);
const relSet = await handleMorphElements(elements.set || []);
const disconnect = await handleMorphElements(elements.disconnect || []);
if (connect.length > 0) {
newValue.connect = connect;
}
if (relSet.length > 0) {
newValue.set = relSet;
}
if (disconnect.length > 0) {
newValue.disconnect = disconnect;
}
// TODO: this should technically be in its own visitor to check morph options, but for now we'll handle it here
if ('options' in elements && typeof elements.options === 'object' && elements.options !== null) {
const filteredOptions = {};
// Iterate through the keys of elements.options
Object.keys(elements.options).forEach((key)=>{
const validator = relations.VALID_RELATION_ORDERING_KEYS[key];
// Ensure the key exists in VALID_RELATION_ORDERING_KEYS and the validator is defined before calling it
if (validator && validator(elements.options[key])) {
filteredOptions[key] = elements.options[key];
}
});
// Assign the filtered options back to newValue
newValue.options = filteredOptions;
} else {
newValue.options = {};
}
set(key, newValue);
} else {
const newMorphValue = await handleMorphElements(elements);
if (newMorphValue.length) {
set(key, newMorphValue);
}
}
};
const handleMorphElements = async (elements)=>{
const allowedElements = [];
if (!fp.isArray(elements)) {
return allowedElements;
}
for (const element of elements){
if (!fp.isObject(element) || !('__type' in element)) {
continue;
}
const scopes = ACTIONS_TO_VERIFY.map((action)=>`${element.__type}.${action}`);
const isAllowed = await hasAccessToSomeScopes(scopes, auth);
if (isAllowed) {
allowedElements.push(element);
}
}
return allowedElements;
};
const handleRegularRelation = async ()=>{
const scopes = ACTIONS_TO_VERIFY.map((action)=>`${attribute.target}.${action}`);
const isAllowed = await hasAccessToSomeScopes(scopes, auth);
// If the authenticated user don't have access to any of the scopes, then remove the field
if (!isAllowed) {
remove(key);
}
};
const isCreatorRelation = [
CREATED_BY_ATTRIBUTE,
UPDATED_BY_ATTRIBUTE
].includes(key);
// Polymorphic relations
if (contentTypes.isMorphToRelationalAttribute(attribute)) {
await handleMorphRelation();
return;
}
// Creator relations
if (isCreatorRelation && schema.options?.populateCreatorFields) {
// do nothing
return;
}
// Regular relations
await handleRegularRelation();
});
const hasAccessToSomeScopes = async (scopes, auth)=>{
for (const scope of scopes){
try {
await strapi.auth.verify(auth, {
scope
});
return true;
} catch {
continue;
}
}
return false;
};
module.exports = removeRestrictedRelations;
//# sourceMappingURL=remove-restricted-relations.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,114 @@
import { isArray, isObject } from 'lodash/fp';
import { isMorphToRelationalAttribute, constants } from '../../content-types.mjs';
import { VALID_RELATION_ORDERING_KEYS } from '../../relations.mjs';
const ACTIONS_TO_VERIFY = [
'find'
];
const { CREATED_BY_ATTRIBUTE, UPDATED_BY_ATTRIBUTE } = constants;
var removeRestrictedRelations = ((auth)=>async ({ data, key, attribute, schema }, { remove, set })=>{
if (!attribute) {
return;
}
const isRelation = attribute.type === 'relation';
if (!isRelation) {
return;
}
const handleMorphRelation = async ()=>{
const elements = data[key];
if ('connect' in elements || 'set' in elements || 'disconnect' in elements) {
const newValue = {};
const connect = await handleMorphElements(elements.connect || []);
const relSet = await handleMorphElements(elements.set || []);
const disconnect = await handleMorphElements(elements.disconnect || []);
if (connect.length > 0) {
newValue.connect = connect;
}
if (relSet.length > 0) {
newValue.set = relSet;
}
if (disconnect.length > 0) {
newValue.disconnect = disconnect;
}
// TODO: this should technically be in its own visitor to check morph options, but for now we'll handle it here
if ('options' in elements && typeof elements.options === 'object' && elements.options !== null) {
const filteredOptions = {};
// Iterate through the keys of elements.options
Object.keys(elements.options).forEach((key)=>{
const validator = VALID_RELATION_ORDERING_KEYS[key];
// Ensure the key exists in VALID_RELATION_ORDERING_KEYS and the validator is defined before calling it
if (validator && validator(elements.options[key])) {
filteredOptions[key] = elements.options[key];
}
});
// Assign the filtered options back to newValue
newValue.options = filteredOptions;
} else {
newValue.options = {};
}
set(key, newValue);
} else {
const newMorphValue = await handleMorphElements(elements);
if (newMorphValue.length) {
set(key, newMorphValue);
}
}
};
const handleMorphElements = async (elements)=>{
const allowedElements = [];
if (!isArray(elements)) {
return allowedElements;
}
for (const element of elements){
if (!isObject(element) || !('__type' in element)) {
continue;
}
const scopes = ACTIONS_TO_VERIFY.map((action)=>`${element.__type}.${action}`);
const isAllowed = await hasAccessToSomeScopes(scopes, auth);
if (isAllowed) {
allowedElements.push(element);
}
}
return allowedElements;
};
const handleRegularRelation = async ()=>{
const scopes = ACTIONS_TO_VERIFY.map((action)=>`${attribute.target}.${action}`);
const isAllowed = await hasAccessToSomeScopes(scopes, auth);
// If the authenticated user don't have access to any of the scopes, then remove the field
if (!isAllowed) {
remove(key);
}
};
const isCreatorRelation = [
CREATED_BY_ATTRIBUTE,
UPDATED_BY_ATTRIBUTE
].includes(key);
// Polymorphic relations
if (isMorphToRelationalAttribute(attribute)) {
await handleMorphRelation();
return;
}
// Creator relations
if (isCreatorRelation && schema.options?.populateCreatorFields) {
// do nothing
return;
}
// Regular relations
await handleRegularRelation();
});
const hasAccessToSomeScopes = async (scopes, auth)=>{
for (const scope of scopes){
try {
await strapi.auth.verify(auth, {
scope
});
return true;
} catch {
continue;
}
}
return false;
};
export { removeRestrictedRelations as default };
//# sourceMappingURL=remove-restricted-relations.mjs.map

File diff suppressed because one or more lines are too long