scope.ts 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. // SCOPE_SEED defines the basic scope structure.
  2. // When you need to set different permissions for Admin and User
  3. // on specific endpoints (like /me), use SCOPE rather than modifying SCOPE_SEED.
  4. // If you want to add a new scope, you only need to add a new key to the SCOPE_SEED object.
  5. // Change translation file contents (accesstoken_scopes_desc) when scope structure is modified
  6. const SCOPE_SEED_ADMIN = {
  7. admin: {
  8. top: {},
  9. app: {},
  10. security: {},
  11. markdown: {},
  12. customize: {},
  13. import_data: {},
  14. export_data: {},
  15. data_transfer: {},
  16. external_notification: {},
  17. slack_integration: {},
  18. legacy_slack_integration: {},
  19. user_management: {},
  20. user_group_management: {},
  21. audit_log: {},
  22. plugin: {},
  23. ai_integration: {},
  24. full_text_search: {},
  25. },
  26. } as const;
  27. const SCOPE_SEED_USER = {
  28. user_settings: {
  29. info: {},
  30. external_account: {},
  31. password: {},
  32. api: {
  33. api_token: {},
  34. access_token: {},
  35. },
  36. in_app_notification: {},
  37. other: {},
  38. },
  39. features: {
  40. ai_assistant: {},
  41. page: {},
  42. share_link: {},
  43. bookmark: {},
  44. questionnaire: {},
  45. attachment: {},
  46. },
  47. } as const;
  48. const SCOPE_SEED = {
  49. ...SCOPE_SEED_ADMIN,
  50. ...SCOPE_SEED_USER,
  51. } as const;
  52. export const ACTION = {
  53. READ: 'read',
  54. WRITE: 'write',
  55. } as const;
  56. type ACTION_TYPE = typeof ACTION[keyof typeof ACTION];
  57. export const ALL_SIGN = '*';
  58. const SCOPE_SEED_WITH_ACTION = Object.values(ACTION).reduce(
  59. (acc, action) => {
  60. acc[action] = SCOPE_SEED;
  61. return acc;
  62. },
  63. {} as Record<ACTION_TYPE, typeof SCOPE_SEED>,
  64. );
  65. type FlattenObject<T> = {
  66. [K in keyof T]: T[K] extends object
  67. ? (keyof T[K] extends never
  68. ? K
  69. : `${K & string}:${FlattenObject<T[K]> & string}`)
  70. : K
  71. }[keyof T];
  72. type AddAllToScope<S extends string> =
  73. S extends `${infer X}:${infer Y}`
  74. ? `${X}:${typeof ALL_SIGN}` | `${X}:${AddAllToScope<Y>}` | S
  75. : S;
  76. type ScopeOnly = FlattenObject<typeof SCOPE_SEED_WITH_ACTION>;
  77. type ScopeWithAll = AddAllToScope<ScopeOnly>;
  78. export type Scope = ScopeOnly | ScopeWithAll;
  79. // ScopeConstants type definition
  80. type ScopeConstantLeaf = Scope;
  81. type ScopeConstantNode<T> = {
  82. [K in keyof T as Uppercase<string & K>]: T[K] extends object
  83. ? (keyof T[K] extends never
  84. ? ScopeConstantLeaf
  85. : ScopeConstantNode<T[K]> & { ALL: Scope })
  86. : ScopeConstantLeaf
  87. };
  88. type ScopeConstantType = {
  89. [A in keyof typeof SCOPE_SEED_WITH_ACTION as Uppercase<string & A>]:
  90. ScopeConstantNode<typeof SCOPE_SEED> & { ALL: Scope }
  91. };
  92. const buildScopeConstants = (): ScopeConstantType => {
  93. const result = {} as Partial<ScopeConstantType>;
  94. const processObject = (obj: Record<string, any>, path: string[] = [], resultObj: Record<string, any>) => {
  95. Object.entries(obj).forEach(([key, value]) => {
  96. const upperKey = key.toUpperCase();
  97. const currentPath = [...path, key];
  98. const scopePath = currentPath.join(':');
  99. if (value == null) {
  100. return;
  101. }
  102. if (typeof value === 'object' && Object.keys(value).length === 0) {
  103. resultObj[upperKey] = `${scopePath}` as Scope;
  104. }
  105. else if (typeof value === 'object') {
  106. resultObj[upperKey] = {
  107. ALL: `${scopePath}:${ALL_SIGN}` as Scope,
  108. };
  109. processObject(value, currentPath, resultObj[upperKey]);
  110. }
  111. });
  112. };
  113. processObject(SCOPE_SEED_WITH_ACTION, [], result);
  114. return result as ScopeConstantType;
  115. };
  116. export const SCOPE = buildScopeConstants();