{"version":3,"file":"index.mjs","sources":["../src/index.js"],"sourcesContent":["import { propEq, intersection, difference, includes, is, curry, map, prop, either, identity } from 'ramda'\nimport roles from './roles'\nexport const ROLES = roles\n\nconst hroles = ROLES.reduce((acc, role) => {\n  acc[role.id] = role\n  return acc\n}, {})\n\n/**\n * Checks if a user has all specified roles\n * @function hasAllRoles\n * @tag users\n * @param {Array|string} - Roles to check\n * @param {Object} - User object containing roles\n * @return {boolean} - Returns true if the user has all specified roles, otherwise false\n * @example\n *\n *   expect(hasAllRoles(['a', 'b'], { roles: ['a', 'b', 'c'] })).toBeTruthy()\n *   expect(hasAllRoles(['a', 'b'], { roles: ['a', 'd'] })).toBeFalsy()\n *\n */\nexport const hasAllRoles = curry((roles, user) => {\n  if (!user) return false\n  const mustHave = is(Array, roles) ? roles : [roles]\n  return !difference(mustHave, user.roles || []).length\n})\n\n/**\n * Alias for `hasAllRoles`\n * @function hasRole\n */\nexport const hasRole = hasAllRoles\n\n/**\n * Alias for `hasAllRoles`\n * @function hasRoles\n */\nexport const hasRoles = hasAllRoles\n\n/**\n * Checks if a user is an administrator\n * @function isAdmin\n * @tag users\n * @param {Object} - User object containing roles\n * @return {boolean} - Returns true if the user is an administrator, otherwise false\n * @example\n *\n *   expect(isAdmin({ roles: ['admin'] })).toBeTruthy()\n *   expect(isAdmin({ roles: ['admin', 'toto'] })).toBeTruthy()\n *   expect(isAdmin({ roles: ['titi', 'toto'] })).toBeFalsy()\n *\n */\nexport const isAdmin = hasRole('admin')\n\n/**\n * Checks if a user has some of the specified roles\n * @function hasSomeRole\n * @tag users\n * @param {Array|string} - Roles to check\n * @param {Object} - User object containing roles\n * @return {boolean} - Returns true if the user has some of the specified roles, otherwise false\n * @example\n *\n *   expect(hasSomeRoles(['a', 'b'], { roles: ['a'] })).toBeTruthy()\n *   expect(hasSomeRoles(['a', 'b'], { roles: ['c', 'd'] })).toBeFalsy()\n *\n */\nexport const hasSomeRoles = curry((roles, user) => {\n  if (!user) return false\n  const some = is(Array, roles) ? roles : [roles]\n  return intersection(some, user.roles || []).length\n})\n\n/**\n * Checks if a user has a root role\n * @function hasRootRole\n * @tag users\n * @param {string} - Root role to check\n * @param {Object} - User object containing roles\n * @return {boolean} - Returns true if the user has the root role, otherwise false\n * @example\n *\n *   expect(hasRootRole('a:b', { roles: ['a:b:c', '1:2'] })).toBeTruthy()\n *   expect(hasRootRole('a:b', { roles: ['1:a:b:c', '1:2'] })).toBeFalsy()\n *\n */\nexport const hasRootRole = curry((role, user) => {\n  if (!user) return false\n  for (const userRole of user.roles || []) {\n    if (userRole.startsWith(role)) return true\n  }\n  return false\n})\n\n/**\n * Checks if a user can wrte on artefacts linked to all specified agencies\n * @function hasAgencies\n * @tag users\n * @param {Array|string} - Agency Ids to check\n * @param {string|{id}} - Member ID\n * @param {Object} - User object containing members and related agencies\n * @return {boolean} - Returns true if the user has all specified agencyIds, otherwise false\n * @example\n *\n *   const user = {\n       members: [{ id: 'member1', agencies: [{ id: 'AGENCY1' }, { id: 'AGENCY2' }] }],\n     }\n\n *   expect(hasAgencies(['AGENCY1', 'AGENCY2'], 'unknownMember', user)).toBeFalsy()\n *   expect(hasAgencies('AGENCY1', 'member1', user)).toBeTruthy()\n *   expect(hasAgencies('AGENCY2', 'member1', user)).toBeTruthy()\n * \n *   expect(hasAgencies('AGENCY1.FSD', 'member1', user)).toBeTruthy()\n *   expect(hasAgencies(['AGENCY1','AGENCY1.FSD'], 'member1', user)).toBeTruthy()\n * \n *   expect(hasAgencies(['AGENCY1', 'AGENCY2'], 'member1', user)).toBeTruthy() \n *   expect(hasAgencies(['AGENCY1', 'AGENCY2', 'unknownAgencyId'], 'member1', user)).toBeFalsy() \n *   expect(hasAgencies('unknownAgencyId', 'member1', user)).toBeFalsy() \n *\n */\nexport const hasAgencies = (agencyIds, memberId, user) => {\n  if (!agencyIds || !memberId || !user) return false\n  if (isAdmin(user)) return true\n  if (!user.members?.length) return false\n\n  agencyIds = Array.isArray(agencyIds) ? agencyIds : [agencyIds]\n  if (memberId.id) memberId = memberId.id\n\n  const userMember = user.members.find(member => member.id === memberId)\n  if (!userMember?.agencies) return true\n  if (!userMember.agencies.length) return false\n\n  const userAgencyIds = map(prop('id'), userMember.agencies)\n\n  for (const agencyId of agencyIds) {\n    const hasAccess = userAgencyIds.some(\n      userAgencyId => agencyId === userAgencyId || agencyId.startsWith(`${userAgencyId}.`),\n    )\n    if (!hasAccess) return false\n  }\n\n  return true\n}\n\n/**\n * Returns a list of writable agencies\n * @function getWritableAgencies\n * @tag users\n * @param {Array} - Agency List\n * @param {string} - Member ID\n * @param {Object} - User object containing members and related agencies\n * @return {Array} - Returns the list of writable agencies for the specified memberId and the specified user\n * @example\n *\n *   const user = {\n *     members: [\n *       {\n *         id: 'member1',\n *         agencies: [{ id: 'FSD' }],\n *       },\n *       {\n *         id: 'member2',\n *         agencies: [{ id: 'SDMX' }],\n *       },\n *       {\n *         id: 'member3',\n *         agencies: [{ id: 'ORG' }],\n *       },\n *     ],\n *   }\n *\n *   const agencyList = [\n *     { id: 'FSD', name: 'FSD' },\n *     { id: 'SDMX', name: 'SDMX' },\n *     { id: 'ORG', name: 'ORG' },\n *     { id: 'ORG.TEST1', name: 'TEST1' },\n *     { id: 'ORG.TEST2', name: 'TEST2' },\n *   ]\n *\n *   expect(getWritableAgencies(agencyList, 'member1', { roles: ['admin'] })).toStrictEqual(agencyList)\n *   expect(getWritableAgencies(agencyList, 'member1', user)).toStrictEqual([{ id: 'FSD', name: 'FSD' }])\n *   expect(getWritableAgencies(agencyList, 'member2', user)).toStrictEqual([{ id: 'SDMX', name: 'SDMX' }])\n *   expect(getWritableAgencies(agencyList, 'member3', user)).toStrictEqual([{ id: 'ORG', name: 'ORG' }, { id: 'ORG.TEST1', name: 'TEST1' }, { id: 'ORG.TEST2', name: 'TEST2' }])\n *\n */\nexport const getWritableAgencies = (agencyList, memberId, user) => {\n  if (!agencyList?.length || !memberId || !user) return []\n  if (isAdmin(user)) return agencyList\n  if (!user.members?.length) return []\n\n  if (memberId.id) memberId = memberId.id\n\n  const userMember = user.members.find(member => member.id === memberId)\n  if (!userMember?.agencies) return agencyList\n  if (!userMember.agencies.length) return []\n\n  const userAgencyIds = map(prop('id'), userMember.agencies)\n\n  return agencyList.filter(agency =>\n    userAgencyIds.some(userAgencyId => {\n      const agencyId = agency.agencyID ?? agency.id\n      if (!agencyId) return false\n\n      return agencyId.startsWith(userAgencyId)\n    }),\n  )\n}\n\n/**\n * Checks if a user has the specified permission\n * @function hasPermission\n * @tag users\n * @param {string} - Permission to check\n * @param {Object} - User object containing roles and permissions\n * @return {boolean} - Returns true if the user has all specified permissions, otherwise false\n * @example\n *\n *   expect(hasPermission('sxs:spaces:read', { roles: ['sxs:spaces:editor'] })).toBeTruthy()\n *   expect(hasPermission('sxs:spaces:*', { roles: ['sxs:spaces:editor'] })).toBeTruthy()\n *   expect(hasPermission('jobs:viewer', { roles: ['sxs:spaces:editor'] })).toBeFalsy()\n *\n */\n\nexport const hasPermission = (permission, user) => {\n  if (!permission || !user) return false\n  if (isAdmin(user)) return true\n  const idx = permission.indexOf('*')\n  const permissions = []\n  for (const permission of getRolesPermissions(user.roles)) permissions.push(permission)\n  if (idx !== -1) {\n    const regexp = new RegExp(`^${permission.slice(0, idx)}`)\n    for (const permission of permissions) {\n      if (regexp.test(permission)) return true\n    }\n    return false\n  } else {\n    return permissions?.includes(permission)\n  }\n}\n\n/**\n * Checks if a user has all specified permissions\n * @function hasPermissions\n * @tag users\n * @param {Array|string} - Permissions to check\n * @param {Object} - User object containing roles and permissions\n * @return {boolean} - Returns true if the user has all specified permissions, otherwise false\n * @example\n *\n *   expect(hasPermissions(['jobs*'], { roles: ['sxs:spaces:editor'] })).toBeFalsy()\n *   expect(hasPermissions('a:b', { roles: ['admin'] })).toBeTruthy()\n *\n */\nexport const hasPermissions = (permissions, user) => {\n  if (!permissions || !user) return false\n  if (isAdmin(user)) return true\n  const some = is(Array, permissions) ? permissions : [permissions]\n  for (const permission of some) {\n    if (!hasPermission(permission, user)) return false\n  }\n  return true\n}\n\n/**\n * Checks if a user is a member\n * @function hasMember\n * @tag users\n * @param {string} - Member ID to check\n * @param {Object} - User object containing member information\n * @return {boolean} - Returns true if the user is a member, otherwise false\n * @example\n *\n *   expect(hasMember('toto', { members: ['toto', 'titi'] })).toBeTruthy()\n *   expect(hasMember('toto', { roles: ['admin'] })).toBeTruthy()\n *   expect(hasMember('tot', { members: ['toto', 'titi'] })).toBeFalsy()\n *\n */\nexport const hasMember = curry((member, user) => {\n  if (!user) return false\n  if (isAdmin(user)) return true\n  const memberIds = getMemberIds(user)\n  return includes(member, memberIds)\n})\n\nexport const getMemberIds = user => {\n  if (!user || isAdmin(user)) return\n  return map(either(prop('id'), identity), user.members || [])\n}\n\nexport const STATUS = {\n  active: 'active',\n  inactive: 'inactive',\n  pending: 'pending',\n}\n\n/**\n * Checks if a user is active\n * @function isActive\n * @tag users\n * @param {Object} - User object containing status information\n * @return {boolean} - Returns true if the user is active, otherwise false\n * @example\n *\n * isActive({status: 'active'}) // true\n * isActive({status: 'inactive'}) //false\n * isActive({status: 'pending'}) //false\n *\n */\nexport const isActive = propEq('status', STATUS.active)\n\n/**\n * Checks if a user is inactive\n * @function isInActive\n * @tag users\n * @param {Object} - User object containing status information\n * @return {boolean} - Returns true if the user is inactive, otherwise false\n * @example\n *\n * isActive({status: 'active'}) // false\n * isActive({status: 'inactive'}) //true\n * isActive({status: 'pending'}) //false\n *\n */\nexport const isInActive = propEq('status', STATUS.inactive)\n\n/**\n * Checks if a user is pending\n * @function isPending\n * @tag users\n * @param {Object} - User object containing status information\n * @return {boolean} - Returns true if the user is pending, otherwise false\n * @example\n *\n * isActive({status: 'active'}) // false\n * isActive({status: 'inactive'}) //false\n * isActive({status: 'pending'}) //true\n *\n */\nexport const isPending = propEq('status', STATUS.pending)\n\n/**\n * Retrieves permissions from user roles\n * @function getRolesPermissions\n * @tag users\n * @param {Array|string} - User roles\n * @return {Array} - Array of permissions\n */\nexport const getRolesPermissions = roles => {\n  if (!roles) return []\n  const permissions = []\n  for (const role of is(Array, roles) ? roles : [roles]) {\n    for (const permission of hroles[role]?.permissions || []) {\n      permissions.push(permission)\n    }\n  }\n  return permissions\n}\n"],"names":[],"mappings":"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"}