hasPermission.ts 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. // Copyright (C) 2012-2022 Zammad Foundation, https://zammad-foundation.org/
  2. /**
  3. * Check if the access can be granted for the given permissions.
  4. *
  5. * Examples:
  6. * hasPermission('ticket.agent', [...]) # access to certain permission key
  7. * hasPermission['ticket.agent', 'ticket.customer'], [...]) # access to one of permission keys
  8. *
  9. * hasPermission('user_preferences.calendar+ticket.agent', [...]) # access must have two permission keys
  10. *
  11. * hasPermission('admin.*', [...]) # access if one sub key access exists
  12. *
  13. * @param {Array<string>|string} requiredPermission - The permissions which are required.
  14. * @param {Array<string>} permissions - The available permission.
  15. *
  16. * @returns {boolean}
  17. */
  18. const hasPermission = (
  19. requiredPermission: Array<string> | string,
  20. permissions: Array<string>,
  21. ): boolean => {
  22. const requiredPermissions = Array.isArray(requiredPermission)
  23. ? requiredPermission
  24. : [requiredPermission]
  25. // Available with any permission.
  26. if (requiredPermissions.length === 0 || requiredPermissions.includes('*')) {
  27. return true
  28. }
  29. // If a permission is needed, but no permission was given, permission will not be granted.
  30. if (permissions.length === 0) return false
  31. for (const localRequirePermission of requiredPermissions) {
  32. // The permission can be combined with a 'AND', then every single permission needs to match.
  33. const localRequiredPermissions = localRequirePermission.split('+')
  34. let accessGranted = false
  35. for (const requiredPermissionItem of localRequiredPermissions) {
  36. let singleAccessGranted = false
  37. // Check first if a permission with wildcard is matching.
  38. if (requiredPermissionItem.includes('*')) {
  39. const regexRequiredPermission = new RegExp(
  40. requiredPermissionItem.replace('.', '\\.').replace('*', '.+'),
  41. )
  42. singleAccessGranted = permissions.some((permission) =>
  43. regexRequiredPermission.test(permission),
  44. )
  45. }
  46. // If not already a wildcard permission match exists, check for a direct permission.
  47. if (!singleAccessGranted) {
  48. const partsRequiredPermission = requiredPermissionItem.split('.')
  49. let checkPartsRequiredPermission = ''
  50. for (const partRequiredPermission of partsRequiredPermission) {
  51. if (checkPartsRequiredPermission) checkPartsRequiredPermission += '.'
  52. checkPartsRequiredPermission += partRequiredPermission
  53. singleAccessGranted = permissions.includes(
  54. checkPartsRequiredPermission,
  55. )
  56. if (singleAccessGranted) break
  57. }
  58. }
  59. accessGranted = singleAccessGranted
  60. // If one permission not exists, no access can be granted for this required permission.
  61. if (!accessGranted) break
  62. }
  63. // If one required permission matches, the access can be granted.
  64. if (accessGranted) return accessGranted
  65. }
  66. return false
  67. }
  68. export default hasPermission