@casual-simulation/aux-records 3.4.6-alpha.14601027727 → 3.5.0-alpha.15117651144

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (211) hide show
  1. package/AIController.js +835 -890
  2. package/AIController.js.map +1 -1
  3. package/AIHumeInterface.js +43 -54
  4. package/AIHumeInterface.js.map +1 -1
  5. package/AIOpenAIRealtimeInterface.js +60 -71
  6. package/AIOpenAIRealtimeInterface.js.map +1 -1
  7. package/AnthropicAIChatInterface.js +96 -142
  8. package/AnthropicAIChatInterface.js.map +1 -1
  9. package/AuthController.d.ts +3 -2
  10. package/AuthController.js +1907 -1933
  11. package/AuthController.js.map +1 -1
  12. package/AuthStore.d.ts +1 -10
  13. package/BlockadeLabsGenerateSkyboxInterface.js +57 -72
  14. package/BlockadeLabsGenerateSkyboxInterface.js.map +1 -1
  15. package/CachingConfigStore.js +30 -45
  16. package/CachingConfigStore.js.map +1 -1
  17. package/CachingPolicyStore.d.ts +8 -2
  18. package/CachingPolicyStore.js +108 -135
  19. package/CachingPolicyStore.js.map +1 -1
  20. package/ComIdConfig.d.ts +18 -18
  21. package/ComIdConfig.js.map +1 -1
  22. package/ConsoleAuthMessenger.js +7 -20
  23. package/ConsoleAuthMessenger.js.map +1 -1
  24. package/DataRecordsController.d.ts +2 -2
  25. package/DataRecordsController.js +369 -377
  26. package/DataRecordsController.js.map +1 -1
  27. package/DataRecordsStore.d.ts +1 -1
  28. package/DataRecordsStore.js +1 -1
  29. package/DataRecordsStore.js.map +1 -1
  30. package/EventRecordsController.js +226 -240
  31. package/EventRecordsController.js.map +1 -1
  32. package/FileRecordsController.d.ts +13 -2
  33. package/FileRecordsController.js +458 -450
  34. package/FileRecordsController.js.map +1 -1
  35. package/GoogleAIChatInterface.js +133 -179
  36. package/GoogleAIChatInterface.js.map +1 -1
  37. package/LivekitController.js +43 -54
  38. package/LivekitController.js.map +1 -1
  39. package/LoomController.js +64 -75
  40. package/LoomController.js.map +1 -1
  41. package/MemoryAuthMessenger.js +10 -23
  42. package/MemoryAuthMessenger.js.map +1 -1
  43. package/MemoryCache.js +18 -35
  44. package/MemoryCache.js.map +1 -1
  45. package/MemoryFileRecordsLookup.js +105 -125
  46. package/MemoryFileRecordsLookup.js.map +1 -1
  47. package/MemoryModerationJobProvider.js +17 -30
  48. package/MemoryModerationJobProvider.js.map +1 -1
  49. package/MemoryRateLimiter.js +12 -27
  50. package/MemoryRateLimiter.js.map +1 -1
  51. package/MemoryStore.d.ts +18 -6
  52. package/MemoryStore.js +1879 -1997
  53. package/MemoryStore.js.map +1 -1
  54. package/MetricsStore.d.ts +2 -2
  55. package/ModerationController.js +186 -200
  56. package/ModerationController.js.map +1 -1
  57. package/OpenAIChatInterface.js +105 -135
  58. package/OpenAIChatInterface.js.map +1 -1
  59. package/OpenAIImageInterface.js +57 -51
  60. package/OpenAIImageInterface.js.map +1 -1
  61. package/PolicyController.d.ts +150 -10
  62. package/PolicyController.js +1546 -1299
  63. package/PolicyController.js.map +1 -1
  64. package/PolicyStore.d.ts +110 -2
  65. package/PolicyStore.js +36 -1
  66. package/PolicyStore.js.map +1 -1
  67. package/PrivoClient.js +398 -435
  68. package/PrivoClient.js.map +1 -1
  69. package/RateLimitController.js +25 -36
  70. package/RateLimitController.js.map +1 -1
  71. package/RecordsClient.js +51 -74
  72. package/RecordsClient.js.map +1 -1
  73. package/RecordsController.d.ts +2 -42
  74. package/RecordsController.js +1026 -1182
  75. package/RecordsController.js.map +1 -1
  76. package/RecordsServer.d.ts +196 -27
  77. package/RecordsServer.js +1701 -1343
  78. package/RecordsServer.js.map +1 -1
  79. package/RecordsStore.d.ts +1 -10
  80. package/RecordsStore.js.map +1 -1
  81. package/ServerConfig.d.ts +339 -195
  82. package/ServerConfig.js +13 -0
  83. package/ServerConfig.js.map +1 -1
  84. package/SloydInterface.js +62 -75
  85. package/SloydInterface.js.map +1 -1
  86. package/StabilityAIImageInterface.js +150 -167
  87. package/StabilityAIImageInterface.js.map +1 -1
  88. package/SubscriptionConfigBuilder.d.ts +6 -1
  89. package/SubscriptionConfigBuilder.js +22 -0
  90. package/SubscriptionConfigBuilder.js.map +1 -1
  91. package/SubscriptionConfiguration.d.ts +266 -169
  92. package/SubscriptionConfiguration.js +101 -79
  93. package/SubscriptionConfiguration.js.map +1 -1
  94. package/SubscriptionController.d.ts +2 -1
  95. package/SubscriptionController.js +643 -650
  96. package/SubscriptionController.js.map +1 -1
  97. package/SystemNotificationMessenger.d.ts +21 -4
  98. package/SystemNotificationMessenger.js +36 -30
  99. package/SystemNotificationMessenger.js.map +1 -1
  100. package/TestUtils.d.ts +9 -1
  101. package/TestUtils.js +105 -129
  102. package/TestUtils.js.map +1 -1
  103. package/Utils.d.ts +2 -16
  104. package/Utils.js +21 -22
  105. package/Utils.js.map +1 -1
  106. package/crud/CrudHelpers.js +17 -26
  107. package/crud/CrudHelpers.js.map +1 -1
  108. package/crud/CrudRecordsController.d.ts +1 -1
  109. package/crud/CrudRecordsController.js +259 -267
  110. package/crud/CrudRecordsController.js.map +1 -1
  111. package/crud/CrudRecordsControllerTests.js +174 -185
  112. package/crud/CrudRecordsControllerTests.js.map +1 -1
  113. package/crud/CrudRecordsStore.d.ts +7 -3
  114. package/crud/MemoryCrudRecordsStore.d.ts +4 -4
  115. package/crud/MemoryCrudRecordsStore.js +98 -118
  116. package/crud/MemoryCrudRecordsStore.js.map +1 -1
  117. package/crud/sub/MemorySubCrudRecordsStore.d.ts +24 -0
  118. package/crud/sub/MemorySubCrudRecordsStore.js +146 -0
  119. package/crud/sub/MemorySubCrudRecordsStore.js.map +1 -0
  120. package/crud/sub/SubCrudRecordsController.d.ts +182 -0
  121. package/crud/sub/SubCrudRecordsController.js +360 -0
  122. package/crud/sub/SubCrudRecordsController.js.map +1 -0
  123. package/crud/sub/SubCrudRecordsControllerTests.d.ts +39 -0
  124. package/crud/sub/SubCrudRecordsControllerTests.js +821 -0
  125. package/crud/sub/SubCrudRecordsControllerTests.js.map +1 -0
  126. package/crud/sub/SubCrudRecordsStore.d.ts +95 -0
  127. package/{forms/index.js → crud/sub/SubCrudRecordsStore.js} +2 -2
  128. package/crud/sub/SubCrudRecordsStore.js.map +1 -0
  129. package/crud/sub/index.d.ts +3 -0
  130. package/crud/sub/index.js +20 -0
  131. package/{forms → crud/sub}/index.js.map +1 -1
  132. package/index.d.ts +1 -1
  133. package/index.js +1 -1
  134. package/index.js.map +1 -1
  135. package/notifications/MemoryNotificationRecordsStore.js +189 -198
  136. package/notifications/MemoryNotificationRecordsStore.js.map +1 -1
  137. package/notifications/NotificationRecordsController.js +438 -460
  138. package/notifications/NotificationRecordsController.js.map +1 -1
  139. package/notifications/NotificationRecordsStore.d.ts +2 -1
  140. package/notifications/WebPushInterface.d.ts +0 -1
  141. package/notifications/WebPushInterface.js +0 -1
  142. package/notifications/WebPushInterface.js.map +1 -1
  143. package/package.json +6 -6
  144. package/packages/MemoryPackageRecordsStore.d.ts +10 -0
  145. package/packages/MemoryPackageRecordsStore.js +38 -0
  146. package/packages/MemoryPackageRecordsStore.js.map +1 -0
  147. package/packages/PackageRecordsController.d.ts +26 -0
  148. package/packages/PackageRecordsController.js +49 -0
  149. package/packages/PackageRecordsController.js.map +1 -0
  150. package/packages/PackageRecordsStore.d.ts +32 -0
  151. package/packages/PackageRecordsStore.js +19 -0
  152. package/packages/PackageRecordsStore.js.map +1 -0
  153. package/packages/index.d.ts +4 -0
  154. package/packages/index.js +21 -0
  155. package/packages/index.js.map +1 -0
  156. package/packages/version/MemoryPackageVersionRecordsStore.d.ts +21 -0
  157. package/packages/version/MemoryPackageVersionRecordsStore.js +177 -0
  158. package/packages/version/MemoryPackageVersionRecordsStore.js.map +1 -0
  159. package/packages/version/PackageVersionRecordsController.d.ts +144 -0
  160. package/packages/version/PackageVersionRecordsController.js +656 -0
  161. package/packages/version/PackageVersionRecordsController.js.map +1 -0
  162. package/packages/version/PackageVersionRecordsStore.d.ts +342 -0
  163. package/packages/version/PackageVersionRecordsStore.js +126 -0
  164. package/packages/version/PackageVersionRecordsStore.js.map +1 -0
  165. package/packages/version/index.d.ts +4 -0
  166. package/packages/version/index.js +21 -0
  167. package/packages/version/index.js.map +1 -0
  168. package/tracing/TracingDecorators.js +31 -40
  169. package/tracing/TracingDecorators.js.map +1 -1
  170. package/webhooks/MemoryWebhookRecordsStore.js +56 -72
  171. package/webhooks/MemoryWebhookRecordsStore.js.map +1 -1
  172. package/webhooks/WebhookEnvironment.d.ts +3 -3
  173. package/webhooks/WebhookRecordsController.d.ts +2 -1
  174. package/webhooks/WebhookRecordsController.js +389 -382
  175. package/webhooks/WebhookRecordsController.js.map +1 -1
  176. package/webhooks/WebhookRecordsStore.d.ts +2 -1
  177. package/websockets/InstRecordsStore.d.ts +50 -0
  178. package/websockets/InstRecordsStore.js +17 -0
  179. package/websockets/InstRecordsStore.js.map +1 -1
  180. package/websockets/MemoryTempInstRecordsStore.d.ts +5 -0
  181. package/websockets/MemoryTempInstRecordsStore.js +168 -179
  182. package/websockets/MemoryTempInstRecordsStore.js.map +1 -1
  183. package/websockets/MemoryWebsocketConnectionStore.js +98 -135
  184. package/websockets/MemoryWebsocketConnectionStore.js.map +1 -1
  185. package/websockets/MemoryWebsocketMessenger.js +29 -48
  186. package/websockets/MemoryWebsocketMessenger.js.map +1 -1
  187. package/websockets/SplitInstRecordsStore.d.ts +4 -1
  188. package/websockets/SplitInstRecordsStore.js +167 -185
  189. package/websockets/SplitInstRecordsStore.js.map +1 -1
  190. package/websockets/TemporaryInstRecordsStore.d.ts +19 -1
  191. package/websockets/TemporaryInstRecordsStore.js +17 -0
  192. package/websockets/TemporaryInstRecordsStore.js.map +1 -1
  193. package/websockets/WebsocketController.d.ts +147 -3
  194. package/websockets/WebsocketController.js +1735 -1391
  195. package/websockets/WebsocketController.js.map +1 -1
  196. package/websockets/index.d.ts +0 -1
  197. package/websockets/index.js +0 -1
  198. package/websockets/index.js.map +1 -1
  199. package/AAGUID.d.ts +0 -11
  200. package/AAGUID.js +0 -116
  201. package/AAGUID.js.map +0 -1
  202. package/AuthUtils.d.ts +0 -162
  203. package/AuthUtils.js +0 -327
  204. package/AuthUtils.js.map +0 -1
  205. package/forms/FormError.d.ts +0 -43
  206. package/forms/FormError.js +0 -56
  207. package/forms/FormError.js.map +0 -1
  208. package/forms/index.d.ts +0 -2
  209. package/websockets/Utils.d.ts +0 -33
  210. package/websockets/Utils.js +0 -82
  211. package/websockets/Utils.js.map +0 -1
@@ -4,23 +4,13 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
4
4
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
5
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6
6
  };
7
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
8
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
9
- return new (P || (P = Promise))(function (resolve, reject) {
10
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
11
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
12
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
13
- step((generator = generator.apply(thisArg, _arguments || [])).next());
14
- });
15
- };
16
- import { isRecordKey } from './RecordsController';
17
- import { ADMIN_ROLE_NAME, PUBLIC_READ_MARKER, ACCOUNT_MARKER, PRIVATE_MARKER, } from '@casual-simulation/aux-common';
7
+ import { ADMIN_ROLE_NAME, PUBLIC_READ_MARKER, ACCOUNT_MARKER, PRIVATE_MARKER, isRecordKey, isSuperUserRole, normalizeInstId, parseInstId, } from '@casual-simulation/aux-common';
18
8
  import { getExpireTime, getPublicMarkersPermission } from './PolicyStore';
19
9
  import { sortBy, without } from 'lodash';
20
10
  import { getRootMarker, getRootMarkersOrDefault } from './Utils';
21
- import { normalizeInstId, parseInstId } from './websockets';
22
11
  import { traced } from './tracing/TracingDecorators';
23
12
  import { SpanStatusCode, trace } from '@opentelemetry/api';
13
+ import { v7 as uuidv7 } from 'uuid';
24
14
  const TRACE_NAME = 'PolicyController';
25
15
  /**
26
16
  * The maximum number of instances that can be authorized at once.
@@ -57,6 +47,8 @@ const ALLOWED_STUDIO_MEMBER_RESOURCES = [
57
47
  ],
58
48
  ['loom', ['create']],
59
49
  ['webhook', ['read', 'create', 'delete', 'update', 'list', 'run']],
50
+ ['package', ['read', 'create', 'delete', 'update', 'list']],
51
+ ['package.version', ['read', 'create', 'delete', 'update', 'list', 'run']],
60
52
  ];
61
53
  const ALLOWED_MODERATOR_ACTIONS = new Set([
62
54
  'read',
@@ -149,180 +141,142 @@ export function getMarkerResourcesForUpdate(existingMarkers, newMarkers) {
149
141
  * Defines a class that is able to calculate the policies and permissions that are allowed for specific actions.
150
142
  */
