scope-utils.ts 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. import {
  2. ACTION, ALL_SIGN, SCOPE, type Scope,
  3. } from '../../interfaces/scope';
  4. export const isValidScope = (scope: Scope): boolean => {
  5. const scopeParts = scope.split(':').map(x => (x === ALL_SIGN ? 'ALL' : x.toUpperCase()));
  6. let obj: any = SCOPE;
  7. scopeParts.forEach((part) => {
  8. if (obj[part] == null) {
  9. return false;
  10. }
  11. obj = obj[part];
  12. });
  13. return obj === scope;
  14. };
  15. export const hasAllScope = (scope: Scope): scope is Scope => {
  16. return scope.endsWith(`:${ALL_SIGN}`);
  17. };
  18. /**
  19. * Returns all values of the scope object
  20. * For example, SCOPE.READ.USER_SETTINGS.API.ALL returns ['read:user:api:access_token', 'read:user:api:api_token']
  21. */
  22. const getAllScopeValuesFromObj = (scopeObj: any): Scope[] => {
  23. const result: Scope[] = [];
  24. const traverse = (current: any): void => {
  25. if (typeof current !== 'object' || current === null) {
  26. if (typeof current === 'string') {
  27. result.push(current as Scope);
  28. }
  29. return;
  30. }
  31. Object.values(current).forEach((value) => {
  32. traverse(value);
  33. });
  34. };
  35. traverse(scopeObj);
  36. return result;
  37. };
  38. /**
  39. * Returns all implied scopes for a given scope
  40. * For example, WRITE permission implies READ permission
  41. */
  42. const getImpliedScopes = (scope: Scope): Scope[] => {
  43. const scopeParts = scope.split(':');
  44. if (scopeParts[0] === ACTION.READ) {
  45. return [scope];
  46. }
  47. if (scopeParts[0] === ACTION.WRITE) {
  48. return [scope, `${ACTION.READ}:${scopeParts.slice(1).join(':')}` as Scope];
  49. }
  50. return [];
  51. };
  52. export const extractAllScope = (scope: Scope): Scope[] => {
  53. if (!hasAllScope(scope)) {
  54. return [scope];
  55. }
  56. const result = [] as Scope[];
  57. const scopeParts = scope.split(':').map(x => (x.toUpperCase()));
  58. let obj: any = SCOPE;
  59. scopeParts.forEach((part) => {
  60. if (part === ALL_SIGN) {
  61. return;
  62. }
  63. obj = obj[part];
  64. });
  65. getAllScopeValuesFromObj(obj).forEach((value) => {
  66. result.push(value);
  67. });
  68. return result.filter(scope => !hasAllScope(scope));
  69. };
  70. /**
  71. * Extracts scopes from a given array of scopes
  72. * And delete all scopes
  73. * For example, [SCOPE.WRITE.USER_SETTINGS.API.ALL] === ['write:user:api:all']
  74. * returns ['read:user:api:access_token',
  75. * 'read:user:api:api_token'
  76. * 'write:user:api:access_token',
  77. * 'write:user:api:api_token']
  78. */
  79. export const extractScopes = (scopes?: Scope[]): Scope[] => {
  80. if (scopes == null) {
  81. return [];
  82. }
  83. const result = new Set<Scope>(); // remove duplicates
  84. const impliedScopes = new Set<Scope>();
  85. scopes.forEach((scope) => {
  86. getImpliedScopes(scope).forEach((impliedScope) => {
  87. impliedScopes.add(impliedScope);
  88. });
  89. });
  90. impliedScopes.forEach((scope) => {
  91. extractAllScope(scope).forEach((extractedScope) => {
  92. result.add(extractedScope);
  93. });
  94. });
  95. return Array.from(result);
  96. };