{"version":3,"file":"throw-restricted-relations.mjs","sources":["../../../src/validate/visitors/throw-restricted-relations.ts"],"sourcesContent":["import { isObject } from 'lodash';\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 MorphMutationPayload = {\n  connect?: unknown[];\n  set?: unknown[];\n  disconnect?: unknown[];\n  options?: Record<string, unknown> | null;\n};\ntype MorphPopulatePayload = {\n  on: Record<string, unknown>;\n};\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 = (data as Record<string, unknown>)[key];\n\n      if (isMorphMutationPayload(elements)) {\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            const optionKey = key as keyof typeof VALID_RELATION_ORDERING_KEYS;\n            const validator = VALID_RELATION_ORDERING_KEYS[optionKey];\n\n            if (!validator) {\n              throwInvalidKey({ key, path: path.attribute });\n            }\n            if (!validator(elements.options[key])) {\n              throwInvalidKey({ key, path: path.attribute });\n            }\n          }\n        }\n      } else if (isMorphPopulatePayload(elements)) {\n        for (const uid of Object.keys(elements.on)) {\n          const scopes = ACTIONS_TO_VERIFY.map((action) => `${uid}.${action}`);\n          const isAllowed = await hasAccessToSomeScopes(scopes, auth);\n\n          if (!isAllowed) {\n            throwInvalidKey({ key, path: path.attribute });\n          }\n        }\n      } else {\n        await handleMorphElements(elements);\n      }\n    };\n\n    const isMorphMutationPayload = (value: unknown): value is MorphMutationPayload => {\n      return (\n        isObject(value) &&\n        ('connect' in value || 'set' in value || 'disconnect' in value || 'options' in value)\n      );\n    };\n\n    const isMorphPopulatePayload = (value: unknown): value is MorphPopulatePayload => {\n      return isObject(value) && !('__type' in value) && 'on' in value && isObject(value.on);\n    };\n\n    const isMorphPopulateAllOrCount = (value: unknown): value is true | { count: true } => {\n      return value === true || (isObject(value) && 'count' in value && value.count === true);\n    };\n\n    const handleMorphElements = async (elements: unknown) => {\n      if (!Array.isArray(elements)) {\n        throwInvalidKey({ key, path: path.attribute });\n      }\n\n      const morphElements = elements as unknown[];\n\n      for (const element of morphElements) {\n        if (!isObject(element) || !('__type' in element) || typeof element.__type !== 'string') {\n          throwInvalidKey({ key, path: path.attribute });\n        }\n\n        const type = (element as { __type: string }).__type;\n        const scopes = ACTIONS_TO_VERIFY.map((action) => `${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      const value = (data as Record<string, unknown>)[key];\n      if (isMorphPopulateAllOrCount(value)) {\n        return;\n      }\n\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","isMorphMutationPayload","handleMorphElements","connect","set","disconnect","options","undefined","throwInvalidKey","optionKeys","Object","keys","optionKey","validator","VALID_RELATION_ORDERING_KEYS","isMorphPopulatePayload","uid","on","scopes","map","action","isAllowed","hasAccessToSomeScopes","value","isObject","isMorphPopulateAllOrCount","count","Array","isArray","morphElements","element","__type","handleRegularRelation","target","isCreatorRelation","includes","populateCreatorFields","scope","strapi","verify"],"mappings":"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"}