{"version":3,"file":"throw-restricted-relations.mjs","sources":["../../../src/validate/visitors/throw-restricted-relations.ts"],"sourcesContent":["import { isArray, isObject } from 'lodash/fp';\nimport * as contentTypeUtils from '../../content-types';\nimport { throwInvalidKey } from '../utils';\nimport type { Visitor } from '../../traverse/factory';\nimport { VALID_RELATION_ORDERING_KEYS } from '../../relations';\n\nconst ACTIONS_TO_VERIFY = ['find'];\nconst { CREATED_BY_ATTRIBUTE, UPDATED_BY_ATTRIBUTE } = contentTypeUtils.constants;\n\ntype MorphArray = Array<{ __type: string }>;\n\nexport default (auth: unknown): Visitor =>\n  async ({ data, key, attribute, schema, path }) => {\n    if (!attribute) {\n      return;\n    }\n\n    const isRelation = attribute.type === 'relation';\n\n    if (!isRelation) {\n      return;\n    }\n\n    const handleMorphRelation = async () => {\n      const elements: any = (data as Record<string, MorphArray>)[key];\n\n      if (\n        'connect' in elements ||\n        'set' in elements ||\n        'disconnect' in elements ||\n        'options' in elements\n      ) {\n        await handleMorphElements(elements.connect || []);\n        await handleMorphElements(elements.set || []);\n        await handleMorphElements(elements.disconnect || []);\n\n        // TODO: this should technically be in its own visitor to check morph options, but for now we'll handle it here\n        if ('options' in elements) {\n          if (elements.options === null || elements.options === undefined) {\n            return;\n          }\n\n          if (typeof elements.options !== 'object') {\n            throwInvalidKey({ key, path: path.attribute });\n          }\n\n          const optionKeys = Object.keys(elements.options);\n\n          // Validate each key based on its validator function\n          for (const key of optionKeys) {\n            if (!(key in VALID_RELATION_ORDERING_KEYS)) {\n              throwInvalidKey({ key, path: path.attribute });\n            }\n            if (!VALID_RELATION_ORDERING_KEYS[key](elements.options[key])) {\n              throwInvalidKey({ key, path: path.attribute });\n            }\n          }\n        }\n      } else {\n        await handleMorphElements(elements);\n      }\n    };\n\n    const handleMorphElements = async (elements: any[]) => {\n      if (!isArray(elements)) {\n        throwInvalidKey({ key, path: path.attribute });\n      }\n\n      for (const element of elements) {\n        if (!isObject(element) || !('__type' in element)) {\n          throwInvalidKey({ key, path: path.attribute });\n        }\n\n        const scopes = ACTIONS_TO_VERIFY.map((action) => `${element.__type}.${action}`);\n        const isAllowed = await hasAccessToSomeScopes(scopes, auth);\n\n        if (!isAllowed) {\n          throwInvalidKey({ key, path: path.attribute });\n        }\n      }\n    };\n\n    const handleRegularRelation = async () => {\n      const scopes = ACTIONS_TO_VERIFY.map((action) => `${attribute.target}.${action}`);\n\n      const isAllowed = await hasAccessToSomeScopes(scopes, auth);\n\n      // If the authenticated user don't have access to any of the scopes\n      if (!isAllowed) {\n        throwInvalidKey({ key, path: path.attribute });\n      }\n    };\n\n    const isCreatorRelation = [CREATED_BY_ATTRIBUTE, UPDATED_BY_ATTRIBUTE].includes(key);\n\n    // Polymorphic relations\n    if (contentTypeUtils.isMorphToRelationalAttribute(attribute)) {\n      await handleMorphRelation();\n      return;\n    }\n\n    // Creator relations\n    if (isCreatorRelation && schema.options?.populateCreatorFields) {\n      // do nothing\n      return;\n    }\n\n    // Regular relations\n    await handleRegularRelation();\n  };\n\nconst hasAccessToSomeScopes = async (scopes: string[], auth: unknown) => {\n  for (const scope of scopes) {\n    try {\n      await strapi.auth.verify(auth, { scope });\n      return true;\n    } catch {\n      continue;\n    }\n  }\n\n  return false;\n};\n"],"names":["ACTIONS_TO_VERIFY","CREATED_BY_ATTRIBUTE","UPDATED_BY_ATTRIBUTE","contentTypeUtils","auth","data","key","attribute","schema","path","isRelation","type","handleMorphRelation","elements","handleMorphElements","connect","set","disconnect","options","undefined","throwInvalidKey","optionKeys","Object","keys","VALID_RELATION_ORDERING_KEYS","isArray","element","isObject","scopes","map","action","__type","isAllowed","hasAccessToSomeScopes","handleRegularRelation","target","isCreatorRelation","includes","populateCreatorFields","scope","strapi","verify"],"mappings":"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"}