151
143
  export class PolicyController {
152
- constructor(auth, records, policies) {
144
+ constructor(auth, records, policies, insts = null, packageVersions = null) {
153
145
  this._auth = auth;
154
146
  this._records = records;
155
147
  this._policies = policies;
148
+ this._insts = insts;
149
+ this._packageVersions = packageVersions;
156
150
  }
157
151
  /**
158
152
  * Constructs the authorization context that is needed for the given request.
159
153
  * @param request The request that will be authorized.
160
154
  * @returns The authorization context that will be used to evaluate whether the request is authorized.
161
155
  */
162
- constructAuthorizationContext(request) {
156
+ async constructAuthorizationContext(request) {
163
157
  var _a, _b;
164
- return __awaiter(this, void 0, void 0, function* () {
165
- let recordKeyResult = null;
166
- let recordName;
167
- let recordKeyCreatorId;
168
- let ownerId;
169
- let studioId;
170
- let studioMembers = undefined;
171
- const recordKeyProvided = isRecordKey(request.recordKeyOrRecordName);
172
- if (recordKeyProvided) {
173
- recordKeyResult = yield this._records.validatePublicRecordKey(request.recordKeyOrRecordName);
174
- if (recordKeyResult.success === true) {
175
- recordName = recordKeyResult.recordName;
176
- ownerId = recordKeyResult.ownerId;
177
- recordKeyCreatorId = recordKeyResult.keyCreatorId;
178
- }
179
- else {
180
- return {
181
- success: false,
182
- errorCode: recordKeyResult.errorCode,
183
- errorMessage: recordKeyResult.errorMessage,
184
- };
185
- }
158
+ let recordKeyResult = null;
159
+ let recordName;
160
+ let recordKeyCreatorId;
161
+ let ownerId;
162
+ let studioId;
163
+ let studioMembers = undefined;
164
+ const recordKeyProvided = isRecordKey(request.recordKeyOrRecordName);
165
+ if (recordKeyProvided) {
166
+ recordKeyResult = await this._records.validatePublicRecordKey(request.recordKeyOrRecordName);
167
+ if (recordKeyResult.success === true) {
168
+ recordName = recordKeyResult.recordName;
169
+ ownerId = recordKeyResult.ownerId;
170
+ recordKeyCreatorId = recordKeyResult.keyCreatorId;
186
171
  }
187
172
  else {
188
- const result = yield this._records.validateRecordName(request.recordKeyOrRecordName, request.userId);
189
- if (result.success === false) {
190
- return {
191
- success: false,
192
- errorCode: result.errorCode,
193
- errorMessage: result.errorMessage,
194
- };
195
- }
196
- recordName = result.recordName;
197
- ownerId = result.ownerId;
198
- studioId = result.studioId;
199
- studioMembers = result.studioMembers;
200
- }
201
- const subjectPolicy = !!recordKeyResult && recordKeyResult.success
202
- ? recordKeyResult.policy
203
- : 'subjectfull';
204
- let recordOwnerPrivacyFeatures = null;
205
- let userPrivacyFeatures = null;
206
- if (ownerId) {
207
- recordOwnerPrivacyFeatures =
208
- yield this._policies.getUserPrivacyFeatures(ownerId);
209
- }
210
- if (!recordOwnerPrivacyFeatures) {
211
- // The record owner will most likely have privacy features,
212
- // but this is just a sanity check in case they dont.
213
- if (this._auth.privoEnabled) {
214
- recordOwnerPrivacyFeatures = {
215
- allowAI: false,
216
- allowPublicData: false,
217
- allowPublicInsts: false,
218
- publishData: false,
219
- };
220
- }
221
- else {
222
- recordOwnerPrivacyFeatures = {
223
- allowAI: true,
224
- allowPublicData: true,
225
- allowPublicInsts: true,
226
- publishData: true,
227
- };
228
- }
229
- }
230
- if (request.userId) {
231
- userPrivacyFeatures = yield this._policies.getUserPrivacyFeatures(request.userId);
232
- }
233
- if (!userPrivacyFeatures) {
234
- if (this._auth.privoEnabled) {
235
- userPrivacyFeatures = {
236
- allowAI: false,
237
- allowPublicData: false,
238
- allowPublicInsts: false,
239
- publishData: false,
240
- };
241
- }
242
- else {
243
- userPrivacyFeatures = {
244
- allowAI: true,
245
- allowPublicData: true,
246
- allowPublicInsts: true,
247
- publishData: true,
248
- };
249
- }
173
+ return {
174
+ success: false,
175
+ errorCode: recordKeyResult.errorCode,
176
+ errorMessage: recordKeyResult.errorMessage,
177
+ };
250
178
  }
251
- const context = {
252
- recordName,
253
- recordKeyResult,
254
- subjectPolicy,
255
- recordKeyProvided,
256
- recordKeyCreatorId,
257
- recordOwnerId: ownerId,
258
- recordOwnerPrivacyFeatures,
259
- recordStudioId: studioId,
260
- recordStudioMembers: studioMembers,
261
- userId: request.userId,
262
- userRole: (_a = userPrivacyFeatures === null || userPrivacyFeatures === void 0 ? void 0 : userPrivacyFeatures.userRole) !== null && _a !== void 0 ? _a : 'none',
263
- userPrivacyFeatures,
264
- sendNotLoggedIn: (_b = request.sendNotLoggedIn) !== null && _b !== void 0 ? _b : true,
265
- };
266
- return {
267
- success: true,
268
- context,
269
- };
270
- });
271
- }
272
- /**
273
- * Attempts to authorize the given user and instances for the action and resource(s).
274
- * @param context The authorization context for the request.
275
- * @param request The request.
276
- */
277
- authorizeUserAndInstances(context, request) {
278
- var _a;
279
- return __awaiter(this, void 0, void 0, function* () {
280
- try {
281
- const authorization = yield this.authorizeSubjects(context, {
282
- action: request.action,
283
- markers: request.markers,
284
- resourceKind: request.resourceKind,
285
- resourceId: request.resourceId,
286
- subjects: [
287
- {
288
- subjectType: 'user',
289
- subjectId: request.userId,
290
- },
291
- ...((_a = request.instances) !== null && _a !== void 0 ? _a : []).map((i) => ({
292
- subjectType: 'inst',
293
- subjectId: i,
294
- })),
295
- ],
296
- });
297
- if (authorization.success === false) {
298
- return authorization;
299
- }
300
- const userResult = authorization.results.find((r) => r.subjectType === 'user' && r.subjectId === request.userId);
301
- return Object.assign(Object.assign({}, authorization), { user: userResult });
302
- }
303
- catch (err) {
304
- const span = trace.getActiveSpan();
305
- span === null || span === void 0 ? void 0 : span.recordException(err);
306
- span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
307
- console.error('[PolicyController] A server error occurred while authorizing user and instances.', err);
179
+ }
180
+ else {
181
+ const result = await this._records.validateRecordName(request.recordKeyOrRecordName, request.userId);
182
+ if (result.success === false) {
308
183
  return {
309
184
  success: false,
310
- errorCode: 'server_error',
311
- errorMessage: 'A server error occurred.',
185
+ errorCode: result.errorCode,
186
+ errorMessage: result.errorMessage,
312
187
  };
313
188
  }
314
- });
189
+ recordName = result.recordName;
190
+ ownerId = result.ownerId;
191
+ studioId = result.studioId;
192
+ studioMembers = result.studioMembers;
193
+ }
194
+ const subjectPolicy = !!recordKeyResult && recordKeyResult.success
195
+ ? recordKeyResult.policy
196
+ : 'subjectfull';
197
+ let recordOwnerPrivacyFeatures = null;
198
+ let userPrivacyFeatures = null;
199
+ if (ownerId) {
200
+ recordOwnerPrivacyFeatures =
201
+ await this._policies.getUserPrivacyFeatures(ownerId);
202
+ }
203
+ if (!recordOwnerPrivacyFeatures) {
204
+ // The record owner will most likely have privacy features,
205
+ // but this is just a sanity check in case they dont.
206
+ if (this._auth.privoEnabled) {
207
+ recordOwnerPrivacyFeatures = {
208
+ allowAI: false,
209
+ allowPublicData: false,
210
+ allowPublicInsts: false,
211
+ publishData: false,
212
+ };
213
+ }
214
+ else {
215
+ recordOwnerPrivacyFeatures = {
216
+ allowAI: true,
217
+ allowPublicData: true,
218
+ allowPublicInsts: true,
219
+ publishData: true,
220
+ };
221
+ }
222
+ }
223
+ if (request.userId) {
224
+ userPrivacyFeatures = await this._policies.getUserPrivacyFeatures(request.userId);
225
+ }
226
+ if (!userPrivacyFeatures) {
227
+ if (this._auth.privoEnabled) {
228
+ userPrivacyFeatures = {
229
+ allowAI: false,
230
+ allowPublicData: false,
231
+ allowPublicInsts: false,
232
+ publishData: false,
233
+ };
234
+ }
235
+ else {
236
+ userPrivacyFeatures = {
237
+ allowAI: true,
238
+ allowPublicData: true,
239
+ allowPublicInsts: true,
240
+ publishData: true,
241
+ };
242
+ }
243
+ }
244
+ const context = {
245
+ recordName,
246
+ recordKeyResult,
247
+ subjectPolicy,
248
+ recordKeyProvided,
249
+ recordKeyCreatorId,
250
+ recordOwnerId: ownerId,
251
+ recordOwnerPrivacyFeatures,
252
+ recordStudioId: studioId,
253
+ recordStudioMembers: studioMembers,
254
+ userId: request.userId,
255
+ userRole: (_a = (request.userId
256
+ ? userPrivacyFeatures === null || userPrivacyFeatures === void 0 ? void 0 : userPrivacyFeatures.userRole
257
+ : request.userRole)) !== null && _a !== void 0 ? _a : 'none',
258
+ userPrivacyFeatures,
259
+ sendNotLoggedIn: (_b = request.sendNotLoggedIn) !== null && _b !== void 0 ? _b : true,
260
+ };
261
+ return {
262
+ success: true,
263
+ context,
264
+ };
315
265
  }
316
266
  /**
317
- * Attempts to authorize the given user and instances for the given resources.
267
+ * Attempts to authorize the given user and instances for the action and resource(s).
318
268
  * @param context The authorization context for the request.
319
269
  * @param request The request.
320
270
  */
321
- authorizeUserAndInstancesForResources(context, request) {
271
+ async authorizeUserAndInstances(context, request) {
322
272
  var _a;
323
- return __awaiter(this, void 0, void 0, function* () {
324
- try {
325
- const subjects = [
273
+ try {
274
+ const authorization = await this.authorizeSubjects(context, {
275
+ action: request.action,
276
+ markers: request.markers,
277
+ resourceKind: request.resourceKind,
278
+ resourceId: request.resourceId,
279
+ subjects: [
326
280
  {
327
281
  subjectType: 'user',
328
282
  subjectId: request.userId,
@@ -331,164 +285,211 @@ export class PolicyController {
331
285
  subjectType: 'inst',
332
286
  subjectId: i,
333
287
  })),
334
- ];
335
- const subjectPermission = new Map();
336
- const results = [];
337
- const recordName = context.recordName;
338
- for (let resource of request.resources) {
339
- let subjectsToAuthorize = [];
340
- let authorizations = [];
341
- for (let subject of subjects) {
342
- const subjectKey = `${subject.subjectType}.${subject.subjectId}`;
343
- const authorizedSubject = subjectPermission.get(subjectKey);
344
- if (authorizedSubject) {
345
- const permission = authorizedSubject.permission;
346
- const isCorrectResourceKind = permission.resourceKind === null ||
347
- permission.resourceKind === resource.resourceKind;
348
- const isCorrectAction = permission.action === null ||
349
- permission.action === resource.action;
350
- const isCorrectMarker = !('marker' in permission) ||
351
- resource.markers.includes(permission.marker);
352
- const isCorrectResource = !('resourceId' in permission) ||
353
- permission.resourceId === null ||
354
- permission.resourceId === resource.resourceId;
355
- if (isCorrectResourceKind &&
356
- isCorrectAction &&
357
- isCorrectMarker &&
358
- isCorrectResource) {
359
- // Record the authorization
360
- authorizations.push(authorizedSubject);
361
- }
362
- else {
363
- subjectsToAuthorize.push(subject);
364
- }
288
+ ],
289
+ });
290
+ if (authorization.success === false) {
291
+ return authorization;
292
+ }
293
+ const userResult = authorization.results.find((r) => r.subjectType === 'user' && r.subjectId === request.userId);
294
+ return {
295
+ ...authorization,
296
+ user: userResult,
297
+ };
298
+ }
299
+ catch (err) {
300
+ const span = trace.getActiveSpan();
301
+ span === null || span === void 0 ? void 0 : span.recordException(err);
302
+ span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
303
+ console.error('[PolicyController] A server error occurred while authorizing user and instances.', err);
304
+ return {
305
+ success: false,
306
+ errorCode: 'server_error',
307
+ errorMessage: 'A server error occurred.',
308
+ };
309
+ }
310
+ }
311
+ /**
312
+ * Attempts to authorize the given user and instances for the given resources.
313
+ * @param context The authorization context for the request.
314
+ * @param request The request.
315
+ */
316
+ async authorizeUserAndInstancesForResources(context, request) {
317
+ var _a;
318
+ try {
319
+ const subjects = [
320
+ {
321
+ subjectType: 'user',
322
+ subjectId: request.userId,
323
+ },
324
+ ...((_a = request.instances) !== null && _a !== void 0 ? _a : []).map((i) => ({
325
+ subjectType: 'inst',
326
+ subjectId: i,
327
+ })),
328
+ ];
329
+ const subjectPermission = new Map();
330
+ const results = [];
331
+ const recordName = context.recordName;
332
+ for (let resource of request.resources) {
333
+ let subjectsToAuthorize = [];
334
+ let authorizations = [];
335
+ for (let subject of subjects) {
336
+ const subjectKey = `${subject.subjectType}.${subject.subjectId}`;
337
+ const authorizedSubject = subjectPermission.get(subjectKey);
338
+ if (authorizedSubject) {
339
+ const permission = authorizedSubject.permission;
340
+ const isCorrectResourceKind = permission.resourceKind === null ||
341
+ permission.resourceKind === resource.resourceKind;
342
+ const isCorrectAction = permission.action === null ||
343
+ permission.action === resource.action;
344
+ const isCorrectMarker = !('marker' in permission) ||
345
+ resource.markers.includes(permission.marker);
346
+ const isCorrectResource = !('resourceId' in permission) ||
347
+ permission.resourceId === null ||
348
+ permission.resourceId === resource.resourceId;
349
+ if (isCorrectResourceKind &&
350
+ isCorrectAction &&
351
+ isCorrectMarker &&
352
+ isCorrectResource) {
353
+ // Record the authorization
354
+ authorizations.push(authorizedSubject);
365
355
  }
366
356
  else {
367
357
  subjectsToAuthorize.push(subject);
368
358
  }
369
359
  }
370
- if (subjectsToAuthorize.length > 0) {
371
- const result = yield this.authorizeSubjects(context, {
372
- action: resource.action,
373
- markers: resource.markers,
374
- resourceKind: resource.resourceKind,
375
- resourceId: resource.resourceId,
376
- subjects: subjectsToAuthorize,
377
- });
378
- if (result.success === false) {
379
- return result;
360
+ else {
361
+ subjectsToAuthorize.push(subject);
362
+ }
363
+ }
364
+ if (subjectsToAuthorize.length > 0) {
365
+ const result = await this.authorizeSubjects(context, {
366
+ action: resource.action,
367
+ markers: resource.markers,
368
+ resourceKind: resource.resourceKind,
369
+ resourceId: resource.resourceId,
370
+ subjects: subjectsToAuthorize,
371
+ });
372
+ if (result.success === false) {
373
+ return result;
374
+ }
375
+ for (let authorization of result.results) {
376
+ const subjectKey = `${authorization.subjectType}.${authorization.subjectId}`;
377
+ authorizations.push(authorization);
378
+ const permission = authorization.permission;
379
+ const existingAuthorization = subjectPermission.get(subjectKey);
380
+ if (!existingAuthorization) {
381
+ subjectPermission.set(subjectKey, authorization);
380
382
  }
381
- for (let authorization of result.results) {
382
- const subjectKey = `${authorization.subjectType}.${authorization.subjectId}`;
383
- authorizations.push(authorization);
384
- const permission = authorization.permission;
385
- const existingAuthorization = subjectPermission.get(subjectKey);
386
- if (!existingAuthorization) {
383
+ else {
384
+ const existingPermission = existingAuthorization.permission;
385
+ const isResourceKindMoreGeneral = permission.resourceKind === null &&
386
+ existingPermission.resourceKind !== null;
387
+ const isActionMoreGeneral = permission.action === null &&
388
+ existingPermission.action !== null;
389
+ const isMarkerMoreGeneral = 'marker' in permission &&
390
+ 'marker' in existingPermission &&
391
+ permission.marker === null &&
392
+ existingPermission.marker !== null;
393
+ const isResourceMoreGeneral = 'resourceId' in permission &&
394
+ 'resourceId' in existingPermission &&
395
+ permission.resourceId === null &&
396
+ existingPermission.resourceId !== null;
397
+ if (isResourceKindMoreGeneral ||
398
+ isActionMoreGeneral ||
399
+ isMarkerMoreGeneral ||
400
+ isResourceMoreGeneral) {
387
401
  subjectPermission.set(subjectKey, authorization);
388
402
  }
389
- else {
390
- const existingPermission = existingAuthorization.permission;
391
- const isResourceKindMoreGeneral = permission.resourceKind === null &&
392
- existingPermission.resourceKind !== null;
393
- const isActionMoreGeneral = permission.action === null &&
394
- existingPermission.action !== null;
395
- const isMarkerMoreGeneral = 'marker' in permission &&
396
- 'marker' in existingPermission &&
397
- permission.marker === null &&
398
- existingPermission.marker !== null;
399
- const isResourceMoreGeneral = 'resourceId' in permission &&
400
- 'resourceId' in existingPermission &&
401
- permission.resourceId === null &&
402
- existingPermission.resourceId !== null;
403
- if (isResourceKindMoreGeneral ||
404
- isActionMoreGeneral ||
405
- isMarkerMoreGeneral ||
406
- isResourceMoreGeneral) {
407
- subjectPermission.set(subjectKey, authorization);
408
- }
409
- }
410
403
  }
411
404
  }
412
- if (authorizations.length !== subjects.length) {
413
- console.error('[PolicyController] [authorizeUserAndInstancesForResources] The number of authorizations does not match the number of subjects!');
414
- return {
415
- success: false,
416
- errorCode: 'server_error',
417
- errorMessage: 'A server error occurred.',
418
- };
419
- }
420
- results.push({
421
- success: true,
422
- recordName: recordName,
423
- resourceKind: resource.resourceKind,
424
- resourceId: resource.resourceId,
425
- action: resource.action,
426
- markers: resource.markers,
427
- results: authorizations,
428
- user: authorizations.find((r) => r.subjectType === 'user' &&
429
- r.subjectId === request.userId),
430
- });
431
405
  }
432
- return {
406
+ if (authorizations.length !== subjects.length) {
407
+ console.error('[PolicyController] [authorizeUserAndInstancesForResources] The number of authorizations does not match the number of subjects!');
408
+ return {
409
+ success: false,
410
+ errorCode: 'server_error',
411
+ errorMessage: 'A server error occurred.',
412
+ };
413
+ }
414
+ results.push({
433
415
  success: true,
434
416
  recordName: recordName,
435
- results,
436
- };
437
- }
438
- catch (err) {
439
- const span = trace.getActiveSpan();
440
- span === null || span === void 0 ? void 0 : span.recordException(err);
441
- span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
442
- console.error('[PolicyController] A server error occurred while authorizing user and instances for resources.', err);
443
- return {
444
- success: false,
445
- errorCode: 'server_error',
446
- errorMessage: 'A server error occurred.',
447
- };
417
+ resourceKind: resource.resourceKind,
418
+ resourceId: resource.resourceId,
419
+ action: resource.action,
420
+ markers: resource.markers,
421
+ results: authorizations,
422
+ user: authorizations.find((r) => r.subjectType === 'user' &&
423
+ r.subjectId === request.userId),
424
+ });
448
425
  }
449
- });
426
+ return {
427
+ success: true,
428
+ recordName: recordName,
429
+ results,
430
+ };
431
+ }
432
+ catch (err) {
433
+ const span = trace.getActiveSpan();
434
+ span === null || span === void 0 ? void 0 : span.recordException(err);
435
+ span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
436
+ console.error('[PolicyController] A server error occurred while authorizing user and instances for resources.', err);
437
+ return {
438
+ success: false,
439
+ errorCode: 'server_error',
440
+ errorMessage: 'A server error occurred.',
441
+ };
442
+ }
450
443
  }
451
444
  /**
452
445
  * Attempts to authorize the given subjects for the action and resource(s).
453
446
  * @param context The authorization context for the request.
454
447
  * @param request The request.
455
448
  */
456
- authorizeSubjects(context, request) {
457
- return __awaiter(this, void 0, void 0, function* () {
458
- try {
459
- if (request.subjects.length <= 0) {
460
- return {
461
- success: false,
462
- errorCode: 'unacceptable_request',
463
- errorMessage: 'You must provide at least one subject to authorize.',
464
- };
465
- }
466
- const results = [];
467
- for (let subject of request.subjects) {
468
- const subjectResult = yield this.authorizeSubjectUsingContext(context, Object.assign(Object.assign({}, subject), { action: request.action, resourceKind: request.resourceKind, resourceId: request.resourceId, markers: request.markers }));
469
- if (subjectResult.success === false) {
470
- return subjectResult;
471
- }
472
- results.push(Object.assign(Object.assign({}, subjectResult), { subjectType: subject.subjectType, subjectId: subject.subjectId }));
473
- }
474
- return {
475
- success: true,
476
- recordName: context.recordName,
477
- results: results,
478
- };
479
- }
480
- catch (err) {
481
- const span = trace.getActiveSpan();
482
- span === null || span === void 0 ? void 0 : span.recordException(err);
483
- span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
484
- console.error('[PolicyController] A server error occurred while authorizing subjects.', err);
449
+ async authorizeSubjects(context, request) {
450
+ try {
451
+ if (request.subjects.length <= 0) {
485
452
  return {
486
453
  success: false,
487
- errorCode: 'server_error',
488
- errorMessage: 'A server error occurred.',
454
+ errorCode: 'unacceptable_request',
455
+ errorMessage: 'You must provide at least one subject to authorize.',
489
456
  };
490
457
  }
491
- });
458
+ const results = [];
459
+ for (let subject of request.subjects) {
460
+ const subjectResult = await this.authorizeSubjectUsingContext(context, {
461
+ ...subject,
462
+ action: request.action,
463
+ resourceKind: request.resourceKind,
464
+ resourceId: request.resourceId,
465
+ markers: request.markers,
466
+ });
467
+ if (subjectResult.success === false) {
468
+ return subjectResult;
469
+ }
470
+ results.push({
471
+ ...subjectResult,
472
+ subjectType: subject.subjectType,
473
+ subjectId: subject.subjectId,
474
+ });
475
+ }
476
+ return {
477
+ success: true,
478
+ recordName: context.recordName,
479
+ results: results,
480
+ };
481
+ }
482
+ catch (err) {
483
+ const span = trace.getActiveSpan();
484
+ span === null || span === void 0 ? void 0 : span.recordException(err);
485
+ span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
486
+ console.error('[PolicyController] A server error occurred while authorizing subjects.', err);
487
+ return {
488
+ success: false,
489
+ errorCode: 'server_error',
490
+ errorMessage: 'A server error occurred.',
491
+ };
492
+ }
492
493
  }
493
494
  /**
494
495
  * Attempts to authorize the given subject for the action and resource(s).
@@ -496,26 +497,24 @@ export class PolicyController {
496
497
  * @param context The context for the request.
497
498
  * @param request The request to authorize.
498
499
  */
499
- authorizeSubject(context, request) {
500
- return __awaiter(this, void 0, void 0, function* () {
501
- try {
502
- if (context.success === false) {
503
- return context;
504
- }
505
- return yield this.authorizeSubjectUsingContext(context.context, request);
506
- }
507
- catch (err) {
508
- const span = trace.getActiveSpan();
509
- span === null || span === void 0 ? void 0 : span.recordException(err);
510
- span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
511
- console.error('[PolicyController] A server error occurred while authorizing a subject.', err);
512
- return {
513
- success: false,
514
- errorCode: 'server_error',
515
- errorMessage: 'A server error occurred.',
516
- };
500
+ async authorizeSubject(context, request) {
501
+ try {
502
+ if (context.success === false) {
503
+ return context;
517
504
  }
518
- });
505
+ return await this.authorizeSubjectUsingContext(context.context, request);
506
+ }
507
+ catch (err) {
508
+ const span = trace.getActiveSpan();
509
+ span === null || span === void 0 ? void 0 : span.recordException(err);
510
+ span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
511
+ console.error('[PolicyController] A server error occurred while authorizing a subject.', err);
512
+ return {
513
+ success: false,
514
+ errorCode: 'server_error',
515
+ errorMessage: 'A server error occurred.',
516
+ };
517
+ }
519
518
  }
520
519
  /**
521
520
  * Attempts to authorize the given subject for the action and resource(s).
@@ -523,17 +522,15 @@ export class PolicyController {
523
522
  * @param context The context for the request.
524
523
  * @param request The request to authorize.
525
524
  */
526
- authorizeSubjectUsingContext(context, request) {
527
- return __awaiter(this, void 0, void 0, function* () {
528
- const result = yield this._authorizeSubjectUsingContext(context, request);
529
- if (result.success) {
530
- console.log(`[PolicyController] [action: ${request.resourceKind}.${request.action} resourceId: ${request.resourceId} recordName: ${context.recordName}, ${request.subjectType}: ${request.subjectId}, userId: ${context.userId}] Request authorized.`);
531
- }
532
- else {
533
- console.log(`[PolicyController] [action: ${request.resourceKind}.${request.action} resourceId: ${request.resourceId} recordName: ${context.recordName}, ${request.subjectType}: ${request.subjectId}, userId: ${context.userId}] Request denied:`, result);
534
- }
535
- return result;
536
- });
525
+ async authorizeSubjectUsingContext(context, request) {
526
+ const result = await this._authorizeSubjectUsingContext(context, request);
527
+ if (result.success) {
528
+ console.log(`[PolicyController] [action: ${request.resourceKind}.${request.action} resourceId: ${request.resourceId} recordName: ${context.recordName}, ${request.subjectType}: ${request.subjectId}, userId: ${context.userId}] Request authorized: ${result.explanation}`);
529
+ }
530
+ else {
531
+ console.log(`[PolicyController] [action: ${request.resourceKind}.${request.action} resourceId: ${request.resourceId} recordName: ${context.recordName}, ${request.subjectType}: ${request.subjectId}, userId: ${context.userId}] Request denied:`, result);
532
+ }
533
+ return result;
537
534
  }
538
535
  /**
539
536
  * Attempts to authorize the given subject for the action and resource(s).
@@ -541,21 +538,143 @@ export class PolicyController {
541
538
  * @param context The context for the request.
542
539
  * @param request The request to authorize.
543
540
  */
544
- _authorizeSubjectUsingContext(context, request) {
545
- return __awaiter(this, void 0, void 0, function* () {
546
- try {
547
- const markers = getRootMarkersOrDefault(request.markers);
548
- if (request.action === 'list' && markers.length > 1) {
541
+ async _authorizeSubjectUsingContext(context, request) {
542
+ var _a, _b, _c;
543
+ try {
544
+ const markers = getRootMarkersOrDefault(request.markers);
545
+ let recommendedEntitlement = undefined;
546
+ if (request.action === 'list' && markers.length > 1) {
547
+ return {
548
+ success: false,
549
+ errorCode: 'not_authorized',
550
+ errorMessage: `The "${request.action}" action cannot be used with multiple markers.`,
551
+ reason: {
552
+ type: 'too_many_markers',
553
+ },
554
+ recommendedEntitlement,
555
+ };
556
+ }
557
+ if (!context.userPrivacyFeatures.publishData) {
558
+ return {
559
+ success: false,
560
+ errorCode: 'not_authorized',
561
+ errorMessage: 'You are not authorized to perform this action.',
562
+ reason: {
563
+ type: 'disabled_privacy_feature',
564
+ recordName: context.recordName,
565
+ subjectType: 'user',
566
+ subjectId: context.userId,
567
+ resourceKind: request.resourceKind,
568
+ action: request.action,
569
+ resourceId: request.resourceId,
570
+ privacyFeature: 'publishData',
571
+ },
572
+ recommendedEntitlement,
573
+ };
574
+ }
575
+ const recordName = context.recordName;
576
+ const subjectType = request.subjectType;
577
+ let subjectId = request.subjectId;
578
+ if (subjectType === 'inst') {
579
+ subjectId = normalizeInstId(subjectId);
580
+ }
581
+ if (context.userRole === 'superUser' &&
582
+ request.subjectType !== 'inst') {
583
+ // super users are allowed to do anything for any user
584
+ // insts need to be authorized separately so that a malicious inst can't just do anything
585
+ // if a super user happens to visit it
586
+ return {
587
+ success: true,
588
+ recordName: recordName,
589
+ permission: {
590
+ id: null,
591
+ recordName: recordName,
592
+ userId: null,
593
+ // Record owners are treated as if they are admins in the record
594
+ subjectType: 'role',
595
+ subjectId: ADMIN_ROLE_NAME,
596
+ // Admins get all access to all resources in a record
597
+ resourceKind: null,
598
+ action: null,
599
+ marker: markers[0],
600
+ options: {},
601
+ expireTimeMs: null,
602
+ },
603
+ explanation: `User is a superUser.`,
604
+ };
605
+ }
606
+ else if (context.userRole === 'system') {
607
+ return {
608
+ success: true,
609
+ recordName: recordName,
610
+ permission: {
611
+ id: null,
612
+ recordName: recordName,
613
+ userId: null,
614
+ // Record owners are treated as if they are admins in the record
615
+ subjectType: 'role',
616
+ subjectId: ADMIN_ROLE_NAME,
617
+ // Admins get all access to all resources in a record
618
+ resourceKind: null,
619
+ action: null,
620
+ marker: markers[0],
621
+ options: {},
622
+ expireTimeMs: null,
623
+ },
624
+ explanation: `The system is requesting the action.`,
625
+ };
626
+ }
627
+ else if (context.userRole === 'moderator' &&
628
+ request.subjectType !== 'inst') {
629
+ // moderators are allowed to read anything for any user
630
+ // insts need to be authorized separately so that a malicious inst can't just read everything
631
+ // if a moderator happens to visit it
632
+ if (isAllowedModeratorResource(request.resourceKind, request.action)) {
633
+ return {
634
+ success: true,
635
+ recordName: recordName,
636
+ permission: {
637
+ id: null,
638
+ recordName: recordName,
639
+ userId: null,
640
+ // Record owners are treated as if they are admins in the record
641
+ subjectType: 'role',
642
+ subjectId: ADMIN_ROLE_NAME,
643
+ // Admins get all access to all resources in a record
644
+ resourceKind: null,
645
+ action: request.action,
646
+ marker: markers[0],
647
+ options: {},
648
+ expireTimeMs: null,
649
+ },
650
+ explanation: `User is a moderator.`,
651
+ };
652
+ }
653
+ }
654
+ const publicPermission = getPublicMarkersPermission(markers, request.resourceKind, request.action);
655
+ if (context.recordOwnerId &&
656
+ context.userId !== context.recordOwnerId) {
657
+ if (!context.recordOwnerPrivacyFeatures.allowPublicData) {
549
658
  return {
550
659
  success: false,
551
660
  errorCode: 'not_authorized',
552
- errorMessage: `The "${request.action}" action cannot be used with multiple markers.`,
661
+ errorMessage: 'You are not authorized to perform this action.',
553
662
  reason: {
554
- type: 'too_many_markers',
663
+ type: 'disabled_privacy_feature',
664
+ recordName: context.recordName,
665
+ subjectType: 'user',
666
+ subjectId: context.userId,
667
+ resourceKind: request.resourceKind,
668
+ action: request.action,
669
+ resourceId: request.resourceId,
670
+ privacyFeature: 'allowPublicData',
555
671
  },
672
+ recommendedEntitlement,
556
673
  };
557
674
  }
558
- if (!context.userPrivacyFeatures.publishData) {
675
+ if (request.resourceKind === 'inst' &&
676
+ (!context.recordOwnerPrivacyFeatures.allowPublicInsts ||
677
+ !context.userPrivacyFeatures.allowPublicInsts)) {
559
678
  return {
560
679
  success: false,
561
680
  errorCode: 'not_authorized',
@@ -568,139 +687,107 @@ export class PolicyController {
568
687
  resourceKind: request.resourceKind,
569
688
  action: request.action,
570
689
  resourceId: request.resourceId,
571
- privacyFeature: 'publishData',
690
+ privacyFeature: 'allowPublicInsts',
572
691
  },
692
+ recommendedEntitlement,
573
693
  };
574
694
  }
575
- const recordName = context.recordName;
576
- if (context.userRole === 'superUser') {
695
+ }
696
+ if (publicPermission) {
697
+ if (!context.userPrivacyFeatures.allowPublicData) {
577
698
  return {
578
- success: true,
699
+ success: false,
700
+ errorCode: 'not_authorized',
701
+ errorMessage: 'You are not authorized to perform this action.',
702
+ reason: {
703
+ type: 'disabled_privacy_feature',
704
+ recordName: context.recordName,
705
+ subjectType: 'user',
706
+ subjectId: context.userId,
707
+ resourceKind: request.resourceKind,
708
+ action: request.action,
709
+ resourceId: request.resourceId,
710
+ privacyFeature: 'allowPublicData',
711
+ },
712
+ recommendedEntitlement,
713
+ };
714
+ }
715
+ return {
716
+ success: true,
717
+ recordName,
718
+ permission: {
719
+ id: null,
579
720
  recordName: recordName,
580
- permission: {
581
- id: null,
582
- recordName: recordName,
583
- userId: null,
584
- // Record owners are treated as if they are admins in the record
585
- subjectType: 'role',
586
- subjectId: ADMIN_ROLE_NAME,
587
- // Admins get all access to all resources in a record
588
- resourceKind: null,
589
- action: null,
590
- marker: markers[0],
591
- options: {},
592
- expireTimeMs: null,
593
- },
594
- explanation: `User is a superUser.`,
595
- };
596
- }
597
- else if (context.userRole === 'moderator') {
598
- if (isAllowedModeratorResource(request.resourceKind, request.action)) {
599
- return {
600
- success: true,
601
- recordName: recordName,
602
- permission: {
603
- id: null,
604
- recordName: recordName,
605
- userId: null,
606
- // Record owners are treated as if they are admins in the record
607
- subjectType: 'role',
608
- subjectId: ADMIN_ROLE_NAME,
609
- // Admins get all access to all resources in a record
610
- resourceKind: null,
611
- action: request.action,
612
- marker: markers[0],
613
- options: {},
614
- expireTimeMs: null,
615
- },
616
- explanation: `User is a moderator.`,
617
- };
618
- }
619
- }
620
- const subjectType = request.subjectType;
621
- let subjectId = request.subjectId;
622
- if (subjectType === 'inst') {
623
- subjectId = normalizeInstId(subjectId);
624
- }
625
- const publicPermission = getPublicMarkersPermission(markers, request.resourceKind, request.action);
626
- if (context.recordOwnerId &&
627
- context.userId !== context.recordOwnerId) {
628
- if (!context.recordOwnerPrivacyFeatures.allowPublicData) {
629
- return {
630
- success: false,
631
- errorCode: 'not_authorized',
632
- errorMessage: 'You are not authorized to perform this action.',
633
- reason: {
634
- type: 'disabled_privacy_feature',
635
- recordName: context.recordName,
636
- subjectType: 'user',
637
- subjectId: context.userId,
638
- resourceKind: request.resourceKind,
639
- action: request.action,
640
- resourceId: request.resourceId,
641
- privacyFeature: 'allowPublicData',
642
- },
643
- };
644
- }
645
- if (request.resourceKind === 'inst' &&
646
- (!context.recordOwnerPrivacyFeatures.allowPublicInsts ||
647
- !context.userPrivacyFeatures.allowPublicInsts)) {
648
- return {
649
- success: false,
650
- errorCode: 'not_authorized',
651
- errorMessage: 'You are not authorized to perform this action.',
652
- reason: {
653
- type: 'disabled_privacy_feature',
654
- recordName: context.recordName,
655
- subjectType: 'user',
656
- subjectId: context.userId,
657
- resourceKind: request.resourceKind,
658
- action: request.action,
659
- resourceId: request.resourceId,
660
- privacyFeature: 'allowPublicInsts',
661
- },
662
- };
663
- }
664
- }
665
- if (publicPermission) {
666
- if (!context.userPrivacyFeatures.allowPublicData) {
667
- return {
668
- success: false,
669
- errorCode: 'not_authorized',
670
- errorMessage: 'You are not authorized to perform this action.',
671
- reason: {
672
- type: 'disabled_privacy_feature',
673
- recordName: context.recordName,
674
- subjectType: 'user',
675
- subjectId: context.userId,
676
- resourceKind: request.resourceKind,
677
- action: request.action,
678
- resourceId: request.resourceId,
679
- privacyFeature: 'allowPublicData',
680
- },
681
- };
682
- }
721
+ userId: null,
722
+ subjectType: subjectType,
723
+ subjectId: subjectId,
724
+ resourceKind: publicPermission.resourceKind,
725
+ action: publicPermission.action,
726
+ marker: publicPermission.marker,
727
+ options: {},
728
+ expireTimeMs: null,
729
+ },
730
+ explanation: publicPermission.marker === PUBLIC_READ_MARKER
731
+ ? 'Resource has the publicRead marker.'
732
+ : 'Resource has the publicWrite marker.',
733
+ };
734
+ }
735
+ if (subjectType === 'role' && subjectId === ADMIN_ROLE_NAME) {
736
+ return {
737
+ success: true,
738
+ recordName: recordName,
739
+ permission: {
740
+ id: null,
741
+ recordName: recordName,
742
+ userId: null,
743
+ // Record owners are treated as if they are admins in the record
744
+ subjectType: 'role',
745
+ subjectId: ADMIN_ROLE_NAME,
746
+ // Admins get all access to all resources in a record
747
+ resourceKind: null,
748
+ action: null,
749
+ marker: markers[0],
750
+ options: {},
751
+ expireTimeMs: null,
752
+ },
753
+ explanation: `Role is "${ADMIN_ROLE_NAME}".`,
754
+ };
755
+ }
756
+ if (context.recordKeyProvided &&
757
+ context.recordKeyResult &&
758
+ context.recordKeyResult.success &&
759
+ isAllowedRecordKeyResource(request.resourceKind, request.action)) {
760
+ if (context.subjectPolicy === 'subjectfull' &&
761
+ subjectType === 'user' &&
762
+ !subjectId) {
683
763
  return {
684
- success: true,
685
- recordName,
686
- permission: {
687
- id: null,
688
- recordName: recordName,
689
- userId: null,
690
- subjectType: subjectType,
691
- subjectId: subjectId,
692
- resourceKind: publicPermission.resourceKind,
693
- action: publicPermission.action,
694
- marker: publicPermission.marker,
695
- options: {},
696
- expireTimeMs: null,
697
- },
698
- explanation: publicPermission.marker === PUBLIC_READ_MARKER
699
- ? 'Resource has the publicRead marker.'
700
- : 'Resource has the publicWrite marker.',
764
+ success: false,
765
+ errorCode: 'not_logged_in',
766
+ errorMessage: 'You must be logged in in order to use this record key.',
701
767
  };
702
768
  }
703
- if (subjectType === 'role' && subjectId === ADMIN_ROLE_NAME) {
769
+ return {
770
+ success: true,
771
+ recordName: context.recordName,
772
+ permission: {
773
+ id: null,
774
+ recordName: recordName,
775
+ userId: null,
776
+ // Record owners are treated as if they are admins in the record
777
+ subjectType: 'role',
778
+ subjectId: ADMIN_ROLE_NAME,
779
+ // Admins get all access to all resources in a record
780
+ resourceKind: request.resourceKind,
781
+ action: request.action,
782
+ marker: markers[0],
783
+ options: {},
784
+ expireTimeMs: null,
785
+ },
786
+ explanation: 'A recordKey was used.',
787
+ };
788
+ }
789
+ if (subjectType === 'user' && subjectId) {
790
+ if (subjectId === context.recordOwnerId) {
704
791
  return {
705
792
  success: true,
706
793
  recordName: recordName,
@@ -718,130 +805,165 @@ export class PolicyController {
718
805
  options: {},
719
806
  expireTimeMs: null,
720
807
  },
721
- explanation: `Role is "${ADMIN_ROLE_NAME}".`,
808
+ explanation: 'User is the owner of the record.',
722
809
  };
723
810
  }
724
- if (context.recordKeyProvided &&
725
- context.recordKeyResult &&
726
- context.recordKeyResult.success &&
727
- isAllowedRecordKeyResource(request.resourceKind, request.action)) {
728
- if (context.subjectPolicy === 'subjectfull' &&
729
- subjectType === 'user' &&
730
- !subjectId) {
731
- return {
732
- success: false,
733
- errorCode: 'not_logged_in',
734
- errorMessage: 'You must be logged in in order to use this record key.',
735
- };
736
- }
737
- return {
738
- success: true,
739
- recordName: context.recordName,
740
- permission: {
741
- id: null,
742
- recordName: recordName,
743
- userId: null,
744
- // Record owners are treated as if they are admins in the record
745
- subjectType: 'role',
746
- subjectId: ADMIN_ROLE_NAME,
747
- // Admins get all access to all resources in a record
748
- resourceKind: request.resourceKind,
749
- action: request.action,
750
- marker: markers[0],
751
- options: {},
752
- expireTimeMs: null,
753
- },
754
- explanation: 'A recordKey was used.',
755
- };
756
- }
757
- if (subjectType === 'user' && subjectId) {
758
- if (subjectId === context.recordOwnerId) {
759
- return {
760
- success: true,
761
- recordName: recordName,
762
- permission: {
763
- id: null,
811
+ else if (context.recordStudioMembers) {
812
+ const member = context.recordStudioMembers.find((m) => m.userId === subjectId);
813
+ if (member) {
814
+ if (member.role === 'admin') {
815
+ return {
816
+ success: true,
764
817
  recordName: recordName,
765
- userId: null,
766
- // Record owners are treated as if they are admins in the record
767
- subjectType: 'role',
768
- subjectId: ADMIN_ROLE_NAME,
769
- // Admins get all access to all resources in a record
770
- resourceKind: null,
771
- action: null,
772
- marker: markers[0],
773
- options: {},
774
- expireTimeMs: null,
775
- },
776
- explanation: 'User is the owner of the record.',
777
- };
778
- }
779
- else if (context.recordStudioMembers) {
780
- const member = context.recordStudioMembers.find((m) => m.userId === subjectId);
781
- if (member) {
782
- if (member.role === 'admin') {
818
+ permission: {
819
+ id: null,
820
+ recordName: recordName,
821
+ userId: null,
822
+ // Admins in a studio are treated as if they are admins in the record.
823
+ subjectType: 'role',
824
+ subjectId: ADMIN_ROLE_NAME,
825
+ // Admins get all access to all resources in a record
826
+ resourceKind: null,
827
+ action: null,
828
+ marker: markers[0],
829
+ options: {},
830
+ // No expiration
831
+ expireTimeMs: null,
832
+ },
833
+ explanation: "User is an admin in the record's studio.",
834
+ };
835
+ }
836
+ else if (member.role === 'member') {
837
+ let isAssigningDefaultMarker = (request.resourceKind === 'marker' &&
838
+ request.resourceId ===
839
+ PUBLIC_READ_MARKER) ||
840
+ request.resourceId === PRIVATE_MARKER;
841
+ if (isAssigningDefaultMarker ||
842
+ isAllowedStudioMemberResource(request.resourceKind, request.action)) {
783
843
  return {
784
844
  success: true,
785
845
  recordName: recordName,
786
846
  permission: {
787
847
  id: null,
788
848
  recordName: recordName,
789
- userId: null,
790
- // Admins in a studio are treated as if they are admins in the record.
791
- subjectType: 'role',
792
- subjectId: ADMIN_ROLE_NAME,
793
- // Admins get all access to all resources in a record
794
- resourceKind: null,
795
- action: null,
849
+ // Members in a studio are treated as if they are granted direct access to most resources
850
+ // in the record.
851
+ userId: subjectId,
852
+ subjectType: 'user',
853
+ subjectId: subjectId,
854
+ // Not all actions or resources are granted though
855
+ resourceKind: request.resourceKind,
856
+ action: request.action,
796
857
  marker: markers[0],
797
858
  options: {},
798
- // No expiration
799
859
  expireTimeMs: null,
800
860
  },
801
- explanation: "User is an admin in the record's studio.",
861
+ explanation: "User is a member in the record's studio.",
802
862
  };
803
863
  }
804
- else if (member.role === 'member') {
805
- let isAssigningDefaultMarker = (request.resourceKind === 'marker' &&
806
- request.resourceId ===
807
- PUBLIC_READ_MARKER) ||
808
- request.resourceId === PRIVATE_MARKER;
809
- if (isAssigningDefaultMarker ||
810
- isAllowedStudioMemberResource(request.resourceKind, request.action)) {
811
- return {
812
- success: true,
813
- recordName: recordName,
814
- permission: {
815
- id: null,
816
- recordName: recordName,
817
- // Members in a studio are treated as if they are granted direct access to most resources
818
- // in the record.
819
- userId: subjectId,
820
- subjectType: 'user',
821
- subjectId: subjectId,
822
- // Not all actions or resources are granted though
823
- resourceKind: request.resourceKind,
824
- action: request.action,
825
- marker: markers[0],
826
- options: {},
827
- expireTimeMs: null,
828
- },
829
- explanation: "User is a member in the record's studio.",
830
- };
864
+ }
865
+ }
866
+ }
867
+ }
868
+ else if (subjectType === 'inst' && subjectId) {
869
+ const instId = parseInstId(subjectId);
870
+ if (!instId) {
871
+ return {
872
+ success: false,
873
+ errorCode: 'unacceptable_request',
874
+ errorMessage: 'Invalid inst ID. It must contain a forward slash',
875
+ };
876
+ }
877
+ const entitlementFeature = getEntitlementFeatureForAction(request.resourceKind, request.action);
878
+ let hasPackages = false;
879
+ if (entitlementFeature) {
880
+ const loadedPackages = (_b = (await ((_a = this._insts) === null || _a === void 0 ? void 0 : _a.listLoadedPackages(instId.recordName, instId.inst)))) !== null && _b !== void 0 ? _b : [];
881
+ const grantedEntitlements = await this._policies.listGrantedEntitlementsByFeatureAndUserId(loadedPackages.map((p) => p.packageId), entitlementFeature, context.userId, context.recordName, Date.now());
882
+ if ((loadedPackages === null || loadedPackages === void 0 ? void 0 : loadedPackages.length) > 0 ||
883
+ (grantedEntitlements === null || grantedEntitlements === void 0 ? void 0 : grantedEntitlements.length) > 0) {
884
+ hasPackages = true;
885
+ }
886
+ if (grantedEntitlements && grantedEntitlements.length > 0) {
887
+ // check scope
888
+ const entitlement = grantedEntitlements.find((entitlement) => {
889
+ if (entitlement.revokeTimeMs === null &&
890
+ entitlement.scope === 'designated' &&
891
+ entitlement.recordName ===
892
+ context.recordName) {
893
+ // Entitlement is for the current record
894
+ return true;
895
+ }
896
+ else {
897
+ return false;
898
+ }
899
+ });
900
+ if (entitlement) {
901
+ const loadedPackage = loadedPackages.find((lp) => lp.packageId === entitlement.packageId);
902
+ return {
903
+ success: true,
904
+ recordName,
905
+ permission: {
906
+ id: null,
907
+ recordName,
908
+ userId: context.userId,
909
+ subjectType: 'inst',
910
+ subjectId: subjectId,
911
+ // Not all actions or resources are granted though
912
+ resourceKind: request.resourceKind,
913
+ resourceId: request.resourceId,
914
+ action: request.action,
915
+ options: {},
916
+ expireTimeMs: entitlement.expireTimeMs,
917
+ },
918
+ entitlementGrant: {
919
+ ...entitlement,
920
+ loadedPackage,
921
+ },
922
+ explanation: `Inst has entitlement.`,
923
+ };
924
+ }
925
+ }
926
+ if (hasPackages) {
927
+ const firstPackage = loadedPackages[0];
928
+ const pkg = await ((_c = this._packageVersions) === null || _c === void 0 ? void 0 : _c.getItemById(firstPackage.packageVersionId));
929
+ if (pkg === null || pkg === void 0 ? void 0 : pkg.item) {
930
+ const canRecommendEntitlement = pkg.item.entitlements.some((e) => {
931
+ var _a, _b;
932
+ if (e.scope === 'personal' &&
933
+ context.userId === context.recordName) {
934
+ return true;
935
+ }
936
+ else if (e.scope === 'owned' &&
937
+ context.recordOwnerId === context.userId) {
938
+ return true;
939
+ }
940
+ else if (e.scope === 'studio' &&
941
+ ((_a = context.recordStudioMembers) === null || _a === void 0 ? void 0 : _a.some((m) => m.userId === context.userId))) {
942
+ return true;
943
+ }
944
+ else if (e.scope === 'designated' &&
945
+ ((_b = e.designatedRecords) === null || _b === void 0 ? void 0 : _b.includes(context.recordName))) {
946
+ return true;
947
+ }
948
+ else if (e.scope === 'shared') {
949
+ return true;
831
950
  }
951
+ return false;
952
+ });
953
+ if (canRecommendEntitlement) {
954
+ recommendedEntitlement = {
955
+ feature: entitlementFeature,
956
+ scope: 'designated',
957
+ recordName: context.recordName,
958
+ packageId: loadedPackages[0].packageId,
959
+ };
832
960
  }
833
961
  }
834
962
  }
835
963
  }
836
- else if (subjectType === 'inst' && subjectId) {
837
- const instId = parseInstId(subjectId);
838
- if (!instId) {
839
- return {
840
- success: false,
841
- errorCode: 'unacceptable_request',
842
- errorMessage: 'Invalid inst ID. It must contain a forward slash',
843
- };
844
- }
964
+ // Automatic permissions don't apply to insts with packages
965
+ // TODO: Maybe add a flag for insts to choose whether they want automatic permissions or if they have to explicitly grant them or use packages
966
+ if (!hasPackages) {
845
967
  if (instId.recordName) {
846
968
  if (instId.recordName === recordName) {
847
969
  return {
@@ -864,7 +986,7 @@ export class PolicyController {
864
986
  explanation: `Inst is owned by the record.`,
865
987
  };
866
988
  }
867
- const instRecord = yield this._records.validateRecordName(instId.recordName, context.userId);
989
+ const instRecord = await this._records.validateRecordName(instId.recordName, context.userId);
868
990
  if (instRecord.success === false) {
869
991
  return instRecord;
870
992
  }
@@ -914,95 +1036,96 @@ export class PolicyController {
914
1036
  }
915
1037
  }
916
1038
  }
917
- if (subjectId) {
918
- if (subjectType === 'inst' || subjectType === 'user') {
919
- // check for admin role
920
- const roles = subjectType === 'user'
921
- ? yield this._policies.listRolesForUser(recordName, subjectId)
922
- : yield this._policies.listRolesForInst(recordName, subjectId);
923
- const role = roles.find((r) => r.role === ADMIN_ROLE_NAME);
924
- if (role) {
925
- const kindString = subjectType === 'user' ? 'User' : 'Inst';
926
- return {
927
- success: true,
928
- recordName: recordName,
929
- permission: {
930
- id: null,
931
- recordName: recordName,
932
- userId: null,
933
- // Admins in a studio are treated as if they are admins in the record.
934
- subjectType: 'role',
935
- subjectId: ADMIN_ROLE_NAME,
936
- // Admins get all access to all resources in a record
937
- resourceKind: null,
938
- action: null,
939
- marker: markers[0],
940
- options: {},
941
- // No expiration
942
- expireTimeMs: role.expireTimeMs,
943
- },
944
- explanation: `${kindString} is assigned the "${ADMIN_ROLE_NAME}" role.`,
945
- };
946
- }
947
- }
948
- let permission = null;
949
- if (request.resourceId) {
950
- const result = yield this._policies.getPermissionForSubjectAndResource(subjectType, subjectId, recordName, request.resourceKind, request.resourceId, request.action, Date.now());
951
- if (result.success === false) {
952
- return result;
953
- }
954
- permission = result.permissionAssignment;
955
- }
956
- if (!permission) {
957
- const result = yield this._policies.getPermissionForSubjectAndMarkers(subjectType, subjectId, recordName, request.resourceKind, markers, request.action, Date.now());
958
- if (result.success === false) {
959
- return result;
960
- }
961
- permission = result.permissionAssignment;
962
- }
963
- if (permission) {
1039
+ }
1040
+ if (subjectId) {
1041
+ if (subjectType === 'inst' || subjectType === 'user') {
1042
+ // check for admin role
1043
+ const roles = subjectType === 'user'
1044
+ ? await this._policies.listRolesForUser(recordName, subjectId)
1045
+ : await this._policies.listRolesForInst(recordName, subjectId);
1046
+ const role = roles.find((r) => r.role === ADMIN_ROLE_NAME);
1047
+ if (role) {
1048
+ const kindString = subjectType === 'user' ? 'User' : 'Inst';
964
1049
  return {
965
1050
  success: true,
966
- recordName,
967
- permission: permission,
968
- explanation: explainationForPermissionAssignment(subjectType, permission),
1051
+ recordName: recordName,
1052
+ permission: {
1053
+ id: null,
1054
+ recordName: recordName,
1055
+ userId: null,
1056
+ // Admins in a studio are treated as if they are admins in the record.
1057
+ subjectType: 'role',
1058
+ subjectId: ADMIN_ROLE_NAME,
1059
+ // Admins get all access to all resources in a record
1060
+ resourceKind: null,
1061
+ action: null,
1062
+ marker: markers[0],
1063
+ options: {},
1064
+ // No expiration
1065
+ expireTimeMs: role.expireTimeMs,
1066
+ },
1067
+ explanation: `${kindString} is assigned the "${ADMIN_ROLE_NAME}" role.`,
969
1068
  };
970
1069
  }
971
1070
  }
972
- if (context.sendNotLoggedIn &&
973
- !subjectId &&
974
- (!context.recordKeyProvided ||
975
- !isAllowedRecordKeyResource(request.resourceKind, request.action))) {
1071
+ let permission = null;
1072
+ if (request.resourceId) {
1073
+ const result = await this._policies.getPermissionForSubjectAndResource(subjectType, subjectId, recordName, request.resourceKind, request.resourceId, request.action, Date.now());
1074
+ if (result.success === false) {
1075
+ return result;
1076
+ }
1077
+ permission = result.permissionAssignment;
1078
+ }
1079
+ if (!permission) {
1080
+ const result = await this._policies.getPermissionForSubjectAndMarkers(subjectType, subjectId, recordName, request.resourceKind, markers, request.action, Date.now());
1081
+ if (result.success === false) {
1082
+ return result;
1083
+ }
1084
+ permission = result.permissionAssignment;
1085
+ }
1086
+ if (permission) {
976
1087
  return {
977
- success: false,
978
- errorCode: 'not_logged_in',
979
- errorMessage: 'The user must be logged in. Please provide a sessionKey or a recordKey.',
1088
+ success: true,
1089
+ recordName,
1090
+ permission: permission,
1091
+ explanation: explainationForPermissionAssignment(subjectType, permission),
980
1092
  };
981
1093
  }
982
- return {
983
- success: false,
984
- errorCode: 'not_authorized',
985
- errorMessage: 'You are not authorized to perform this action.',
986
- reason: {
987
- type: 'missing_permission',
988
- recordName: recordName,
989
- subjectType: subjectType,
990
- subjectId: subjectId,
991
- resourceKind: request.resourceKind,
992
- resourceId: request.resourceId,
993
- action: request.action,
994
- },
995
- };
996
1094
  }
997
- catch (err) {
998
- console.error('[PolicyController] A server error occurred while authorizing a subject.', err);
1095
+ if (context.sendNotLoggedIn &&
1096
+ !subjectId &&
1097
+ (!context.recordKeyProvided ||
1098
+ !isAllowedRecordKeyResource(request.resourceKind, request.action))) {
999
1099
  return {
1000
1100
  success: false,
1001
- errorCode: 'server_error',
1002
- errorMessage: 'A server error occurred.',
1101
+ errorCode: 'not_logged_in',
1102
+ errorMessage: 'The user must be logged in. Please provide a sessionKey or a recordKey.',
1003
1103
  };
1004
1104
  }
1005
- });
1105
+ return {
1106
+ success: false,
1107
+ errorCode: 'not_authorized',
1108
+ errorMessage: 'You are not authorized to perform this action.',
1109
+ reason: {
1110
+ type: 'missing_permission',
1111
+ recordName: recordName,
1112
+ subjectType: subjectType,
1113
+ subjectId: subjectId,
1114
+ resourceKind: request.resourceKind,
1115
+ resourceId: request.resourceId,
1116
+ action: request.action,
1117
+ },
1118
+ recommendedEntitlement,
1119
+ };
1120
+ }
1121
+ catch (err) {
1122
+ console.error('[PolicyController] A server error occurred while authorizing a subject.', err);
1123
+ return {
1124
+ success: false,
1125
+ errorCode: 'server_error',
1126
+ errorMessage: 'A server error occurred.',
1127
+ };
1128
+ }
1006
1129
  }
1007
1130
  /**
1008
1131
  * Gets the list of permissions in the given record.
@@ -1010,70 +1133,68 @@ export class PolicyController {
1010
1133
  * @param userId The ID of the currently logged in user.
1011
1134
  * @param instances The instances that are loaded.
1012
1135
  */
1013
- listPermissions(recordKeyOrRecordName, userId, instances) {
1014
- return __awaiter(this, void 0, void 0, function* () {
1015
- try {
1016
- const context = yield this.constructAuthorizationContext({
1017
- recordKeyOrRecordName,
1018
- userId,
1019
- });
1020
- if (context.success === false) {
1021
- return context;
1022
- }
1023
- const authorization = yield this.authorizeUserAndInstances(context.context, {
1024
- userId,
1025
- instances,
1026
- resourceKind: 'marker',
1027
- action: 'list',
1028
- markers: [ACCOUNT_MARKER],
1029
- });
1030
- if (authorization.success === false) {
1031
- return authorization;
1032
- }
1033
- const recordName = context.context.recordName;
1034
- const result = yield this._policies.listPermissionsInRecord(recordName);
1035
- if (result.success === false) {
1036
- return result;
1037
- }
1038
- return {
1039
- success: true,
1040
- recordName,
1041
- resourcePermissions: result.resourceAssignments.map((r) => ({
1042
- id: r.id,
1043
- recordName: r.recordName,
1044
- subjectType: r.subjectType,
1045
- subjectId: r.subjectId,
1046
- resourceKind: r.resourceKind,
1047
- action: r.action,
1048
- resourceId: r.resourceId,
1049
- options: r.options,
1050
- expireTimeMs: r.expireTimeMs,
1051
- })),
1052
- markerPermissions: result.markerAssignments.map((r) => ({
1053
- id: r.id,
1054
- recordName: r.recordName,
1055
- subjectType: r.subjectType,
1056
- subjectId: r.subjectId,
1057
- resourceKind: r.resourceKind,
1058
- action: r.action,
1059
- marker: r.marker,
1060
- options: r.options,
1061
- expireTimeMs: r.expireTimeMs,
1062
- })),
1063
- };
1136
+ async listPermissions(recordKeyOrRecordName, userId, instances) {
1137
+ try {
1138
+ const context = await this.constructAuthorizationContext({
1139
+ recordKeyOrRecordName,
1140
+ userId,
1141
+ });
1142
+ if (context.success === false) {
1143
+ return context;
1064
1144
  }
1065
- catch (err) {
1066
- const span = trace.getActiveSpan();
1067
- span === null || span === void 0 ? void 0 : span.recordException(err);
1068
- span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
1069
- console.error('[PolicyController] A server error occurred while listing permissions.', err);
1070
- return {
1071
- success: false,
1072
- errorCode: 'server_error',
1073
- errorMessage: 'A server error occurred.',
1074
- };
1145
+ const authorization = await this.authorizeUserAndInstances(context.context, {
1146
+ userId,
1147
+ instances,
1148
+ resourceKind: 'marker',
1149
+ action: 'list',
1150
+ markers: [ACCOUNT_MARKER],
1151
+ });
1152
+ if (authorization.success === false) {
1153
+ return authorization;
1075
1154
  }
1076
- });
1155
+ const recordName = context.context.recordName;
1156
+ const result = await this._policies.listPermissionsInRecord(recordName);
1157
+ if (result.success === false) {
1158
+ return result;
1159
+ }
1160
+ return {
1161
+ success: true,
1162
+ recordName,
1163
+ resourcePermissions: result.resourceAssignments.map((r) => ({
1164
+ id: r.id,
1165
+ recordName: r.recordName,
1166
+ subjectType: r.subjectType,
1167
+ subjectId: r.subjectId,
1168
+ resourceKind: r.resourceKind,
1169
+ action: r.action,
1170
+ resourceId: r.resourceId,
1171
+ options: r.options,
1172
+ expireTimeMs: r.expireTimeMs,
1173
+ })),
1174
+ markerPermissions: result.markerAssignments.map((r) => ({
1175
+ id: r.id,
1176
+ recordName: r.recordName,
1177
+ subjectType: r.subjectType,
1178
+ subjectId: r.subjectId,
1179
+ resourceKind: r.resourceKind,
1180
+ action: r.action,
1181
+ marker: r.marker,
1182
+ options: r.options,
1183
+ expireTimeMs: r.expireTimeMs,
1184
+ })),
1185
+ };
1186
+ }
1187
+ catch (err) {
1188
+ const span = trace.getActiveSpan();
1189
+ span === null || span === void 0 ? void 0 : span.recordException(err);
1190
+ span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
1191
+ console.error('[PolicyController] A server error occurred while listing permissions.', err);
1192
+ return {
1193
+ success: false,
1194
+ errorCode: 'server_error',
1195
+ errorMessage: 'A server error occurred.',
1196
+ };
1197
+ }
1077
1198
  }
1078
1199
  /**
1079
1200
  * Gets the list of permissions that have been assigned to the given marker.
@@ -1082,57 +1203,55 @@ export class PolicyController {
1082
1203
  * @param userId The ID of the currently logged in user.
1083
1204
  * @param instances The instances that are loaded.
1084
1205
  */
1085
- listPermissionsForMarker(recordKeyOrRecordName, marker, userId, instances) {
1086
- return __awaiter(this, void 0, void 0, function* () {
1087
- try {
1088
- marker = getRootMarker(marker);
1089
- const context = yield this.constructAuthorizationContext({
1090
- recordKeyOrRecordName,
1091
- userId,
1092
- });
1093
- if (context.success === false) {
1094
- return context;
1095
- }
1096
- const authorization = yield this.authorizeUserAndInstances(context.context, {
1097
- userId,
1098
- instances,
1099
- resourceKind: 'marker',
1100
- action: 'list',
1101
- markers: [ACCOUNT_MARKER],
1102
- });
1103
- if (authorization.success === false) {
1104
- return authorization;
1105
- }
1106
- const recordName = context.context.recordName;
1107
- const result = yield this._policies.listPermissionsForMarker(recordName, marker);
1108
- return {
1109
- success: true,
1110
- recordName,
1111
- markerPermissions: result.map((r) => ({
1112
- id: r.id,
1113
- recordName: r.recordName,
1114
- subjectType: r.subjectType,
1115
- subjectId: r.subjectId,
1116
- resourceKind: r.resourceKind,
1117
- action: r.action,
1118
- marker: r.marker,
1119
- options: r.options,
1120
- expireTimeMs: r.expireTimeMs,
1121
- })),
1122
- };
1206
+ async listPermissionsForMarker(recordKeyOrRecordName, marker, userId, instances) {
1207
+ try {
1208
+ marker = getRootMarker(marker);
1209
+ const context = await this.constructAuthorizationContext({
1210
+ recordKeyOrRecordName,
1211
+ userId,
1212
+ });
1213
+ if (context.success === false) {
1214
+ return context;
1123
1215
  }
1124
- catch (err) {
1125
- const span = trace.getActiveSpan();
1126
- span === null || span === void 0 ? void 0 : span.recordException(err);
1127
- span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
1128
- console.error('[PolicyController] A server error occurred while listing permissions for marker.', err);
1129
- return {
1130
- success: false,
1131
- errorCode: 'server_error',
1132
- errorMessage: 'A server error occurred.',
1133
- };
1216
+ const authorization = await this.authorizeUserAndInstances(context.context, {
1217
+ userId,
1218
+ instances,
1219
+ resourceKind: 'marker',
1220
+ action: 'list',
1221
+ markers: [ACCOUNT_MARKER],
1222
+ });
1223
+ if (authorization.success === false) {
1224
+ return authorization;
1134
1225
  }
1135
- });
1226
+ const recordName = context.context.recordName;
1227
+ const result = await this._policies.listPermissionsForMarker(recordName, marker);
1228
+ return {
1229
+ success: true,
1230
+ recordName,
1231
+ markerPermissions: result.map((r) => ({
1232
+ id: r.id,
1233
+ recordName: r.recordName,
1234
+ subjectType: r.subjectType,
1235
+ subjectId: r.subjectId,
1236
+ resourceKind: r.resourceKind,
1237
+ action: r.action,
1238
+ marker: r.marker,
1239
+ options: r.options,
1240
+ expireTimeMs: r.expireTimeMs,
1241
+ })),
1242
+ };
1243
+ }
1244
+ catch (err) {
1245
+ const span = trace.getActiveSpan();
1246
+ span === null || span === void 0 ? void 0 : span.recordException(err);
1247
+ span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
1248
+ console.error('[PolicyController] A server error occurred while listing permissions for marker.', err);
1249
+ return {
1250
+ success: false,
1251
+ errorCode: 'server_error',
1252
+ errorMessage: 'A server error occurred.',
1253
+ };
1254
+ }
1136
1255
  }
1137
1256
  /**
1138
1257
  * Gets the list of permissions that have been assigned to the given marker.
@@ -1142,406 +1261,341 @@ export class PolicyController {
1142
1261
  * @param userId The ID of the currently logged in user.
1143
1262
  * @param instances The instances that are loaded.
1144
1263
  */
1145
- listPermissionsForResource(recordKeyOrRecordName, resourceKind, resourceId, userId, instances) {
1146
- return __awaiter(this, void 0, void 0, function* () {
1147
- try {
1148
- const context = yield this.constructAuthorizationContext({
1149
- recordKeyOrRecordName,
1150
- userId,
1151
- });
1152
- if (context.success === false) {
1153
- return context;
1154
- }
1155
- const authorization = yield this.authorizeUserAndInstances(context.context, {
1156
- userId,
1157
- instances,
1158
- resourceKind: 'marker',
1159
- action: 'list',
1160
- markers: [ACCOUNT_MARKER],
1161
- });
1162
- if (authorization.success === false) {
1163
- return authorization;
1164
- }
1165
- const recordName = context.context.recordName;
1166
- const result = yield this._policies.listPermissionsForResource(recordName, resourceKind, resourceId);
1167
- return {
1168
- success: true,
1169
- recordName,
1170
- resourcePermissions: result.map((r) => ({
1171
- id: r.id,
1172
- recordName: r.recordName,
1173
- subjectType: r.subjectType,
1174
- subjectId: r.subjectId,
1175
- resourceKind: r.resourceKind,
1176
- action: r.action,
1177
- resourceId: r.resourceId,
1178
- options: r.options,
1179
- expireTimeMs: r.expireTimeMs,
1180
- })),
1181
- };
1264
+ async listPermissionsForResource(recordKeyOrRecordName, resourceKind, resourceId, userId, instances) {
1265
+ try {
1266
+ const context = await this.constructAuthorizationContext({
1267
+ recordKeyOrRecordName,
1268
+ userId,
1269
+ });
1270
+ if (context.success === false) {
1271
+ return context;
1182
1272
  }
1183
- catch (err) {
1184
- const span = trace.getActiveSpan();
1185
- span === null || span === void 0 ? void 0 : span.recordException(err);
1186
- span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
1187
- console.error('[PolicyController] A server error occurred while listing permissions for resource.', err);
1188
- return {
1189
- success: false,
1190
- errorCode: 'server_error',
1191
- errorMessage: 'A server error occurred.',
1192
- };
1273
+ const authorization = await this.authorizeUserAndInstances(context.context, {
1274
+ userId,
1275
+ instances,
1276
+ resourceKind: 'marker',
1277
+ action: 'list',
1278
+ markers: [ACCOUNT_MARKER],
1279
+ });
1280
+ if (authorization.success === false) {
1281
+ return authorization;
1193
1282
  }
1194
- });
1283
+ const recordName = context.context.recordName;
1284
+ const result = await this._policies.listPermissionsForResource(recordName, resourceKind, resourceId);
1285
+ return {
1286
+ success: true,
1287
+ recordName,
1288
+ resourcePermissions: result.map((r) => ({
1289
+ id: r.id,
1290
+ recordName: r.recordName,
1291
+ subjectType: r.subjectType,
1292
+ subjectId: r.subjectId,
1293
+ resourceKind: r.resourceKind,
1294
+ action: r.action,
1295
+ resourceId: r.resourceId,
1296
+ options: r.options,
1297
+ expireTimeMs: r.expireTimeMs,
1298
+ })),
1299
+ };
1300
+ }
1301
+ catch (err) {
1302
+ const span = trace.getActiveSpan();
1303
+ span === null || span === void 0 ? void 0 : span.recordException(err);
1304
+ span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
1305
+ console.error('[PolicyController] A server error occurred while listing permissions for resource.', err);
1306
+ return {
1307
+ success: false,
1308
+ errorCode: 'server_error',
1309
+ errorMessage: 'A server error occurred.',
1310
+ };
1311
+ }
1195
1312
  }
1196
1313
  /**
1197
1314
  * Attempts to grant a permission to a marker.
1198
1315
  * @param request The request for the operation.
1199
1316
  */
1200
- grantMarkerPermission(request) {
1317
+ async grantMarkerPermission(request) {
1201
1318
  var _a, _b, _c;
1202
- return __awaiter(this, void 0, void 0, function* () {
1203
- try {
1204
- const baseRequest = {
1205
- recordKeyOrRecordName: request.recordKeyOrRecordName,
1206
- userId: request.userId,
1207
- };
1208
- const context = yield this.constructAuthorizationContext(baseRequest);
1209
- if (context.success === false) {
1210
- return {
1211
- success: false,
1212
- errorCode: context.errorCode,
1213
- errorMessage: context.errorMessage,
1214
- };
1215
- }
1216
- const marker = getRootMarker(request.marker);
1217
- const authorization = yield this.authorizeUserAndInstances(context.context, {
1218
- action: 'grantPermission',
1219
- resourceKind: 'marker',
1220
- resourceId: marker,
1221
- markers: [ACCOUNT_MARKER],
1222
- userId: request.userId,
1223
- instances: request.instances,
1224
- });
1225
- if (authorization.success === false) {
1226
- return authorization;
1227
- }
1228
- const recordName = context.context.recordName;
1229
- const assignmentResult = yield this._policies.assignPermissionToSubjectAndMarker(recordName, request.permission.subjectType, request.permission.subjectId, request.permission.resourceKind, marker, request.permission.action, request.permission.options, request.permission.expireTimeMs);
1230
- if (assignmentResult.success === false) {
1231
- return assignmentResult;
1232
- }
1233
- console.log(`[PolicyController] [grantMarkerPermission] [userId: ${request.userId}, recordName: ${recordName}, subjectType: ${request.permission.subjectType}, subjectId: ${request.permission.subjectId}, marker: ${marker}, resourceKind: ${(_a = request.permission.resourceKind) !== null && _a !== void 0 ? _a : '(null)'}, action: ${(_b = request.permission.action) !== null && _b !== void 0 ? _b : '(null)'}, expireTimeMs: ${(_c = request.permission.expireTimeMs) !== null && _c !== void 0 ? _c : '(null)'}, permissionId: ${assignmentResult.permissionAssignment.id}] Granted marker permission.`);
1234
- return {
1235
- success: true,
1236
- };
1237
- }
1238
- catch (err) {
1239
- const span = trace.getActiveSpan();
1240
- span === null || span === void 0 ? void 0 : span.recordException(err);
1241
- span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
1242
- console.error('[PolicyController] A server error occurred while granting a marker permission.', err);
1319
+ try {
1320
+ const baseRequest = {
1321
+ recordKeyOrRecordName: request.recordKeyOrRecordName,
1322
+ userId: request.userId,
1323
+ };
1324
+ const context = await this.constructAuthorizationContext(baseRequest);
1325
+ if (context.success === false) {
1243
1326
  return {
1244
1327
  success: false,
1245
- errorCode: 'server_error',
1246
- errorMessage: 'A server error occurred.',
1328
+ errorCode: context.errorCode,
1329
+ errorMessage: context.errorMessage,
1247
1330
  };
1248
1331
  }
1249
- });
1332
+ const marker = getRootMarker(request.marker);
1333
+ const authorization = await this.authorizeUserAndInstances(context.context, {
1334
+ action: 'grantPermission',
1335
+ resourceKind: 'marker',
1336
+ resourceId: marker,
1337
+ markers: [ACCOUNT_MARKER],
1338
+ userId: request.userId,
1339
+ instances: request.instances,
1340
+ });
1341
+ if (authorization.success === false) {
1342
+ return authorization;
1343
+ }
1344
+ const recordName = context.context.recordName;
1345
+ const assignmentResult = await this._policies.assignPermissionToSubjectAndMarker(recordName, request.permission.subjectType, request.permission.subjectId, request.permission.resourceKind, marker, request.permission.action, request.permission.options, request.permission.expireTimeMs);
1346
+ if (assignmentResult.success === false) {
1347
+ return assignmentResult;
1348
+ }
1349
+ console.log(`[PolicyController] [grantMarkerPermission] [userId: ${request.userId}, recordName: ${recordName}, subjectType: ${request.permission.subjectType}, subjectId: ${request.permission.subjectId}, marker: ${marker}, resourceKind: ${(_a = request.permission.resourceKind) !== null && _a !== void 0 ? _a : '(null)'}, action: ${(_b = request.permission.action) !== null && _b !== void 0 ? _b : '(null)'}, expireTimeMs: ${(_c = request.permission.expireTimeMs) !== null && _c !== void 0 ? _c : '(null)'}, permissionId: ${assignmentResult.permissionAssignment.id}] Granted marker permission.`);
1350
+ return {
1351
+ success: true,
1352
+ };
1353
+ }
1354
+ catch (err) {
1355
+ const span = trace.getActiveSpan();
1356
+ span === null || span === void 0 ? void 0 : span.recordException(err);
1357
+ span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
1358
+ console.error('[PolicyController] A server error occurred while granting a marker permission.', err);
1359
+ return {
1360
+ success: false,
1361
+ errorCode: 'server_error',
1362
+ errorMessage: 'A server error occurred.',
1363
+ };
1364
+ }
1250
1365
  }
1251
1366
  /**
1252
1367
  * Attempts to revoke a permission from a marker.
1253
1368
  * @param request The request for the operation.
1254
1369
  */
1255
- revokeMarkerPermission(request) {
1256
- return __awaiter(this, void 0, void 0, function* () {
1257
- try {
1258
- const permission = yield this._policies.getMarkerPermissionAssignmentById(request.permissionId);
1259
- if (!permission) {
1260
- return {
1261
- success: false,
1262
- errorCode: 'permission_not_found',
1263
- errorMessage: 'The permission was not found.',
1264
- };
1265
- }
1266
- const baseRequest = {
1267
- recordKeyOrRecordName: permission.recordName,
1268
- userId: request.userId,
1269
- };
1270
- const context = yield this.constructAuthorizationContext(baseRequest);
1271
- if (context.success === false) {
1272
- return {
1273
- success: false,
1274
- errorCode: context.errorCode,
1275
- errorMessage: context.errorMessage,
1276
- };
1277
- }
1278
- const authorization = yield this.authorizeUserAndInstances(context.context, {
1279
- action: 'revokePermission',
1280
- resourceKind: 'marker',
1281
- resourceId: permission.marker,
1282
- markers: [ACCOUNT_MARKER],
1283
- userId: request.userId,
1284
- instances: request.instances,
1285
- });
1286
- if (authorization.success === false) {
1287
- return authorization;
1288
- }
1289
- const deleteResult = yield this._policies.deleteMarkerPermissionAssignmentById(permission.id);
1290
- if (!deleteResult.success) {
1291
- return deleteResult;
1292
- }
1293
- console.log(`[PolicyController] [revokeMarkerPermission] [userId: ${request.userId}, permissionId: ${request.permissionId}] Revoked marker permission.`);
1370
+ async revokeMarkerPermission(request) {
1371
+ try {
1372
+ const permission = await this._policies.getMarkerPermissionAssignmentById(request.permissionId);
1373
+ if (!permission) {
1294
1374
  return {
1295
- success: true,
1375
+ success: false,
1376
+ errorCode: 'permission_not_found',
1377
+ errorMessage: 'The permission was not found.',
1296
1378
  };
1297
1379
  }
1298
- catch (err) {
1299
- const span = trace.getActiveSpan();
1300
- span === null || span === void 0 ? void 0 : span.recordException(err);
1301
- span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
1302
- console.error('[PolicyController] A server error occurred while revoking a marker permission.', err);
1380
+ const baseRequest = {
1381
+ recordKeyOrRecordName: permission.recordName,
1382
+ userId: request.userId,
1383
+ };
1384
+ const context = await this.constructAuthorizationContext(baseRequest);
1385
+ if (context.success === false) {
1303
1386
  return {
1304
1387
  success: false,
1305
- errorCode: 'server_error',
1306
- errorMessage: 'A server error occurred.',
1388
+ errorCode: context.errorCode,
1389
+ errorMessage: context.errorMessage,
1307
1390
  };
1308
1391
  }
1309
- });
1392
+ const authorization = await this.authorizeUserAndInstances(context.context, {
1393
+ action: 'revokePermission',
1394
+ resourceKind: 'marker',
1395
+ resourceId: permission.marker,
1396
+ markers: [ACCOUNT_MARKER],
1397
+ userId: request.userId,
1398
+ instances: request.instances,
1399
+ });
1400
+ if (authorization.success === false) {
1401
+ return authorization;
1402
+ }
1403
+ const deleteResult = await this._policies.deleteMarkerPermissionAssignmentById(permission.id);
1404
+ if (!deleteResult.success) {
1405
+ return deleteResult;
1406
+ }
1407
+ console.log(`[PolicyController] [revokeMarkerPermission] [userId: ${request.userId}, permissionId: ${request.permissionId}] Revoked marker permission.`);
1408
+ return {
1409
+ success: true,
1410
+ };
1411
+ }
1412
+ catch (err) {
1413
+ const span = trace.getActiveSpan();
1414
+ span === null || span === void 0 ? void 0 : span.recordException(err);
1415
+ span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
1416
+ console.error('[PolicyController] A server error occurred while revoking a marker permission.', err);
1417
+ return {
1418
+ success: false,
1419
+ errorCode: 'server_error',
1420
+ errorMessage: 'A server error occurred.',
1421
+ };
1422
+ }
1310
1423
  }
1311
1424
  /**
1312
1425
  * Attempts to grant a permission to a resource.
1313
1426
  * @param request The request.
1314
1427
  */
1315
- grantResourcePermission(request) {
1428
+ async grantResourcePermission(request) {
1316
1429
  var _a, _b, _c, _d;
1317
- return __awaiter(this, void 0, void 0, function* () {
1318
- try {
1319
- const baseRequest = {
1320
- recordKeyOrRecordName: request.recordKeyOrRecordName,
1321
- userId: request.userId,
1430
+ try {
1431
+ const baseRequest = {
1432
+ recordKeyOrRecordName: request.recordKeyOrRecordName,
1433
+ userId: request.userId,
1434
+ };
1435
+ const context = await this.constructAuthorizationContext(baseRequest);
1436
+ if (context.success === false) {
1437
+ return {
1438
+ success: false,
1439
+ errorCode: context.errorCode,
1440
+ errorMessage: context.errorMessage,
1322
1441
  };
1323
- const context = yield this.constructAuthorizationContext(baseRequest);
1324
- if (context.success === false) {
1325
- return {
1326
- success: false,
1327
- errorCode: context.errorCode,
1328
- errorMessage: context.errorMessage,
1329
- };
1330
- }
1331
- if (!request.permission.resourceId) {
1332
- return {
1333
- success: false,
1334
- errorCode: 'unacceptable_request',
1335
- errorMessage: 'You must provide a resourceId for the permission.',
1336
- };
1337
- }
1338
- else if (!request.permission.resourceKind) {
1339
- return {
1340
- success: false,
1341
- errorCode: 'unacceptable_request',
1342
- errorMessage: 'You must provide a resourceKind for the permission.',
1343
- };
1344
- }
1345
- const authorization = yield this.authorizeUserAndInstances(context.context, {
1346
- action: 'grantPermission',
1347
- // Resource permissions require access to the "account" marker
1348
- // because there is currently no other marker that would make sense
1349
- // for per-resource permissions.
1350
- resourceKind: 'marker',
1351
- resourceId: ACCOUNT_MARKER,
1352
- markers: [ACCOUNT_MARKER],
1353
- userId: request.userId,
1354
- instances: request.instances,
1355
- });
1356
- if (authorization.success === false) {
1357
- return authorization;
1358
- }
1359
- const recordName = context.context.recordName;
1360
- const assignmentResult = yield this._policies.assignPermissionToSubjectAndResource(recordName, request.permission.subjectType, request.permission.subjectId, request.permission.resourceKind, request.permission.resourceId, request.permission.action, request.permission.options, request.permission.expireTimeMs);
1361
- if (assignmentResult.success === false) {
1362
- return assignmentResult;
1363
- }
1364
- console.log(`[PolicyController] [grantResourcePermission] [userId: ${request.userId}, recordName: ${recordName}, subjectType: ${request.permission.subjectType}, subjectId: ${request.permission.subjectId}, resourceKind: ${(_a = request.permission.resourceKind) !== null && _a !== void 0 ? _a : '(null)'}, resourceId: ${(_b = request.permission.resourceId) !== null && _b !== void 0 ? _b : '(null)'}, action: ${(_c = request.permission.action) !== null && _c !== void 0 ? _c : '(null)'}, expireTimeMs: ${(_d = request.permission.expireTimeMs) !== null && _d !== void 0 ? _d : '(null)'}, permissionId: ${assignmentResult.permissionAssignment.id}] Granted permission for resource.`);
1442
+ }
1443
+ if (!request.permission.resourceId) {
1365
1444
  return {
1366
- success: true,
1445
+ success: false,
1446
+ errorCode: 'unacceptable_request',
1447
+ errorMessage: 'You must provide a resourceId for the permission.',
1367
1448
  };
1368
1449
  }
1369
- catch (err) {
1370
- const span = trace.getActiveSpan();
1371
- span === null || span === void 0 ? void 0 : span.recordException(err);
1372
- span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
1373
- console.error('[PolicyController] A server error occurred while granting a resource permission.', err);
1450
+ else if (!request.permission.resourceKind) {
1374
1451
  return {
1375
1452
  success: false,
1376
- errorCode: 'server_error',
1377
- errorMessage: 'A server error occurred.',
1453
+ errorCode: 'unacceptable_request',
1454
+ errorMessage: 'You must provide a resourceKind for the permission.',
1378
1455
  };
1379
1456
  }
1380
- });
1457
+ const authorization = await this.authorizeUserAndInstances(context.context, {
1458
+ action: 'grantPermission',
1459
+ // Resource permissions require access to the "account" marker
1460
+ // because there is currently no other marker that would make sense
1461
+ // for per-resource permissions.
1462
+ resourceKind: 'marker',
1463
+ resourceId: ACCOUNT_MARKER,
1464
+ markers: [ACCOUNT_MARKER],
1465
+ userId: request.userId,
1466
+ instances: request.instances,
1467
+ });
1468
+ if (authorization.success === false) {
1469
+ return authorization;
1470
+ }
1471
+ const recordName = context.context.recordName;
1472
+ const assignmentResult = await this._policies.assignPermissionToSubjectAndResource(recordName, request.permission.subjectType, request.permission.subjectId, request.permission.resourceKind, request.permission.resourceId, request.permission.action, request.permission.options, request.permission.expireTimeMs);
1473
+ if (assignmentResult.success === false) {
1474
+ return assignmentResult;
1475
+ }
1476
+ console.log(`[PolicyController] [grantResourcePermission] [userId: ${request.userId}, recordName: ${recordName}, subjectType: ${request.permission.subjectType}, subjectId: ${request.permission.subjectId}, resourceKind: ${(_a = request.permission.resourceKind) !== null && _a !== void 0 ? _a : '(null)'}, resourceId: ${(_b = request.permission.resourceId) !== null && _b !== void 0 ? _b : '(null)'}, action: ${(_c = request.permission.action) !== null && _c !== void 0 ? _c : '(null)'}, expireTimeMs: ${(_d = request.permission.expireTimeMs) !== null && _d !== void 0 ? _d : '(null)'}, permissionId: ${assignmentResult.permissionAssignment.id}] Granted permission for resource.`);
1477
+ return {
1478
+ success: true,
1479
+ };
1480
+ }
1481
+ catch (err) {
1482
+ const span = trace.getActiveSpan();
1483
+ span === null || span === void 0 ? void 0 : span.recordException(err);
1484
+ span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
1485
+ console.error('[PolicyController] A server error occurred while granting a resource permission.', err);
1486
+ return {
1487
+ success: false,
1488
+ errorCode: 'server_error',
1489
+ errorMessage: 'A server error occurred.',
1490
+ };
1491
+ }
1381
1492
  }
1382
1493
  /**
1383
1494
  * Attempts to revoke a permission from a resource.
1384
1495
  * @param request The request for the operation.
1385
1496
  */
1386
- revokeResourcePermission(request) {
1387
- return __awaiter(this, void 0, void 0, function* () {
1388
- try {
1389
- const permission = yield this._policies.getResourcePermissionAssignmentById(request.permissionId);
1390
- if (!permission) {
1391
- return {
1392
- success: false,
1393
- errorCode: 'permission_not_found',
1394
- errorMessage: 'The permission was not found.',
1395
- };
1396
- }
1397
- const baseRequest = {
1398
- recordKeyOrRecordName: permission.recordName,
1399
- userId: request.userId,
1400
- };
1401
- const context = yield this.constructAuthorizationContext(baseRequest);
1402
- if (context.success === false) {
1403
- return {
1404
- success: false,
1405
- errorCode: context.errorCode,
1406
- errorMessage: context.errorMessage,
1407
- };
1408
- }
1409
- const authorization = yield this.authorizeUserAndInstances(context.context, {
1410
- action: 'revokePermission',
1411
- resourceKind: 'marker',
1412
- resourceId: ACCOUNT_MARKER,
1413
- markers: [ACCOUNT_MARKER],
1414
- userId: request.userId,
1415
- instances: request.instances,
1416
- });
1417
- if (authorization.success === false) {
1418
- return authorization;
1419
- }
1420
- const deleteResult = yield this._policies.deleteResourcePermissionAssignmentById(permission.id);
1421
- if (!deleteResult.success) {
1422
- return deleteResult;
1423
- }
1424
- console.log(`[PolicyController] [revokeResourcePermission] [userId: ${request.userId}, permissionId: ${request.permissionId}] Revoked resource permission.`);
1497
+ async revokeResourcePermission(request) {
1498
+ try {
1499
+ const permission = await this._policies.getResourcePermissionAssignmentById(request.permissionId);
1500
+ if (!permission) {
1425
1501
  return {
1426
- success: true,
1502
+ success: false,
1503
+ errorCode: 'permission_not_found',
1504
+ errorMessage: 'The permission was not found.',
1427
1505
  };
1428
1506
  }
1429
- catch (err) {
1430
- const span = trace.getActiveSpan();
1431
- span === null || span === void 0 ? void 0 : span.recordException(err);
1432
- span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
1433
- console.error('[PolicyController] A server error occurred while revoking a resource permission.', err);
1507
+ const baseRequest = {
1508
+ recordKeyOrRecordName: permission.recordName,
1509
+ userId: request.userId,
1510
+ };
1511
+ const context = await this.constructAuthorizationContext(baseRequest);
1512
+ if (context.success === false) {
1434
1513
  return {
1435
1514
  success: false,
1436
- errorCode: 'server_error',
1437
- errorMessage: 'A server error occurred.',
1515
+ errorCode: context.errorCode,
1516
+ errorMessage: context.errorMessage,
1438
1517
  };
1439
1518
  }
1440
- });
1441
- }
1442
- /**
1443
- * Attempts to revoke the permission with the given ID.
1444
- * @param request The request for the operation.
1445
- */
1446
- revokePermission(request) {
1447
- return __awaiter(this, void 0, void 0, function* () {
1448
- try {
1449
- const markerResult = yield this.revokeMarkerPermission(request);
1450
- if (markerResult.success === false &&
1451
- markerResult.errorCode === 'permission_not_found') {
1452
- return yield this.revokeResourcePermission(request);
1453
- }
1454
- return markerResult;
1519
+ const authorization = await this.authorizeUserAndInstances(context.context, {
1520
+ action: 'revokePermission',
1521
+ resourceKind: 'marker',
1522
+ resourceId: ACCOUNT_MARKER,
1523
+ markers: [ACCOUNT_MARKER],
1524
+ userId: request.userId,
1525
+ instances: request.instances,
1526
+ });
1527
+ if (authorization.success === false) {
1528
+ return authorization;
1455
1529
  }
1456
- catch (err) {
1457
- const span = trace.getActiveSpan();
1458
- span === null || span === void 0 ? void 0 : span.recordException(err);
1459
- span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
1460
- console.error('[PolicyController] A server error occurred while revoking a permission.', err);
1461
- return {
1462
- success: false,
1463
- errorCode: 'server_error',
1464
- errorMessage: 'A server error occurred.',
1465
- };
1530
+ const deleteResult = await this._policies.deleteResourcePermissionAssignmentById(permission.id);
1531
+ if (!deleteResult.success) {
1532
+ return deleteResult;
1466
1533
  }
1467
- });
1534
+ console.log(`[PolicyController] [revokeResourcePermission] [userId: ${request.userId}, permissionId: ${request.permissionId}] Revoked resource permission.`);
1535
+ return {
1536
+ success: true,
1537
+ };
1538
+ }
1539
+ catch (err) {
1540
+ const span = trace.getActiveSpan();
1541
+ span === null || span === void 0 ? void 0 : span.recordException(err);
1542
+ span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
1543
+ console.error('[PolicyController] A server error occurred while revoking a resource permission.', err);
1544
+ return {
1545
+ success: false,
1546
+ errorCode: 'server_error',
1547
+ errorMessage: 'A server error occurred.',
1548
+ };
1549
+ }
1468
1550
  }
1469
1551
  /**
1470
- * Attempts to list the roles that are assigned to a user.
1471
- * @param recordKeyOrRecordName The record key or the name of the record.
1472
- * @param userId The ID of the user that is currently logged in.
1473
- * @param subjectId The ID of the user whose roles should be listed.
1474
- * @param instances The instances that the request is being made from.
1475
- */
1476
- listUserRoles(recordKeyOrRecordName, userId, subjectId, instances) {
1477
- return __awaiter(this, void 0, void 0, function* () {
1478
- try {
1479
- const baseRequest = {
1480
- recordKeyOrRecordName: recordKeyOrRecordName,
1481
- userId: userId,
1482
- };
1483
- const context = yield this.constructAuthorizationContext(baseRequest);
1484
- if (context.success === false) {
1485
- return {
1486
- success: false,
1487
- errorCode: context.errorCode,
1488
- errorMessage: context.errorMessage,
1489
- };
1490
- }
1491
- if (userId !== subjectId || (!!instances && instances.length > 0)) {
1492
- const authorization = yield this.authorizeUserAndInstances(context.context, {
1493
- resourceKind: 'role',
1494
- action: 'list',
1495
- markers: [ACCOUNT_MARKER],
1496
- userId: userId,
1497
- instances: instances,
1498
- });
1499
- if (authorization.success === false) {
1500
- return authorization;
1501
- }
1502
- }
1503
- const result = yield this._policies.listRolesForUser(context.context.recordName, subjectId);
1504
- return {
1505
- success: true,
1506
- roles: sortBy(result, (r) => r.role),
1507
- };
1508
- }
1509
- catch (err) {
1510
- const span = trace.getActiveSpan();
1511
- span === null || span === void 0 ? void 0 : span.recordException(err);
1512
- span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
1513
- console.error('[PolicyController] A server error occurred.', err);
1514
- return {
1515
- success: false,
1516
- errorCode: 'server_error',
1517
- errorMessage: 'A server error occurred.',
1518
- };
1552
+ * Attempts to revoke the permission with the given ID.
1553
+ * @param request The request for the operation.
1554
+ */
1555
+ async revokePermission(request) {
1556
+ try {
1557
+ const markerResult = await this.revokeMarkerPermission(request);
1558
+ if (markerResult.success === false &&
1559
+ markerResult.errorCode === 'permission_not_found') {
1560
+ return await this.revokeResourcePermission(request);
1519
1561
  }
1520
- });
1562
+ return markerResult;
1563
+ }
1564
+ catch (err) {
1565
+ const span = trace.getActiveSpan();
1566
+ span === null || span === void 0 ? void 0 : span.recordException(err);
1567
+ span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
1568
+ console.error('[PolicyController] A server error occurred while revoking a permission.', err);
1569
+ return {
1570
+ success: false,
1571
+ errorCode: 'server_error',
1572
+ errorMessage: 'A server error occurred.',
1573
+ };
1574
+ }
1521
1575
  }
1522
1576
  /**
1523
- * Attempts to list the roles that are assigned to an inst.
1577
+ * Attempts to list the roles that are assigned to a user.
1524
1578
  * @param recordKeyOrRecordName The record key or the name of the record.
1525
1579
  * @param userId The ID of the user that is currently logged in.
1526
- * @param subjectId The ID of the inst whose roles should be listed.
1580
+ * @param subjectId The ID of the user whose roles should be listed.
1527
1581
  * @param instances The instances that the request is being made from.
1528
1582
  */
1529
- listInstRoles(recordKeyOrRecordName, userId, subjectId, instances) {
1530
- return __awaiter(this, void 0, void 0, function* () {
1531
- try {
1532
- const baseRequest = {
1533
- recordKeyOrRecordName: recordKeyOrRecordName,
1534
- userId: userId,
1583
+ async listUserRoles(recordKeyOrRecordName, userId, subjectId, instances) {
1584
+ try {
1585
+ const baseRequest = {
1586
+ recordKeyOrRecordName: recordKeyOrRecordName,
1587
+ userId: userId,
1588
+ };
1589
+ const context = await this.constructAuthorizationContext(baseRequest);
1590
+ if (context.success === false) {
1591
+ return {
1592
+ success: false,
1593
+ errorCode: context.errorCode,
1594
+ errorMessage: context.errorMessage,
1535
1595
  };
1536
- const context = yield this.constructAuthorizationContext(baseRequest);
1537
- if (context.success === false) {
1538
- return {
1539
- success: false,
1540
- errorCode: context.errorCode,
1541
- errorMessage: context.errorMessage,
1542
- };
1543
- }
1544
- const authorization = yield this.authorizeUserAndInstances(context.context, {
1596
+ }
1597
+ if (userId !== subjectId || (!!instances && instances.length > 0)) {
1598
+ const authorization = await this.authorizeUserAndInstances(context.context, {
1545
1599
  resourceKind: 'role',
1546
1600
  action: 'list',
1547
1601
  markers: [ACCOUNT_MARKER],
@@ -1551,24 +1605,73 @@ export class PolicyController {
1551
1605
  if (authorization.success === false) {
1552
1606
  return authorization;
1553
1607
  }
1554
- const result = yield this._policies.listRolesForInst(context.context.recordName, normalizeInstId(subjectId));
1555
- return {
1556
- success: true,
1557
- roles: sortBy(result, (r) => r.role),
1558
- };
1559
1608
  }
1560
- catch (err) {
1561
- const span = trace.getActiveSpan();
1562
- span === null || span === void 0 ? void 0 : span.recordException(err);
1563
- span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
1564
- console.error('[PolicyController] A server error occurred.', err);
1609
+ const result = await this._policies.listRolesForUser(context.context.recordName, subjectId);
1610
+ return {
1611
+ success: true,
1612
+ roles: sortBy(result, (r) => r.role),
1613
+ };
1614
+ }
1615
+ catch (err) {
1616
+ const span = trace.getActiveSpan();
1617
+ span === null || span === void 0 ? void 0 : span.recordException(err);
1618
+ span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
1619
+ console.error('[PolicyController] A server error occurred.', err);
1620
+ return {
1621
+ success: false,
1622
+ errorCode: 'server_error',
1623
+ errorMessage: 'A server error occurred.',
1624
+ };
1625
+ }
1626
+ }
1627
+ /**
1628
+ * Attempts to list the roles that are assigned to an inst.
1629
+ * @param recordKeyOrRecordName The record key or the name of the record.
1630
+ * @param userId The ID of the user that is currently logged in.
1631
+ * @param subjectId The ID of the inst whose roles should be listed.
1632
+ * @param instances The instances that the request is being made from.
1633
+ */
1634
+ async listInstRoles(recordKeyOrRecordName, userId, subjectId, instances) {
1635
+ try {
1636
+ const baseRequest = {
1637
+ recordKeyOrRecordName: recordKeyOrRecordName,
1638
+ userId: userId,
1639
+ };
1640
+ const context = await this.constructAuthorizationContext(baseRequest);
1641
+ if (context.success === false) {
1565
1642
  return {
1566
1643
  success: false,
1567
- errorCode: 'server_error',
1568
- errorMessage: 'A server error occurred.',
1644
+ errorCode: context.errorCode,
1645
+ errorMessage: context.errorMessage,
1569
1646
  };
1570
1647
  }
1571
- });
1648
+ const authorization = await this.authorizeUserAndInstances(context.context, {
1649
+ resourceKind: 'role',
1650
+ action: 'list',
1651
+ markers: [ACCOUNT_MARKER],
1652
+ userId: userId,
1653
+ instances: instances,
1654
+ });
1655
+ if (authorization.success === false) {
1656
+ return authorization;
1657
+ }
1658
+ const result = await this._policies.listRolesForInst(context.context.recordName, normalizeInstId(subjectId));
1659
+ return {
1660
+ success: true,
1661
+ roles: sortBy(result, (r) => r.role),
1662
+ };
1663
+ }
1664
+ catch (err) {
1665
+ const span = trace.getActiveSpan();
1666
+ span === null || span === void 0 ? void 0 : span.recordException(err);
1667
+ span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
1668
+ console.error('[PolicyController] A server error occurred.', err);
1669
+ return {
1670
+ success: false,
1671
+ errorCode: 'server_error',
1672
+ errorMessage: 'A server error occurred.',
1673
+ };
1674
+ }
1572
1675
  }
1573
1676
  /**
1574
1677
  * Attempts to list the entities that are assigned the given role.
@@ -1577,49 +1680,47 @@ export class PolicyController {
1577
1680
  * @param role The name of the role whose assigments should be listed.
1578
1681
  * @param instances The instances that the request is being made from.
1579
1682
  */
1580
- listAssignedRoles(recordKeyOrRecordName, userId, role, instances) {
1581
- return __awaiter(this, void 0, void 0, function* () {
1582
- try {
1583
- const baseRequest = {
1584
- recordKeyOrRecordName: recordKeyOrRecordName,
1585
- userId: userId,
1586
- };
1587
- const context = yield this.constructAuthorizationContext(baseRequest);
1588
- if (context.success === false) {
1589
- return {
1590
- success: false,
1591
- errorCode: context.errorCode,
1592
- errorMessage: context.errorMessage,
1593
- };
1594
- }
1595
- const authorization = yield this.authorizeUserAndInstances(context.context, {
1596
- resourceKind: 'role',
1597
- action: 'list',
1598
- markers: [ACCOUNT_MARKER],
1599
- userId: userId,
1600
- instances: instances,
1601
- });
1602
- if (authorization.success === false) {
1603
- return authorization;
1604
- }
1605
- const result = yield this._policies.listAssignmentsForRole(context.context.recordName, role);
1606
- return {
1607
- success: true,
1608
- assignments: result.assignments,
1609
- };
1610
- }
1611
- catch (err) {
1612
- const span = trace.getActiveSpan();
1613
- span === null || span === void 0 ? void 0 : span.recordException(err);
1614
- span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
1615
- console.error('[PolicyController] A server error occurred.', err);
1683
+ async listAssignedRoles(recordKeyOrRecordName, userId, role, instances) {
1684
+ try {
1685
+ const baseRequest = {
1686
+ recordKeyOrRecordName: recordKeyOrRecordName,
1687
+ userId: userId,
1688
+ };
1689
+ const context = await this.constructAuthorizationContext(baseRequest);
1690
+ if (context.success === false) {
1616
1691
  return {
1617
1692
  success: false,
1618
- errorCode: 'server_error',
1619
- errorMessage: 'A server error occurred.',
1693
+ errorCode: context.errorCode,
1694
+ errorMessage: context.errorMessage,
1620
1695
  };
1621
1696
  }
1622
- });
1697
+ const authorization = await this.authorizeUserAndInstances(context.context, {
1698
+ resourceKind: 'role',
1699
+ action: 'list',
1700
+ markers: [ACCOUNT_MARKER],
1701
+ userId: userId,
1702
+ instances: instances,
1703
+ });
1704
+ if (authorization.success === false) {
1705
+ return authorization;
1706
+ }
1707
+ const result = await this._policies.listAssignmentsForRole(context.context.recordName, role);
1708
+ return {
1709
+ success: true,
1710
+ assignments: result.assignments,
1711
+ };
1712
+ }
1713
+ catch (err) {
1714
+ const span = trace.getActiveSpan();
1715
+ span === null || span === void 0 ? void 0 : span.recordException(err);
1716
+ span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
1717
+ console.error('[PolicyController] A server error occurred.', err);
1718
+ return {
1719
+ success: false,
1720
+ errorCode: 'server_error',
1721
+ errorMessage: 'A server error occurred.',
1722
+ };
1723
+ }
1623
1724
  }
1624
1725
  /**
1625
1726
  * Lists the role assignments that have been made in the given record.
@@ -1628,57 +1729,55 @@ export class PolicyController {
1628
1729
  * @param startingRole The role that assignments should be returned after.
1629
1730
  * @param instances The instances that the request is being made from.
1630
1731
  */
1631
- listRoleAssignments(recordKeyOrRecordName, userId, startingRole, instances) {
1632
- return __awaiter(this, void 0, void 0, function* () {
1633
- try {
1634
- if (!this._policies.listAssignments) {
1635
- return {
1636
- success: false,
1637
- errorCode: 'not_supported',
1638
- errorMessage: 'This operation is not supported.',
1639
- };
1640
- }
1641
- const baseRequest = {
1642
- recordKeyOrRecordName: recordKeyOrRecordName,
1643
- userId: userId,
1644
- };
1645
- const context = yield this.constructAuthorizationContext(baseRequest);
1646
- if (context.success === false) {
1647
- return {
1648
- success: false,
1649
- errorCode: context.errorCode,
1650
- errorMessage: context.errorMessage,
1651
- };
1652
- }
1653
- const authorization = yield this.authorizeUserAndInstances(context.context, {
1654
- resourceKind: 'role',
1655
- action: 'list',
1656
- markers: [ACCOUNT_MARKER],
1657
- userId: userId,
1658
- instances: instances,
1659
- });
1660
- if (authorization.success === false) {
1661
- return authorization;
1662
- }
1663
- const result = yield this._policies.listAssignments(context.context.recordName, startingRole);
1732
+ async listRoleAssignments(recordKeyOrRecordName, userId, startingRole, instances) {
1733
+ try {
1734
+ if (!this._policies.listAssignments) {
1664
1735
  return {
1665
- success: true,
1666
- assignments: result.assignments,
1667
- totalCount: result.totalCount,
1736
+ success: false,
1737
+ errorCode: 'not_supported',
1738
+ errorMessage: 'This operation is not supported.',
1668
1739
  };
1669
1740
  }
1670
- catch (err) {
1671
- const span = trace.getActiveSpan();
1672
- span === null || span === void 0 ? void 0 : span.recordException(err);
1673
- span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
1674
- console.error('[PolicyController] A server error occurred.', err);
1741
+ const baseRequest = {
1742
+ recordKeyOrRecordName: recordKeyOrRecordName,
1743
+ userId: userId,
1744
+ };
1745
+ const context = await this.constructAuthorizationContext(baseRequest);
1746
+ if (context.success === false) {
1675
1747
  return {
1676
1748
  success: false,
1677
- errorCode: 'server_error',
1678
- errorMessage: 'A server error occurred.',
1749
+ errorCode: context.errorCode,
1750
+ errorMessage: context.errorMessage,
1679
1751
  };
1680
1752
  }
1681
- });
1753
+ const authorization = await this.authorizeUserAndInstances(context.context, {
1754
+ resourceKind: 'role',
1755
+ action: 'list',
1756
+ markers: [ACCOUNT_MARKER],
1757
+ userId: userId,
1758
+ instances: instances,
1759
+ });
1760
+ if (authorization.success === false) {
1761
+ return authorization;
1762
+ }
1763
+ const result = await this._policies.listAssignments(context.context.recordName, startingRole);
1764
+ return {
1765
+ success: true,
1766
+ assignments: result.assignments,
1767
+ totalCount: result.totalCount,
1768
+ };
1769
+ }
1770
+ catch (err) {
1771
+ const span = trace.getActiveSpan();
1772
+ span === null || span === void 0 ? void 0 : span.recordException(err);
1773
+ span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
1774
+ console.error('[PolicyController] A server error occurred.', err);
1775
+ return {
1776
+ success: false,
1777
+ errorCode: 'server_error',
1778
+ errorMessage: 'A server error occurred.',
1779
+ };
1780
+ }
1682
1781
  }
1683
1782
  /**
1684
1783
  * Attempts to grant a role to a user.
@@ -1687,78 +1786,76 @@ export class PolicyController {
1687
1786
  * @param request The request to grant the role.
1688
1787
  * @param instances The instances that the request is being made from.
1689
1788
  */
1690
- grantRole(recordKeyOrRecordName, userId, request, instances) {
1691
- return __awaiter(this, void 0, void 0, function* () {
1692
- try {
1693
- const baseRequest = {
1694
- recordKeyOrRecordName: recordKeyOrRecordName,
1695
- userId: userId,
1789
+ async grantRole(recordKeyOrRecordName, userId, request, instances) {
1790
+ try {
1791
+ const baseRequest = {
1792
+ recordKeyOrRecordName: recordKeyOrRecordName,
1793
+ userId: userId,
1794
+ };
1795
+ const context = await this.constructAuthorizationContext(baseRequest);
1796
+ if (context.success === false) {
1797
+ return {
1798
+ success: false,
1799
+ errorCode: context.errorCode,
1800
+ errorMessage: context.errorMessage,
1696
1801
  };
1697
- const context = yield this.constructAuthorizationContext(baseRequest);
1698
- if (context.success === false) {
1699
- return {
1700
- success: false,
1701
- errorCode: context.errorCode,
1702
- errorMessage: context.errorMessage,
1703
- };
1704
- }
1705
- const recordName = context.context.recordName;
1706
- const targetUserId = request.userId;
1707
- const targetInstance = normalizeInstId(request.instance);
1708
- const expireTimeMs = getExpireTime(request.expireTimeMs);
1709
- const authorization = yield this.authorizeUserAndInstances(context.context, {
1710
- resourceKind: 'role',
1711
- action: 'grant',
1712
- resourceId: request.role,
1713
- markers: [ACCOUNT_MARKER],
1714
- userId: userId,
1715
- instances: instances,
1802
+ }
1803
+ const recordName = context.context.recordName;
1804
+ const targetUserId = request.userId;
1805
+ const targetInstance = normalizeInstId(request.instance);
1806
+ const expireTimeMs = getExpireTime(request.expireTimeMs);
1807
+ const authorization = await this.authorizeUserAndInstances(context.context, {
1808
+ resourceKind: 'role',
1809
+ action: 'grant',
1810
+ resourceId: request.role,
1811
+ markers: [ACCOUNT_MARKER],
1812
+ userId: userId,
1813
+ instances: instances,
1814
+ });
1815
+ if (authorization.success === false) {
1816
+ return authorization;
1817
+ }
1818
+ if (targetUserId) {
1819
+ const result = await this._policies.assignSubjectRole(recordName, targetUserId, 'user', {
1820
+ role: request.role,
1821
+ expireTimeMs,
1716
1822
  });
1717
- if (authorization.success === false) {
1718
- return authorization;
1719
- }
1720
- if (targetUserId) {
1721
- const result = yield this._policies.assignSubjectRole(recordName, targetUserId, 'user', {
1722
- role: request.role,
1723
- expireTimeMs,
1724
- });
1725
- if (result.success === false) {
1726
- return result;
1727
- }
1728
- return {
1729
- success: true,
1730
- };
1731
- }
1732
- else if (targetInstance) {
1733
- const result = yield this._policies.assignSubjectRole(recordName, targetInstance, 'inst', {
1734
- role: request.role,
1735
- expireTimeMs,
1736
- });
1737
- if (result.success === false) {
1738
- return result;
1739
- }
1740
- return {
1741
- success: true,
1742
- };
1823
+ if (result.success === false) {
1824
+ return result;
1743
1825
  }
1744
1826
  return {
1745
- success: false,
1746
- errorCode: 'unacceptable_request',
1747
- errorMessage: 'Either a user ID or an instance must be specified.',
1827
+ success: true,
1748
1828
  };
1749
1829
  }
1750
- catch (err) {
1751
- const span = trace.getActiveSpan();
1752
- span === null || span === void 0 ? void 0 : span.recordException(err);
1753
- span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
1754
- console.error('[PolicyController] A server error occurred.', err);
1830
+ else if (targetInstance) {
1831
+ const result = await this._policies.assignSubjectRole(recordName, targetInstance, 'inst', {
1832
+ role: request.role,
1833
+ expireTimeMs,
1834
+ });
1835
+ if (result.success === false) {
1836
+ return result;
1837
+ }
1755
1838
  return {
1756
- success: false,
1757
- errorCode: 'server_error',
1758
- errorMessage: 'A server error occurred.',
1839
+ success: true,
1759
1840
  };
1760
1841
  }
1761
- });
1842
+ return {
1843
+ success: false,
1844
+ errorCode: 'unacceptable_request',
1845
+ errorMessage: 'Either a user ID or an instance must be specified.',
1846
+ };
1847
+ }
1848
+ catch (err) {
1849
+ const span = trace.getActiveSpan();
1850
+ span === null || span === void 0 ? void 0 : span.recordException(err);
1851
+ span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
1852
+ console.error('[PolicyController] A server error occurred.', err);
1853
+ return {
1854
+ success: false,
1855
+ errorCode: 'server_error',
1856
+ errorMessage: 'A server error occurred.',
1857
+ };
1858
+ }
1762
1859
  }
1763
1860
  /**
1764
1861
  * Attempts to revoke a role from a user.
@@ -1767,71 +1864,191 @@ export class PolicyController {
1767
1864
  * @param request The request to revoke the role.
1768
1865
  * @param instances The instances that the request is being made from.
1769
1866
  */
1770
- revokeRole(recordKeyOrRecordName, userId, request, instances) {
1771
- return __awaiter(this, void 0, void 0, function* () {
1772
- try {
1773
- const baseRequest = {
1774
- recordKeyOrRecordName: recordKeyOrRecordName,
1775
- userId: userId,
1867
+ async revokeRole(recordKeyOrRecordName, userId, request, instances) {
1868
+ try {
1869
+ const baseRequest = {
1870
+ recordKeyOrRecordName: recordKeyOrRecordName,
1871
+ userId: userId,
1872
+ };
1873
+ const context = await this.constructAuthorizationContext(baseRequest);
1874
+ if (context.success === false) {
1875
+ return {
1876
+ success: false,
1877
+ errorCode: context.errorCode,
1878
+ errorMessage: context.errorMessage,
1776
1879
  };
1777
- const context = yield this.constructAuthorizationContext(baseRequest);
1778
- if (context.success === false) {
1779
- return {
1780
- success: false,
1781
- errorCode: context.errorCode,
1782
- errorMessage: context.errorMessage,
1783
- };
1880
+ }
1881
+ const recordName = context.context.recordName;
1882
+ const targetUserId = request.userId;
1883
+ const targetInstance = normalizeInstId(request.instance);
1884
+ const authorization = await this.authorizeUserAndInstances(context.context, {
1885
+ resourceKind: 'role',
1886
+ action: 'revoke',
1887
+ resourceId: request.role,
1888
+ markers: [ACCOUNT_MARKER],
1889
+ userId: userId,
1890
+ instances: instances,
1891
+ });
1892
+ if (authorization.success === false) {
1893
+ return authorization;
1894
+ }
1895
+ if (targetUserId) {
1896
+ const result = await this._policies.revokeSubjectRole(recordName, targetUserId, 'user', request.role);
1897
+ if (result.success === false) {
1898
+ return result;
1784
1899
  }
1785
- const recordName = context.context.recordName;
1786
- const targetUserId = request.userId;
1787
- const targetInstance = normalizeInstId(request.instance);
1788
- const authorization = yield this.authorizeUserAndInstances(context.context, {
1789
- resourceKind: 'role',
1790
- action: 'revoke',
1791
- resourceId: request.role,
1792
- markers: [ACCOUNT_MARKER],
1793
- userId: userId,
1794
- instances: instances,
1795
- });
1796
- if (authorization.success === false) {
1797
- return authorization;
1900
+ return {
1901
+ success: true,
1902
+ };
1903
+ }
1904
+ else if (targetInstance) {
1905
+ const result = await this._policies.revokeSubjectRole(recordName, targetInstance, 'inst', request.role);
1906
+ if (result.success === false) {
1907
+ return result;
1798
1908
  }
1799
- if (targetUserId) {
1800
- const result = yield this._policies.revokeSubjectRole(recordName, targetUserId, 'user', request.role);
1801
- if (result.success === false) {
1802
- return result;
1803
- }
1909
+ return {
1910
+ success: true,
1911
+ };
1912
+ }
1913
+ return {
1914
+ success: false,
1915
+ errorCode: 'unacceptable_request',
1916
+ errorMessage: 'Either a user ID or an instance must be specified.',
1917
+ };
1918
+ }
1919
+ catch (err) {
1920
+ const span = trace.getActiveSpan();
1921
+ span === null || span === void 0 ? void 0 : span.recordException(err);
1922
+ span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
1923
+ console.error('[PolicyController] A server error occurred.', err);
1924
+ return {
1925
+ success: false,
1926
+ errorCode: 'server_error',
1927
+ errorMessage: 'A server error occurred.',
1928
+ };
1929
+ }
1930
+ }
1931
+ /**
1932
+ * Attempts to grant an entitlement to a package.
1933
+ * @param request
1934
+ */
1935
+ async grantEntitlement(request) {
1936
+ var _a, _b, _c, _d, _e, _f, _g, _h;
1937
+ try {
1938
+ if (!isSuperUserRole(request.userRole)) {
1939
+ if (request.userId !== request.grantingUserId) {
1804
1940
  return {
1805
- success: true,
1941
+ success: false,
1942
+ errorCode: 'not_authorized',
1943
+ errorMessage: 'You are not authorized to perform this action.',
1806
1944
  };
1807
1945
  }
1808
- else if (targetInstance) {
1809
- const result = yield this._policies.revokeSubjectRole(recordName, targetInstance, 'inst', request.role);
1810
- if (result.success === false) {
1811
- return result;
1812
- }
1946
+ }
1947
+ const grant = await this._policies.findGrantedPackageEntitlementByUserIdPackageIdFeatureAndScope(request.grantingUserId, request.packageId, request.feature, request.scope, request.recordName);
1948
+ const grantId = (_a = grant === null || grant === void 0 ? void 0 : grant.id) !== null && _a !== void 0 ? _a : uuidv7();
1949
+ const feature = (_b = grant === null || grant === void 0 ? void 0 : grant.feature) !== null && _b !== void 0 ? _b : request.feature;
1950
+ await this._policies.saveGrantedPackageEntitlement({
1951
+ id: grantId,
1952
+ createdAtMs: (_c = grant === null || grant === void 0 ? void 0 : grant.createdAtMs) !== null && _c !== void 0 ? _c : Date.now(),
1953
+ expireTimeMs: Math.max(request.expireTimeMs, (_d = grant === null || grant === void 0 ? void 0 : grant.expireTimeMs) !== null && _d !== void 0 ? _d : 0),
1954
+ revokeTimeMs: null,
1955
+ scope: (_e = grant === null || grant === void 0 ? void 0 : grant.scope) !== null && _e !== void 0 ? _e : request.scope,
1956
+ packageId: (_f = grant === null || grant === void 0 ? void 0 : grant.packageId) !== null && _f !== void 0 ? _f : request.packageId,
1957
+ userId: (_g = grant === null || grant === void 0 ? void 0 : grant.userId) !== null && _g !== void 0 ? _g : request.grantingUserId,
1958
+ feature: feature,
1959
+ recordName: (_h = grant === null || grant === void 0 ? void 0 : grant.recordName) !== null && _h !== void 0 ? _h : request.recordName,
1960
+ });
1961
+ return {
1962
+ success: true,
1963
+ grantId,
1964
+ feature,
1965
+ };
1966
+ }
1967
+ catch (err) {
1968
+ const span = trace.getActiveSpan();
1969
+ span === null || span === void 0 ? void 0 : span.recordException(err);
1970
+ span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
1971
+ console.error('[PolicyController] A server error occurred.', err);
1972
+ return {
1973
+ success: false,
1974
+ errorCode: 'server_error',
1975
+ errorMessage: 'A server error occurred.',
1976
+ };
1977
+ }
1978
+ }
1979
+ async revokeEntitlement(request) {
1980
+ try {
1981
+ const grant = await this._policies.findGrantedPackageEntitlementById(request.grantId);
1982
+ if (!grant) {
1983
+ return {
1984
+ success: false,
1985
+ errorCode: 'not_found',
1986
+ errorMessage: 'The entitlement grant could not be found.',
1987
+ };
1988
+ }
1989
+ if (grant.userId !== request.userId) {
1990
+ if (!isSuperUserRole(request.userRole)) {
1813
1991
  return {
1814
- success: true,
1992
+ success: false,
1993
+ errorCode: 'not_authorized',
1994
+ errorMessage: 'You are not authorized to perform this action.',
1815
1995
  };
1816
1996
  }
1997
+ }
1998
+ if (grant.revokeTimeMs !== null) {
1999
+ // Already revoked
1817
2000
  return {
1818
- success: false,
1819
- errorCode: 'unacceptable_request',
1820
- errorMessage: 'Either a user ID or an instance must be specified.',
2001
+ success: true,
1821
2002
  };
1822
2003
  }
1823
- catch (err) {
1824
- const span = trace.getActiveSpan();
1825
- span === null || span === void 0 ? void 0 : span.recordException(err);
1826
- span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
1827
- console.error('[PolicyController] A server error occurred.', err);
2004
+ await this._policies.saveGrantedPackageEntitlement({
2005
+ ...grant,
2006
+ revokeTimeMs: Date.now(),
2007
+ });
2008
+ return {
2009
+ success: true,
2010
+ };
2011
+ }
2012
+ catch (err) {
2013
+ const span = trace.getActiveSpan();
2014
+ span === null || span === void 0 ? void 0 : span.recordException(err);
2015
+ span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
2016
+ console.error('[PolicyController] A server error occurred.', err);
2017
+ return {
2018
+ success: false,
2019
+ errorCode: 'server_error',
2020
+ errorMessage: 'A server error occurred.',
2021
+ };
2022
+ }
2023
+ }
2024
+ async listGrantedEntitlements(request) {
2025
+ try {
2026
+ if (!request.packageId) {
2027
+ const grants = await this._policies.listGrantedEntitlementsForUser(request.userId, Date.now());
1828
2028
  return {
1829
- success: false,
1830
- errorCode: 'server_error',
1831
- errorMessage: 'A server error occurred.',
2029
+ success: true,
2030
+ grants,
1832
2031
  };
1833
2032
  }
1834
- });
2033
+ else {
2034
+ const grants = await this._policies.listGrantedEntitlementsForUserAndPackage(request.userId, request.packageId, Date.now());
2035
+ return {
2036
+ success: true,
2037
+ grants,
2038
+ };
2039
+ }
2040
+ }
2041
+ catch (err) {
2042
+ const span = trace.getActiveSpan();
2043
+ span === null || span === void 0 ? void 0 : span.recordException(err);
2044
+ span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
2045
+ console.error('[PolicyController] A server error occurred.', err);
2046
+ return {
2047
+ success: false,
2048
+ errorCode: 'server_error',
2049
+ errorMessage: 'A server error occurred.',
2050
+ };
2051
+ }
1835
2052
  }
1836
2053
  }
1837
2054
  __decorate([
@@ -1897,6 +2114,15 @@ __decorate([
1897
2114
  __decorate([
1898
2115
  traced(TRACE_NAME)
1899
2116
  ], PolicyController.prototype, "revokeRole", null);
2117
+ __decorate([
2118
+ traced(TRACE_NAME)
2119
+ ], PolicyController.prototype, "grantEntitlement", null);
2120
+ __decorate([
2121
+ traced(TRACE_NAME)
2122
+ ], PolicyController.prototype, "revokeEntitlement", null);
2123
+ __decorate([
2124
+ traced(TRACE_NAME)
2125
+ ], PolicyController.prototype, "listGrantedEntitlements", null);
1900
2126
  /**
1901
2127
  * Determines if any markers will be remaining after the removal and addition of the specified markers.
1902
2128
  * @param existingMarkers The markers that already exist.
@@ -1939,4 +2165,25 @@ export function explainationForPermissionAssignment(subjectType, permissionAssig
1939
2165
  }
1940
2166
  return permissionString;
1941
2167
  }
2168
+ function getEntitlementFeatureForAction(resourceKind, action) {
2169
+ if (resourceKind === 'data' ||
2170
+ resourceKind === 'file' ||
2171
+ resourceKind === 'event' ||
2172
+ resourceKind === 'inst' ||
2173
+ resourceKind === 'notification' ||
2174
+ resourceKind === 'package' ||
2175
+ resourceKind === 'webhook') {
2176
+ return resourceKind;
2177
+ }
2178
+ else if (resourceKind === 'ai.hume' || resourceKind === 'ai.sloyd') {
2179
+ return 'ai';
2180
+ }
2181
+ else if (resourceKind === 'marker' || resourceKind === 'role') {
2182
+ return 'permissions';
2183
+ }
2184
+ else if (resourceKind === 'package.version') {
2185
+ return 'package';
2186
+ }
2187
+ return null;
2188
+ }
1942
2189
  //# sourceMappingURL=PolicyController.js.map