scope.ts 3.2 KB

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