@casual-simulation/aux-records 3.4.6-alpha.14668890889 → 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,36 +4,16 @@ 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
- var __rest = (this && this.__rest) || function (s, e) {
17
- var t = {};
18
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
19
- t[p] = s[p];
20
- if (s != null && typeof Object.getOwnPropertySymbols === "function")
21
- for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
22
- if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
23
- t[p[i]] = s[p[i]];
24
- }
25
- return t;
26
- };
27
- import { toBase64String, fromBase64String, } from '@casual-simulation/aux-common';
28
7
  import { hashHighEntropyPasswordWithSalt, hashLowEntropyPasswordWithSalt, } from './InstrumentedHashHelpers';
29
8
  import { randomBytes } from 'tweetnacl';
30
9
  import { fromByteArray } from 'base64-js';
31
10
  import { v4 as uuid } from 'uuid';
32
11
  import { getComIdFeatures, getHumeAiFeatures, getLoomFeatures, getSubscriptionFeatures, getSubscriptionTier, } from './SubscriptionConfiguration';
33
12
  import { isActiveSubscription } from './Utils';
34
- import { isSuperUserRole } from './AuthUtils';
13
+ import { isSuperUserRole } from '@casual-simulation/aux-common';
35
14
  import { traced } from './tracing/TracingDecorators';
36
15
  import { SpanStatusCode, trace } from '@opentelemetry/api';
16
+ import { DEFAULT_RECORD_KEY_POLICY, formatV2RecordKey, parseRecordKey, } from '@casual-simulation/aux-common/records/RecordKeys';
37
17
  const TRACE_NAME = 'RecordsController';
38
18
  /**
39
19
  * Defines a class that manages records and their keys.
@@ -51,149 +31,151 @@ export class RecordsController {
51
31
  * Creates a new record.
52
32
  * @param request The request that should be used to create the record.
53
33
  */
54
- createRecord(request) {
55
- return __awaiter(this, void 0, void 0, function* () {
56
- try {
57
- if (!request.userId) {
58
- return {
59
- success: false,
60
- errorCode: 'not_logged_in',
61
- errorMessage: 'The user must be logged in in order to create a record.',
62
- };
63
- }
64
- const record = yield this._store.getRecordByName(request.recordName);
65
- if (record) {
66
- if (record.name === request.userId &&
67
- record.ownerId !== request.userId &&
68
- request.ownerId === request.userId) {
69
- const allowed = yield this._doesSubscriptionAllowToCreateRecord({
70
- ownerId: request.userId,
71
- });
72
- if (!allowed.success) {
73
- return allowed;
74
- }
75
- console.log(`[RecordsController] [action: record.create recordName: ${record.name}, userId: ${request.userId}] Fixing record owner to match actual owner.`);
76
- record.ownerId = request.userId;
77
- record.studioId = null;
78
- // Clear the hashes and re-create the salt so that access to the record is revoked for any record key that was created before.
79
- record.secretHashes = [];
80
- record.secretSalt = this._createSalt();
81
- yield this._store.updateRecord(Object.assign({}, record));
82
- return {
83
- success: true,
84
- };
85
- }
86
- let existingStudioMembers = yield this._store.listStudioAssignments(record.name);
87
- if (existingStudioMembers.length > 0 &&
88
- record.studioId !== record.name &&
89
- request.studioId === record.name) {
90
- const allowed = yield this._doesSubscriptionAllowToCreateRecord({
91
- studioId: request.studioId,
92
- });
93
- if (!allowed.success) {
94
- return allowed;
95
- }
96
- console.log(`[RecordsController] [action: record.create recordName: ${record.name}, userId: ${request.userId}, studioId: ${request.studioId}] Fixing record owner to match actual owner.`);
97
- record.ownerId = null;
98
- record.studioId = request.studioId;
99
- // Clear the hashes and re-create the salt so that access to the record is revoked for any record key that was created before.
100
- record.secretHashes = [];
101
- record.secretSalt = this._createSalt();
102
- yield this._store.updateRecord(Object.assign({}, record));
103
- return {
104
- success: true,
105
- };
106
- }
107
- return {
108
- success: false,
109
- errorCode: 'record_already_exists',
110
- errorMessage: 'A record with that name already exists.',
111
- };
112
- }
113
- if (request.recordName !== request.ownerId &&
114
- request.recordName !== request.studioId) {
115
- const existingUser = yield this._auth.findUser(request.recordName);
116
- if (existingUser) {
117
- return {
118
- success: false,
119
- errorCode: 'record_already_exists',
120
- errorMessage: 'A record with that name already exists.',
121
- };
122
- }
123
- }
124
- if (!request.ownerId && !request.studioId) {
125
- return {
126
- success: false,
127
- errorCode: 'unacceptable_request',
128
- errorMessage: 'You must provide an owner ID or a studio ID.',
129
- };
130
- }
131
- if (request.ownerId) {
132
- if (request.ownerId !== request.userId) {
133
- return {
134
- success: false,
135
- errorCode: 'not_authorized',
136
- errorMessage: 'You are not authorized to create a record for another user.',
137
- };
138
- }
139
- const allowed = yield this._doesSubscriptionAllowToCreateRecord({
34
+ async createRecord(request) {
35
+ try {
36
+ if (!request.userId) {
37
+ return {
38
+ success: false,
39
+ errorCode: 'not_logged_in',
40
+ errorMessage: 'The user must be logged in in order to create a record.',
41
+ };
42
+ }
43
+ const record = await this._store.getRecordByName(request.recordName);
44
+ if (record) {
45
+ if (record.name === request.userId &&
46
+ record.ownerId !== request.userId &&
47
+ request.ownerId === request.userId) {
48
+ const allowed = await this._doesSubscriptionAllowToCreateRecord({
140
49
  ownerId: request.userId,
141
50
  });
142
51
  if (!allowed.success) {
143
52
  return allowed;
144
53
  }
145
- console.log(`[RecordsController] [action: record.create recordName: ${request.recordName}, userId: ${request.userId}, ownerId: ${request.ownerId}] Creating record.`);
146
- yield this._store.addRecord({
147
- name: request.recordName,
148
- ownerId: request.ownerId,
149
- secretHashes: [],
150
- secretSalt: this._createSalt(),
151
- studioId: null,
54
+ console.log(`[RecordsController] [action: record.create recordName: ${record.name}, userId: ${request.userId}] Fixing record owner to match actual owner.`);
55
+ record.ownerId = request.userId;
56
+ record.studioId = null;
57
+ // Clear the hashes and re-create the salt so that access to the record is revoked for any record key that was created before.
58
+ record.secretHashes = [];
59
+ record.secretSalt = this._createSalt();
60
+ await this._store.updateRecord({
61
+ ...record,
152
62
  });
63
+ return {
64
+ success: true,
65
+ };
153
66
  }
154
- else {
155
- const assignments = yield this._store.listStudioAssignments(request.studioId, {
156
- userId: request.userId,
157
- role: 'admin',
158
- });
159
- if (assignments.length <= 0) {
160
- return {
161
- success: false,
162
- errorCode: 'not_authorized',
163
- errorMessage: 'You are not authorized to create a record for this studio.',
164
- };
165
- }
166
- const allowed = yield this._doesSubscriptionAllowToCreateRecord({
67
+ let existingStudioMembers = await this._store.listStudioAssignments(record.name);
68
+ if (existingStudioMembers.length > 0 &&
69
+ record.studioId !== record.name &&
70
+ request.studioId === record.name) {
71
+ const allowed = await this._doesSubscriptionAllowToCreateRecord({
167
72
  studioId: request.studioId,
168
73
  });
169
74
  if (!allowed.success) {
170
75
  return allowed;
171
76
  }
172
- console.log(`[RecordsController] [action: record.create recordName: ${request.recordName}, userId: ${request.userId}, studioId: ${request.studioId}] Creating record.`);
173
- yield this._store.addRecord({
174
- name: request.recordName,
175
- ownerId: null,
176
- secretHashes: [],
177
- secretSalt: this._createSalt(),
178
- studioId: request.studioId,
77
+ console.log(`[RecordsController] [action: record.create recordName: ${record.name}, userId: ${request.userId}, studioId: ${request.studioId}] Fixing record owner to match actual owner.`);
78
+ record.ownerId = null;
79
+ record.studioId = request.studioId;
80
+ // Clear the hashes and re-create the salt so that access to the record is revoked for any record key that was created before.
81
+ record.secretHashes = [];
82
+ record.secretSalt = this._createSalt();
83
+ await this._store.updateRecord({
84
+ ...record,
179
85
  });
86
+ return {
87
+ success: true,
88
+ };
180
89
  }
181
90
  return {
182
- success: true,
91
+ success: false,
92
+ errorCode: 'record_already_exists',
93
+ errorMessage: 'A record with that name already exists.',
183
94
  };
184
95
  }
185
- catch (err) {
186
- const span = trace.getActiveSpan();
187
- span === null || span === void 0 ? void 0 : span.recordException(err);
188
- span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
189
- console.error('[RecordsController] [createRecord] An error occurred while creating a record:', err);
96
+ if (request.recordName !== request.ownerId &&
97
+ request.recordName !== request.studioId) {
98
+ const existingUser = await this._auth.findUser(request.recordName);
99
+ if (existingUser) {
100
+ return {
101
+ success: false,
102
+ errorCode: 'record_already_exists',
103
+ errorMessage: 'A record with that name already exists.',
104
+ };
105
+ }
106
+ }
107
+ if (!request.ownerId && !request.studioId) {
190
108
  return {
191
109
  success: false,
192
- errorCode: 'server_error',
193
- errorMessage: 'A server error occurred.',
110
+ errorCode: 'unacceptable_request',
111
+ errorMessage: 'You must provide an owner ID or a studio ID.',
194
112
  };
195
113
  }
196
- });
114
+ if (request.ownerId) {
115
+ if (request.ownerId !== request.userId) {
116
+ return {
117
+ success: false,
118
+ errorCode: 'not_authorized',
119
+ errorMessage: 'You are not authorized to create a record for another user.',
120
+ };
121
+ }
122
+ const allowed = await this._doesSubscriptionAllowToCreateRecord({
123
+ ownerId: request.userId,
124
+ });
125
+ if (!allowed.success) {
126
+ return allowed;
127
+ }
128
+ console.log(`[RecordsController] [action: record.create recordName: ${request.recordName}, userId: ${request.userId}, ownerId: ${request.ownerId}] Creating record.`);
129
+ await this._store.addRecord({
130
+ name: request.recordName,
131
+ ownerId: request.ownerId,
132
+ secretHashes: [],
133
+ secretSalt: this._createSalt(),
134
+ studioId: null,
135
+ });
136
+ }
137
+ else {
138
+ const assignments = await this._store.listStudioAssignments(request.studioId, {
139
+ userId: request.userId,
140
+ role: 'admin',
141
+ });
142
+ if (assignments.length <= 0) {
143
+ return {
144
+ success: false,
145
+ errorCode: 'not_authorized',
146
+ errorMessage: 'You are not authorized to create a record for this studio.',
147
+ };
148
+ }
149
+ const allowed = await this._doesSubscriptionAllowToCreateRecord({
150
+ studioId: request.studioId,
151
+ });
152
+ if (!allowed.success) {
153
+ return allowed;
154
+ }
155
+ console.log(`[RecordsController] [action: record.create recordName: ${request.recordName}, userId: ${request.userId}, studioId: ${request.studioId}] Creating record.`);
156
+ await this._store.addRecord({
157
+ name: request.recordName,
158
+ ownerId: null,
159
+ secretHashes: [],
160
+ secretSalt: this._createSalt(),
161
+ studioId: request.studioId,
162
+ });
163
+ }
164
+ return {
165
+ success: true,
166
+ };
167
+ }
168
+ catch (err) {
169
+ const span = trace.getActiveSpan();
170
+ span === null || span === void 0 ? void 0 : span.recordException(err);
171
+ span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
172
+ console.error('[RecordsController] [createRecord] An error occurred while creating a record:', err);
173
+ return {
174
+ success: false,
175
+ errorCode: 'server_error',
176
+ errorMessage: 'A server error occurred.',
177
+ };
178
+ }
197
179
  }
198
180
  /**
199
181
  * Creates a new public record key for the given bucket name.
@@ -202,62 +184,74 @@ export class RecordsController {
202
184
  * @param userId The ID of the user that is creating the public record.
203
185
  * @returns
204
186
  */
205
- createPublicRecordKey(name, policy, userId) {
187
+ async createPublicRecordKey(name, policy, userId) {
206
188
  var _a;
207
- return __awaiter(this, void 0, void 0, function* () {
208
- try {
209
- if (!userId) {
189
+ try {
190
+ if (!userId) {
191
+ return {
192
+ success: false,
193
+ errorCode: 'not_logged_in',
194
+ errorMessage: 'The user must be logged in in order to create a record key.',
195
+ errorReason: 'not_logged_in',
196
+ };
197
+ }
198
+ if (!!policy &&
199
+ policy !== 'subjectfull' &&
200
+ policy !== 'subjectless') {
201
+ return {
202
+ success: false,
203
+ errorCode: 'invalid_policy',
204
+ errorMessage: 'The record key policy must be either "subjectfull" or "subjectless".',
205
+ errorReason: 'invalid_policy',
206
+ };
207
+ }
208
+ let existingStudioMembers = await this._store.listStudioAssignments(name);
209
+ let createResult;
210
+ // recordName matches studioId
211
+ if (existingStudioMembers.length > 0) {
212
+ createResult = await this.createRecord({
213
+ recordName: name,
214
+ userId: userId,
215
+ studioId: name,
216
+ });
217
+ }
218
+ else {
219
+ createResult = await this.createRecord({
220
+ recordName: name,
221
+ userId: userId,
222
+ ownerId: userId,
223
+ });
224
+ }
225
+ if (createResult.success === false) {
226
+ if (createResult.errorCode !== 'record_already_exists') {
210
227
  return {
211
- success: false,
212
- errorCode: 'not_logged_in',
213
- errorMessage: 'The user must be logged in in order to create a record key.',
214
- errorReason: 'not_logged_in',
228
+ ...createResult,
229
+ errorReason: 'not_authorized',
215
230
  };
216
231
  }
217
- if (!!policy &&
218
- policy !== 'subjectfull' &&
219
- policy !== 'subjectless') {
232
+ }
233
+ const record = await this._store.getRecordByName(name);
234
+ if (!record) {
235
+ if (createResult.success === false &&
236
+ createResult.errorCode === 'record_already_exists') {
220
237
  return {
221
238
  success: false,
222
- errorCode: 'invalid_policy',
223
- errorMessage: 'The record key policy must be either "subjectfull" or "subjectless".',
224
- errorReason: 'invalid_policy',
239
+ errorCode: 'unauthorized_to_create_record_key',
240
+ errorMessage: 'Another user has already created this record.',
241
+ errorReason: 'record_owned_by_different_user',
225
242
  };
226
243
  }
227
- let existingStudioMembers = yield this._store.listStudioAssignments(name);
228
- let createResult;
229
- // recordName matches studioId
244
+ console.error(`[RecordsController] [action: recordKey.create recordName: ${name}, userId: ${userId}] Unable to find record that was just created!`);
245
+ return {
246
+ success: false,
247
+ errorCode: 'server_error',
248
+ errorMessage: 'A server error occurred.',
249
+ errorReason: 'server_error',
250
+ };
251
+ }
252
+ if (record.ownerId) {
230
253
  if (existingStudioMembers.length > 0) {
231
- createResult = yield this.createRecord({
232
- recordName: name,
233
- userId: userId,
234
- studioId: name,
235
- });
236
- }
237
- else {
238
- createResult = yield this.createRecord({
239
- recordName: name,
240
- userId: userId,
241
- ownerId: userId,
242
- });
243
- }
244
- if (createResult.success === false) {
245
- if (createResult.errorCode !== 'record_already_exists') {
246
- return Object.assign(Object.assign({}, createResult), { errorReason: 'not_authorized' });
247
- }
248
- }
249
- const record = yield this._store.getRecordByName(name);
250
- if (!record) {
251
- if (createResult.success === false &&
252
- createResult.errorCode === 'record_already_exists') {
253
- return {
254
- success: false,
255
- errorCode: 'unauthorized_to_create_record_key',
256
- errorMessage: 'Another user has already created this record.',
257
- errorReason: 'record_owned_by_different_user',
258
- };
259
- }
260
- console.error(`[RecordsController] [action: recordKey.create recordName: ${name}, userId: ${userId}] Unable to find record that was just created!`);
254
+ console.error(`[RecordsController] [action: recordKey.create recordName: ${name}, userId: ${userId}] Studio members exist for the record, but the record is owned by a user!`);
261
255
  return {
262
256
  success: false,
263
257
  errorCode: 'server_error',
@@ -265,69 +259,58 @@ export class RecordsController {
265
259
  errorReason: 'server_error',
266
260
  };
267
261
  }
268
- if (record.ownerId) {
269
- if (existingStudioMembers.length > 0) {
270
- console.error(`[RecordsController] [action: recordKey.create recordName: ${name}, userId: ${userId}] Studio members exist for the record, but the record is owned by a user!`);
271
- return {
272
- success: false,
273
- errorCode: 'server_error',
274
- errorMessage: 'A server error occurred.',
275
- errorReason: 'server_error',
276
- };
277
- }
278
- if (record.ownerId !== userId) {
279
- return {
280
- success: false,
281
- errorCode: 'unauthorized_to_create_record_key',
282
- errorMessage: 'Another user has already created this record.',
283
- errorReason: 'record_owned_by_different_user',
284
- };
285
- }
286
- }
287
- else if (record.studioId) {
288
- let existingStudioMembers = yield this._store.listStudioAssignments(record.studioId, {
289
- userId: userId,
290
- role: 'admin',
291
- });
292
- if (existingStudioMembers.length <= 0) {
293
- return {
294
- success: false,
295
- errorCode: 'unauthorized_to_create_record_key',
296
- errorMessage: 'You are not authorized to create a record key for this record.',
297
- errorReason: 'record_owned_by_different_user',
298
- };
299
- }
262
+ if (record.ownerId !== userId) {
263
+ return {
264
+ success: false,
265
+ errorCode: 'unauthorized_to_create_record_key',
266
+ errorMessage: 'Another user has already created this record.',
267
+ errorReason: 'record_owned_by_different_user',
268
+ };
300
269
  }
301
- console.log(`[RecordsController] [action: recordKey.create recordName: ${name}, userId: ${userId}] Creating record key.`);
302
- const passwordBytes = randomBytes(16);
303
- const password = fromByteArray(passwordBytes); // convert to human-readable string
304
- const salt = record.secretSalt;
305
- const passwordHash = this.hashHighEntropyPasswordWithSalt(password, salt);
306
- yield this._store.addRecordKey({
307
- recordName: name,
308
- secretHash: passwordHash,
309
- policy: policy !== null && policy !== void 0 ? policy : DEFAULT_RECORD_KEY_POLICY,
310
- creatorId: (_a = record.ownerId) !== null && _a !== void 0 ? _a : userId,
311
- });
312
- return {
313
- success: true,
314
- recordKey: formatV2RecordKey(name, password, policy),
315
- recordName: name,
316
- };
317
270
  }
318
- catch (err) {
319
- const span = trace.getActiveSpan();
320
- span === null || span === void 0 ? void 0 : span.recordException(err);
321
- span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
322
- console.error('[RecordsController] [createPublicRecordKey] An error occurred while creating a public record key:', err);
323
- return {
324
- success: false,
325
- errorCode: 'server_error',
326
- errorMessage: 'A server error occurred.',
327
- errorReason: 'server_error',
328
- };
271
+ else if (record.studioId) {
272
+ let existingStudioMembers = await this._store.listStudioAssignments(record.studioId, {
273
+ userId: userId,
274
+ role: 'admin',
275
+ });
276
+ if (existingStudioMembers.length <= 0) {
277
+ return {
278
+ success: false,
279
+ errorCode: 'unauthorized_to_create_record_key',
280
+ errorMessage: 'You are not authorized to create a record key for this record.',
281
+ errorReason: 'record_owned_by_different_user',
282
+ };
283
+ }
329
284
  }
330
- });
285
+ console.log(`[RecordsController] [action: recordKey.create recordName: ${name}, userId: ${userId}] Creating record key.`);
286
+ const passwordBytes = randomBytes(16);
287
+ const password = fromByteArray(passwordBytes); // convert to human-readable string
288
+ const salt = record.secretSalt;
289
+ const passwordHash = this.hashHighEntropyPasswordWithSalt(password, salt);
290
+ await this._store.addRecordKey({
291
+ recordName: name,
292
+ secretHash: passwordHash,
293
+ policy: policy !== null && policy !== void 0 ? policy : DEFAULT_RECORD_KEY_POLICY,
294
+ creatorId: (_a = record.ownerId) !== null && _a !== void 0 ? _a : userId,
295
+ });
296
+ return {
297
+ success: true,
298
+ recordKey: formatV2RecordKey(name, password, policy),
299
+ recordName: name,
300
+ };
301
+ }
302
+ catch (err) {
303
+ const span = trace.getActiveSpan();
304
+ span === null || span === void 0 ? void 0 : span.recordException(err);
305
+ span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
306
+ console.error('[RecordsController] [createPublicRecordKey] An error occurred while creating a public record key:', err);
307
+ return {
308
+ success: false,
309
+ errorCode: 'server_error',
310
+ errorMessage: 'A server error occurred.',
311
+ errorReason: 'server_error',
312
+ };
313
+ }
331
314
  }
332
315
  hashHighEntropyPasswordWithSalt(sessionSecret, sessionId) {
333
316
  return hashHighEntropyPasswordWithSalt(sessionSecret, sessionId);
@@ -337,381 +320,371 @@ export class RecordsController {
337
320
  * @param key The key that should be validated.
338
321
  * @returns
339
322
  */
340
- validatePublicRecordKey(key) {
341
- return __awaiter(this, void 0, void 0, function* () {
342
- try {
343
- const parseResult = parseRecordKey(key);
344
- if (!parseResult) {
345
- return {
346
- success: false,
347
- errorCode: 'invalid_record_key',
348
- errorMessage: 'Invalid record key.',
349
- };
350
- }
351
- const [name, password, policy] = parseResult;
352
- const record = yield this._store.getRecordByName(name);
353
- if (!record) {
354
- return {
355
- success: false,
356
- errorCode: 'record_not_found',
357
- errorMessage: 'Record not found.',
358
- };
359
- }
360
- // Check v2 hashes first because they are much quicker to check
361
- const hashV2 = hashHighEntropyPasswordWithSalt(password, record.secretSalt);
362
- let valid = false;
363
- let resultPolicy = DEFAULT_RECORD_KEY_POLICY;
364
- let creatorId = null;
365
- if (record.secretHashes.some((h) => h === hashV2)) {
366
- valid = true;
367
- creatorId = record.ownerId;
323
+ async validatePublicRecordKey(key) {
324
+ try {
325
+ const parseResult = parseRecordKey(key);
326
+ if (!parseResult) {
327
+ return {
328
+ success: false,
329
+ errorCode: 'invalid_record_key',
330
+ errorMessage: 'Invalid record key.',
331
+ };
332
+ }
333
+ const [name, password, policy] = parseResult;
334
+ const record = await this._store.getRecordByName(name);
335
+ if (!record) {
336
+ return {
337
+ success: false,
338
+ errorCode: 'record_not_found',
339
+ errorMessage: 'Record not found.',
340
+ };
341
+ }
342
+ // Check v2 hashes first because they are much quicker to check
343
+ const hashV2 = hashHighEntropyPasswordWithSalt(password, record.secretSalt);
344
+ let valid = false;
345
+ let resultPolicy = DEFAULT_RECORD_KEY_POLICY;
346
+ let creatorId = null;
347
+ if (record.secretHashes.some((h) => h === hashV2)) {
348
+ valid = true;
349
+ creatorId = record.ownerId;
350
+ }
351
+ else {
352
+ const key = await this._store.getRecordKeyByRecordAndHash(name, hashV2);
353
+ if (key) {
354
+ if (name === record.ownerId &&
355
+ key.creatorId !== record.ownerId) {
356
+ // The record is a user record (because the name is the same as the owner ID)
357
+ // but this key was created when the record was owned by someone else.
358
+ // Normally, this shouldn't happen, but it is possible if the record was created before v3.2.0 or if the record was created before the user was created.
359
+ // This check is a failsafe to ensure that user records are always owned by the user, and not by someone else.
360
+ valid = false;
361
+ }
362
+ else {
363
+ resultPolicy = key.policy;
364
+ creatorId = key.creatorId;
365
+ valid = true;
366
+ }
368
367
  }
369
368
  else {
370
- const key = yield this._store.getRecordKeyByRecordAndHash(name, hashV2);
371
- if (key) {
372
- if (name === record.ownerId &&
373
- key.creatorId !== record.ownerId) {
374
- // The record is a user record (because the name is the same as the owner ID)
375
- // but this key was created when the record was owned by someone else.
376
- // Normally, this shouldn't happen, but it is possible if the record was created before v3.2.0 or if the record was created before the user was created.
377
- // This check is a failsafe to ensure that user records are always owned by the user, and not by someone else.
378
- valid = false;
379
- }
380
- else {
381
- resultPolicy = key.policy;
382
- creatorId = key.creatorId;
383
- valid = true;
384
- }
369
+ // Check v1 hashes
370
+ const hash = hashLowEntropyPasswordWithSalt(password, record.secretSalt);
371
+ if (record.secretHashes.some((h) => h === hash)) {
372
+ valid = true;
385
373
  }
386
374
  else {
387
- // Check v1 hashes
388
- const hash = hashLowEntropyPasswordWithSalt(password, record.secretSalt);
389
- if (record.secretHashes.some((h) => h === hash)) {
390
- valid = true;
391
- }
392
- else {
393
- const key = yield this._store.getRecordKeyByRecordAndHash(name, hash);
394
- if (key) {
395
- if (name === record.ownerId &&
396
- key.creatorId !== record.ownerId) {
397
- // The record is a user record (because the name is the same as the owner ID)
398
- // but this key was created when the record was owned by someone else.
399
- // Normally, this shouldn't happen, but it is possible if the record was created before v3.2.0 or if the record was created before the user was created.
400
- // This check is a failsafe to ensure that user records are always owned by the user, and not by someone else.
401
- valid = false;
402
- }
403
- else {
404
- resultPolicy = key.policy;
405
- creatorId = key.creatorId;
406
- valid = true;
407
- }
375
+ const key = await this._store.getRecordKeyByRecordAndHash(name, hash);
376
+ if (key) {
377
+ if (name === record.ownerId &&
378
+ key.creatorId !== record.ownerId) {
379
+ // The record is a user record (because the name is the same as the owner ID)
380
+ // but this key was created when the record was owned by someone else.
381
+ // Normally, this shouldn't happen, but it is possible if the record was created before v3.2.0 or if the record was created before the user was created.
382
+ // This check is a failsafe to ensure that user records are always owned by the user, and not by someone else.
383
+ valid = false;
384
+ }
385
+ else {
386
+ resultPolicy = key.policy;
387
+ creatorId = key.creatorId;
388
+ valid = true;
408
389
  }
409
390
  }
410
391
  }
411
392
  }
412
- if (resultPolicy !== policy) {
413
- return {
414
- success: false,
415
- errorCode: 'invalid_record_key',
416
- errorMessage: 'Invalid record key.',
417
- };
418
- }
419
- if (valid) {
420
- return {
421
- success: true,
422
- recordName: name,
423
- policy: policy,
424
- ownerId: record.ownerId,
425
- keyCreatorId: creatorId !== null && creatorId !== void 0 ? creatorId : record.ownerId,
426
- };
427
- }
428
- else {
429
- return {
430
- success: false,
431
- errorCode: 'invalid_record_key',
432
- errorMessage: 'Invalid record key.',
433
- };
434
- }
435
393
  }
436
- catch (err) {
437
- const span = trace.getActiveSpan();
438
- span === null || span === void 0 ? void 0 : span.recordException(err);
439
- span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
440
- console.error('[RecordsController] [validatePublicRecordKey] An error occurred while creating a public record key:', err);
394
+ if (resultPolicy !== policy) {
441
395
  return {
442
396
  success: false,
443
- errorCode: 'server_error',
444
- errorMessage: 'A server error occurred.',
397
+ errorCode: 'invalid_record_key',
398
+ errorMessage: 'Invalid record key.',
399
+ };
400
+ }
401
+ if (valid) {
402
+ return {
403
+ success: true,
404
+ recordName: name,
405
+ policy: policy,
406
+ ownerId: record.ownerId,
407
+ keyCreatorId: creatorId !== null && creatorId !== void 0 ? creatorId : record.ownerId,
445
408
  };
446
409
  }
447
- });
410
+ else {
411
+ return {
412
+ success: false,
413
+ errorCode: 'invalid_record_key',
414
+ errorMessage: 'Invalid record key.',
415
+ };
416
+ }
417
+ }
418
+ catch (err) {
419
+ const span = trace.getActiveSpan();
420
+ span === null || span === void 0 ? void 0 : span.recordException(err);
421
+ span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
422
+ console.error('[RecordsController] [validatePublicRecordKey] An error occurred while creating a public record key:', err);
423
+ return {
424
+ success: false,
425
+ errorCode: 'server_error',
426
+ errorMessage: 'A server error occurred.',
427
+ };
428
+ }
448
429
  }
449
430
  /**
450
431
  * Validates the given record name. Returns information about the record if it exists.
451
432
  * @param name The name of the record.
452
433
  * @param userId The ID of the user that is validating the record.
453
434
  */
454
- validateRecordName(name, userId) {
455
- return __awaiter(this, void 0, void 0, function* () {
456
- try {
457
- const record = yield this._store.getRecordByName(name);
458
- if (!record) {
459
- if (userId && name === userId) {
460
- const allowed = yield this._doesSubscriptionAllowToCreateRecord({
461
- ownerId: userId,
462
- });
463
- if (allowed.success === false) {
464
- return allowed;
465
- }
466
- console.log(`[RecordsController] [validateRecordName recordName: ${name}, userId: ${userId}] Creating record for user.`);
467
- yield this._store.addRecord({
468
- name,
469
- ownerId: userId,
470
- studioId: null,
471
- secretHashes: [],
472
- secretSalt: this._createSalt(),
473
- });
474
- return {
475
- success: true,
476
- recordName: name,
477
- ownerId: userId,
478
- studioId: null,
479
- };
480
- }
481
- let studioMembers = yield this._store.listStudioAssignments(name);
482
- if (studioMembers.length > 0) {
483
- const allowed = yield this._doesSubscriptionAllowToCreateRecord({
484
- studioId: name,
485
- });
486
- if (allowed.success === false) {
487
- return allowed;
488
- }
489
- console.log(`[RecordsController] [validateRecordName recordName: ${name}, userId: ${userId}, studioId: ${name}] Creating record for studio.`);
490
- yield this._store.addRecord({
491
- name,
492
- ownerId: null,
493
- studioId: name,
494
- secretHashes: [],
495
- secretSalt: this._createSalt(),
496
- });
497
- return {
498
- success: true,
499
- recordName: name,
500
- ownerId: null,
501
- studioId: name,
502
- studioMembers,
503
- };
504
- }
505
- return {
506
- success: false,
507
- errorCode: 'record_not_found',
508
- errorMessage: 'Record not found.',
509
- };
510
- }
511
- else if (userId &&
512
- record.name === userId &&
513
- record.ownerId !== userId) {
514
- const allowed = yield this._doesSubscriptionAllowToCreateRecord({
435
+ async validateRecordName(name, userId) {
436
+ try {
437
+ const record = await this._store.getRecordByName(name);
438
+ if (!record) {
439
+ if (userId && name === userId) {
440
+ const allowed = await this._doesSubscriptionAllowToCreateRecord({
515
441
  ownerId: userId,
516
442
  });
517
443
  if (allowed.success === false) {
518
444
  return allowed;
519
445
  }
520
- // The user is not currently the owner of their own record.
521
- // This is an issue that needs to be fixed because users should always own the record that has the same name as their ID.
522
- console.log(`[RecordsController] [validateRecordName recordName: ${name}, userId: ${userId}] Fixing record owner to match actual owner.`);
523
- record.ownerId = userId;
524
- // Clear the hashes and re-create the salt so that access to the record is revoked for any record key that was created before.
525
- record.secretHashes = [];
526
- record.secretSalt = this._createSalt();
527
- yield this._store.updateRecord(Object.assign({}, record));
446
+ console.log(`[RecordsController] [validateRecordName recordName: ${name}, userId: ${userId}] Creating record for user.`);
447
+ await this._store.addRecord({
448
+ name,
449
+ ownerId: userId,
450
+ studioId: null,
451
+ secretHashes: [],
452
+ secretSalt: this._createSalt(),
453
+ });
454
+ return {
455
+ success: true,
456
+ recordName: name,
457
+ ownerId: userId,
458
+ studioId: null,
459
+ };
528
460
  }
529
- let existingStudioMembers = yield this._store.listStudioAssignments(name);
530
- if (existingStudioMembers.length > 0 &&
531
- record.studioId !== name &&
532
- record.ownerId !== null) {
533
- const allowed = yield this._doesSubscriptionAllowToCreateRecord({
461
+ let studioMembers = await this._store.listStudioAssignments(name);
462
+ if (studioMembers.length > 0) {
463
+ const allowed = await this._doesSubscriptionAllowToCreateRecord({
534
464
  studioId: name,
535
465
  });
536
466
  if (allowed.success === false) {
537
467
  return allowed;
538
468
  }
539
- console.log(`[RecordsController] [validateRecordName recordName: ${name}, userId: ${userId}, studioId: ${name}] Fixing record studio to match actual studio.`);
540
- record.ownerId = null;
541
- record.studioId = name;
542
- record.secretHashes = [];
543
- record.secretSalt = this._createSalt();
544
- yield this._store.updateRecord(Object.assign({}, record));
545
- }
546
- let studioMembers = undefined;
547
- if (existingStudioMembers.length > 0) {
548
- studioMembers = existingStudioMembers;
549
- }
550
- else if (record.studioId) {
551
- studioMembers = yield this._store.listStudioAssignments(record.studioId);
469
+ console.log(`[RecordsController] [validateRecordName recordName: ${name}, userId: ${userId}, studioId: ${name}] Creating record for studio.`);
470
+ await this._store.addRecord({
471
+ name,
472
+ ownerId: null,
473
+ studioId: name,
474
+ secretHashes: [],
475
+ secretSalt: this._createSalt(),
476
+ });
477
+ return {
478
+ success: true,
479
+ recordName: name,
480
+ ownerId: null,
481
+ studioId: name,
482
+ studioMembers,
483
+ };
552
484
  }
553
- return {
554
- success: true,
555
- recordName: name,
556
- ownerId: record.ownerId,
557
- studioId: record.studioId,
558
- studioMembers,
559
- };
560
- }
561
- catch (err) {
562
- const span = trace.getActiveSpan();
563
- span === null || span === void 0 ? void 0 : span.recordException(err);
564
- span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
565
- console.error('[RecordsController] [validateRecordName] An error occurred while creating a validating a record name:', err);
566
485
  return {
567
486
  success: false,
568
- errorCode: 'server_error',
569
- errorMessage: 'A server error occurred.',
487
+ errorCode: 'record_not_found',
488
+ errorMessage: 'Record not found.',
570
489
  };
571
490
  }
572
- });
573
- }
574
- _doesSubscriptionAllowToCreateRecord(filter) {
575
- var _a, _b;
576
- return __awaiter(this, void 0, void 0, function* () {
577
- const { features, metrics } = yield this._getSubscriptionFeatures(filter);
578
- if (!((_a = features.records) === null || _a === void 0 ? void 0 : _a.allowed)) {
579
- return {
580
- success: false,
581
- errorCode: 'not_authorized',
582
- errorMessage: 'Records are not allowed for this subscription.',
583
- };
491
+ else if (userId &&
492
+ record.name === userId &&
493
+ record.ownerId !== userId) {
494
+ const allowed = await this._doesSubscriptionAllowToCreateRecord({
495
+ ownerId: userId,
496
+ });
497
+ if (allowed.success === false) {
498
+ return allowed;
499
+ }
500
+ // The user is not currently the owner of their own record.
501
+ // This is an issue that needs to be fixed because users should always own the record that has the same name as their ID.
502
+ console.log(`[RecordsController] [validateRecordName recordName: ${name}, userId: ${userId}] Fixing record owner to match actual owner.`);
503
+ record.ownerId = userId;
504
+ // Clear the hashes and re-create the salt so that access to the record is revoked for any record key that was created before.
505
+ record.secretHashes = [];
506
+ record.secretSalt = this._createSalt();
507
+ await this._store.updateRecord({
508
+ ...record,
509
+ });
584
510
  }
585
- else if (((_b = features.records) === null || _b === void 0 ? void 0 : _b.maxRecords) >= 0) {
586
- if (features.records.maxRecords <= metrics.totalRecords + 1) {
587
- return {
588
- success: false,
589
- errorCode: 'subscription_limit_reached',
590
- errorMessage: 'This subscription has hit its record limit.',
591
- };
511
+ let existingStudioMembers = await this._store.listStudioAssignments(name);
512
+ if (existingStudioMembers.length > 0 &&
513
+ record.studioId !== name &&
514
+ record.ownerId !== null) {
515
+ const allowed = await this._doesSubscriptionAllowToCreateRecord({
516
+ studioId: name,
517
+ });
518
+ if (allowed.success === false) {
519
+ return allowed;
592
520
  }
521
+ console.log(`[RecordsController] [validateRecordName recordName: ${name}, userId: ${userId}, studioId: ${name}] Fixing record studio to match actual studio.`);
522
+ record.ownerId = null;
523
+ record.studioId = name;
524
+ record.secretHashes = [];
525
+ record.secretSalt = this._createSalt();
526
+ await this._store.updateRecord({
527
+ ...record,
528
+ });
529
+ }
530
+ let studioMembers = undefined;
531
+ if (existingStudioMembers.length > 0) {
532
+ studioMembers = existingStudioMembers;
533
+ }
534
+ else if (record.studioId) {
535
+ studioMembers = await this._store.listStudioAssignments(record.studioId);
593
536
  }
594
537
  return {
595
538
  success: true,
539
+ recordName: name,
540
+ ownerId: record.ownerId,
541
+ studioId: record.studioId,
542
+ studioMembers,
543
+ };
544
+ }
545
+ catch (err) {
546
+ const span = trace.getActiveSpan();
547
+ span === null || span === void 0 ? void 0 : span.recordException(err);
548
+ span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
549
+ console.error('[RecordsController] [validateRecordName] An error occurred while creating a validating a record name:', err);
550
+ return {
551
+ success: false,
552
+ errorCode: 'server_error',
553
+ errorMessage: 'A server error occurred.',
596
554
  };
597
- });
555
+ }
598
556
  }
599
- _getSubscriptionFeatures(filter) {
600
- return __awaiter(this, void 0, void 0, function* () {
601
- const metrics = yield this._metrics.getSubscriptionRecordMetrics(filter);
602
- const config = yield this._config.getSubscriptionConfiguration();
557
+ async _doesSubscriptionAllowToCreateRecord(filter) {
558
+ var _a, _b;
559
+ const { features, metrics } = await this._getSubscriptionFeatures(filter);
560
+ if (!((_a = features.records) === null || _a === void 0 ? void 0 : _a.allowed)) {
603
561
  return {
604
- metrics,
605
- config,
606
- features: getSubscriptionFeatures(config, metrics.subscriptionStatus, metrics.subscriptionId, metrics.subscriptionType),
562
+ success: false,
563
+ errorCode: 'not_authorized',
564
+ errorMessage: 'Records are not allowed for this subscription.',
607
565
  };
608
- });
566
+ }
567
+ else if (((_b = features.records) === null || _b === void 0 ? void 0 : _b.maxRecords) >= 0) {
568
+ if (features.records.maxRecords <= metrics.totalRecords + 1) {
569
+ return {
570
+ success: false,
571
+ errorCode: 'subscription_limit_reached',
572
+ errorMessage: 'This subscription has hit its record limit.',
573
+ };
574
+ }
575
+ }
576
+ return {
577
+ success: true,
578
+ };
579
+ }
580
+ async _getSubscriptionFeatures(filter) {
581
+ const metrics = await this._metrics.getSubscriptionRecordMetrics(filter);
582
+ const config = await this._config.getSubscriptionConfiguration();
583
+ return {
584
+ metrics,
585
+ config,
586
+ features: getSubscriptionFeatures(config, metrics.subscriptionStatus, metrics.subscriptionId, metrics.subscriptionType),
587
+ };
609
588
  }
610
589
  /**
611
590
  * Gets the list of records that the user with the given ID has access to.
612
591
  * @param userId The ID of the user.
613
592
  */
614
- listRecords(userId) {
615
- return __awaiter(this, void 0, void 0, function* () {
616
- try {
617
- if (!this._store.listRecordsByOwnerId) {
618
- return {
619
- success: false,
620
- errorCode: 'not_supported',
621
- errorMessage: 'This operation is not supported.',
622
- };
623
- }
624
- const records = yield this._store.listRecordsByOwnerId(userId);
625
- return {
626
- success: true,
627
- records: records,
628
- };
629
- }
630
- catch (err) {
631
- const span = trace.getActiveSpan();
632
- span === null || span === void 0 ? void 0 : span.recordException(err);
633
- span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
634
- console.error('[RecordsController] [listRecords] Error listing records: ', err);
593
+ async listRecords(userId) {
594
+ try {
595
+ if (!this._store.listRecordsByOwnerId) {
635
596
  return {
636
597
  success: false,
637
- errorCode: 'server_error',
638
- errorMessage: 'A server error occurred.',
598
+ errorCode: 'not_supported',
599
+ errorMessage: 'This operation is not supported.',
639
600
  };
640
601
  }
641
- });
602
+ const records = await this._store.listRecordsByOwnerId(userId);
603
+ return {
604
+ success: true,
605
+ records: records,
606
+ };
607
+ }
608
+ catch (err) {
609
+ const span = trace.getActiveSpan();
610
+ span === null || span === void 0 ? void 0 : span.recordException(err);
611
+ span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
612
+ console.error('[RecordsController] [listRecords] Error listing records: ', err);
613
+ return {
614
+ success: false,
615
+ errorCode: 'server_error',
616
+ errorMessage: 'A server error occurred.',
617
+ };
618
+ }
642
619
  }
643
620
  /**
644
621
  * Gets the list of records in the given studio that the user with the given ID has access to.
645
622
  * @param studioId The ID of the studio.
646
623
  * @param userId The ID of the user that is currently logged in.
647
624
  */
648
- listStudioRecords(studioId, userId) {
649
- return __awaiter(this, void 0, void 0, function* () {
650
- try {
651
- if (!this._store.listRecordsByStudioIdAndUserId) {
652
- return {
653
- success: false,
654
- errorCode: 'not_supported',
655
- errorMessage: 'This operation is not supported.',
656
- };
657
- }
658
- const user = yield this._auth.findUser(userId);
659
- if (isSuperUserRole(user === null || user === void 0 ? void 0 : user.role)) {
660
- const records = yield this._store.listRecordsByStudioId(studioId);
661
- return {
662
- success: true,
663
- records,
664
- };
665
- }
666
- const records = yield this._store.listRecordsByStudioIdAndUserId(studioId, userId);
625
+ async listStudioRecords(studioId, userId) {
626
+ try {
627
+ if (!this._store.listRecordsByStudioIdAndUserId) {
667
628
  return {
668
- success: true,
669
- records: records,
629
+ success: false,
630
+ errorCode: 'not_supported',
631
+ errorMessage: 'This operation is not supported.',
670
632
  };
671
633
  }
672
- catch (err) {
673
- const span = trace.getActiveSpan();
674
- span === null || span === void 0 ? void 0 : span.recordException(err);
675
- span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
676
- console.error('[RecordsController] [listStudioRecords] Error listing records: ', err);
634
+ const user = await this._auth.findUser(userId);
635
+ if (isSuperUserRole(user === null || user === void 0 ? void 0 : user.role)) {
636
+ const records = await this._store.listRecordsByStudioId(studioId);
677
637
  return {
678
- success: false,
679
- errorCode: 'server_error',
680
- errorMessage: 'A server error occurred.',
638
+ success: true,
639
+ records,
681
640
  };
682
641
  }
683
- });
642
+ const records = await this._store.listRecordsByStudioIdAndUserId(studioId, userId);
643
+ return {
644
+ success: true,
645
+ records: records,
646
+ };
647
+ }
648
+ catch (err) {
649
+ const span = trace.getActiveSpan();
650
+ span === null || span === void 0 ? void 0 : span.recordException(err);
651
+ span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
652
+ console.error('[RecordsController] [listStudioRecords] Error listing records: ', err);
653
+ return {
654
+ success: false,
655
+ errorCode: 'server_error',
656
+ errorMessage: 'A server error occurred.',
657
+ };
658
+ }
684
659
  }
685
660
  /**
686
661
  * Attempts to create a new studio. That is, an entity that can be used to group records.
687
662
  * @param studioName The name of the studio.
688
663
  * @param userId The ID of the user that is creating the studio.
689
664
  */
690
- createStudio(studioName, userId) {
691
- return __awaiter(this, void 0, void 0, function* () {
692
- try {
693
- const studioId = uuid();
694
- yield this._store.createStudioForUser({
695
- id: studioId,
696
- displayName: studioName,
697
- }, userId);
698
- return {
699
- success: true,
700
- studioId: studioId,
701
- };
702
- }
703
- catch (err) {
704
- const span = trace.getActiveSpan();
705
- span === null || span === void 0 ? void 0 : span.recordException(err);
706
- span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
707
- console.error('[RecordsController] [createStudio] An error occurred while creating a studio:', err);
708
- return {
709
- success: false,
710
- errorCode: 'server_error',
711
- errorMessage: 'A server error occurred.',
712
- };
713
- }
714
- });
665
+ async createStudio(studioName, userId) {
666
+ try {
667
+ const studioId = uuid();
668
+ await this._store.createStudioForUser({
669
+ id: studioId,
670
+ displayName: studioName,
671
+ }, userId);
672
+ return {
673
+ success: true,
674
+ studioId: studioId,
675
+ };
676
+ }
677
+ catch (err) {
678
+ const span = trace.getActiveSpan();
679
+ span === null || span === void 0 ? void 0 : span.recordException(err);
680
+ span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
681
+ console.error('[RecordsController] [createStudio] An error occurred while creating a studio:', err);
682
+ return {
683
+ success: false,
684
+ errorCode: 'server_error',
685
+ errorMessage: 'A server error occurred.',
686
+ };
687
+ }
715
688
  }
716
689
  /**
717
690
  * Attempts to create a new studio in the given comId. That is, an entity that can be used to group records.
@@ -719,403 +692,376 @@ export class RecordsController {
719
692
  * @param userId The ID of the user that is creating the studio.
720
693
  * @param comId The comId of the studio that this studio should belong to.
721
694
  */
722
- createStudioInComId(studioName, userId, comId) {
695
+ async createStudioInComId(studioName, userId, comId) {
723
696
  var _a;
724
- return __awaiter(this, void 0, void 0, function* () {
725
- try {
726
- const studioId = uuid();
727
- const existingStudio = yield this._store.getStudioByComId(comId);
728
- if (!existingStudio) {
729
- return {
730
- success: false,
731
- errorCode: 'comId_not_found',
732
- errorMessage: 'The given comId was not found.',
733
- };
734
- }
735
- const config = yield this._config.getSubscriptionConfiguration();
736
- const features = getComIdFeatures(config, existingStudio.subscriptionStatus, existingStudio.subscriptionId);
737
- if (!features.allowed) {
738
- return {
739
- success: false,
740
- errorCode: 'not_authorized',
741
- errorMessage: 'comId features are not allowed for this comId. Make sure you have an active subscription that provides comId features.',
742
- };
743
- }
744
- if (typeof features.maxStudios === 'number') {
745
- const count = yield this._store.countStudiosInComId(comId);
746
- if (count >= features.maxStudios) {
747
- return {
748
- success: false,
749
- errorCode: 'subscription_limit_reached',
750
- errorMessage: 'The maximum number of studios allowed for your comId subscription has been reached.',
751
- };
752
- }
753
- }
754
- const comIdConfig = (_a = existingStudio.comIdConfig) !== null && _a !== void 0 ? _a : {
755
- allowedStudioCreators: 'only-members',
756
- };
757
- if (comIdConfig.allowedStudioCreators === 'only-members') {
758
- const assignments = yield this._store.listStudioAssignments(existingStudio.id, {
759
- userId: userId,
760
- });
761
- if (assignments.length <= 0) {
762
- return {
763
- success: false,
764
- errorCode: 'not_authorized',
765
- errorMessage: 'You are not authorized to create a studio in this comId.',
766
- };
767
- }
768
- }
769
- yield this._store.createStudioForUser({
770
- id: studioId,
771
- displayName: studioName,
772
- ownerStudioComId: comId,
773
- }, userId);
697
+ try {
698
+ const studioId = uuid();
699
+ const existingStudio = await this._store.getStudioByComId(comId);
700
+ if (!existingStudio) {
774
701
  return {
775
- success: true,
776
- studioId: studioId,
702
+ success: false,
703
+ errorCode: 'comId_not_found',
704
+ errorMessage: 'The given comId was not found.',
777
705
  };
778
706
  }
779
- catch (err) {
780
- const span = trace.getActiveSpan();
781
- span === null || span === void 0 ? void 0 : span.recordException(err);
782
- span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
783
- console.error('[RecordsController] [createStudio] An error occurred while creating a studio in a comId:', err);
707
+ const config = await this._config.getSubscriptionConfiguration();
708
+ const features = getComIdFeatures(config, existingStudio.subscriptionStatus, existingStudio.subscriptionId);
709
+ if (!features.allowed) {
784
710
  return {
785
711
  success: false,
786
- errorCode: 'server_error',
787
- errorMessage: 'A server error occurred.',
712
+ errorCode: 'not_authorized',
713
+ errorMessage: 'comId features are not allowed for this comId. Make sure you have an active subscription that provides comId features.',
788
714
  };
789
715
  }
790
- });
791
- }
792
- /**
793
- * Attempts to update the given studio.
794
- */
795
- updateStudio(request) {
796
- return __awaiter(this, void 0, void 0, function* () {
797
- try {
798
- const _a = request.studio, { id, loomConfig, humeConfig } = _a, updates = __rest(_a, ["id", "loomConfig", "humeConfig"]);
799
- const existingStudio = yield this._store.getStudioById(request.studio.id);
800
- if (!existingStudio) {
716
+ if (typeof features.maxStudios === 'number') {
717
+ const count = await this._store.countStudiosInComId(comId);
718
+ if (count >= features.maxStudios) {
801
719
  return {
802
720
  success: false,
803
- errorCode: 'studio_not_found',
804
- errorMessage: 'The given studio was not found.',
721
+ errorCode: 'subscription_limit_reached',
722
+ errorMessage: 'The maximum number of studios allowed for your comId subscription has been reached.',
805
723
  };
806
724
  }
807
- const assignments = yield this._store.listStudioAssignments(existingStudio.id, {
808
- userId: request.userId,
809
- role: 'admin',
725
+ }
726
+ const comIdConfig = (_a = existingStudio.comIdConfig) !== null && _a !== void 0 ? _a : {
727
+ allowedStudioCreators: 'only-members',
728
+ };
729
+ if (comIdConfig.allowedStudioCreators === 'only-members') {
730
+ const assignments = await this._store.listStudioAssignments(existingStudio.id, {
731
+ userId: userId,
810
732
  });
811
733
  if (assignments.length <= 0) {
812
734
  return {
813
735
  success: false,
814
736
  errorCode: 'not_authorized',
815
- errorMessage: 'You are not authorized to update this studio.',
737
+ errorMessage: 'You are not authorized to create a studio in this comId.',
816
738
  };
817
739
  }
818
- const final = Object.assign(Object.assign({}, existingStudio), updates);
819
- yield this._store.updateStudio(final);
820
- if (loomConfig) {
821
- yield this._store.updateStudioLoomConfig(final.id, loomConfig);
822
- }
823
- if (humeConfig) {
824
- yield this._store.updateStudioHumeConfig(final.id, humeConfig);
825
- }
740
+ }
741
+ await this._store.createStudioForUser({
742
+ id: studioId,
743
+ displayName: studioName,
744
+ ownerStudioComId: comId,
745
+ }, userId);
746
+ return {
747
+ success: true,
748
+ studioId: studioId,
749
+ };
750
+ }
751
+ catch (err) {
752
+ const span = trace.getActiveSpan();
753
+ span === null || span === void 0 ? void 0 : span.recordException(err);
754
+ span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
755
+ console.error('[RecordsController] [createStudio] An error occurred while creating a studio in a comId:', err);
756
+ return {
757
+ success: false,
758
+ errorCode: 'server_error',
759
+ errorMessage: 'A server error occurred.',
760
+ };
761
+ }
762
+ }
763
+ /**
764
+ * Attempts to update the given studio.
765
+ */
766
+ async updateStudio(request) {
767
+ try {
768
+ const { id, loomConfig, humeConfig, ...updates } = request.studio;
769
+ const existingStudio = await this._store.getStudioById(request.studio.id);
770
+ if (!existingStudio) {
826
771
  return {
827
- success: true,
772
+ success: false,
773
+ errorCode: 'studio_not_found',
774
+ errorMessage: 'The given studio was not found.',
828
775
  };
829
776
  }
830
- catch (err) {
831
- const span = trace.getActiveSpan();
832
- span === null || span === void 0 ? void 0 : span.recordException(err);
833
- span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
834
- console.error('[RecordsController] [updateStudio] An error occurred while updating a studio:', err);
777
+ const assignments = await this._store.listStudioAssignments(existingStudio.id, {
778
+ userId: request.userId,
779
+ role: 'admin',
780
+ });
781
+ if (assignments.length <= 0) {
835
782
  return {
836
783
  success: false,
837
- errorCode: 'server_error',
838
- errorMessage: 'A server error occurred.',
784
+ errorCode: 'not_authorized',
785
+ errorMessage: 'You are not authorized to update this studio.',
839
786
  };
840
787
  }
841
- });
788
+ const final = {
789
+ ...existingStudio,
790
+ ...updates,
791
+ };
792
+ await this._store.updateStudio(final);
793
+ if (loomConfig) {
794
+ await this._store.updateStudioLoomConfig(final.id, loomConfig);
795
+ }
796
+ if (humeConfig) {
797
+ await this._store.updateStudioHumeConfig(final.id, humeConfig);
798
+ }
799
+ return {
800
+ success: true,
801
+ };
802
+ }
803
+ catch (err) {
804
+ const span = trace.getActiveSpan();
805
+ span === null || span === void 0 ? void 0 : span.recordException(err);
806
+ span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
807
+ console.error('[RecordsController] [updateStudio] An error occurred while updating a studio:', err);
808
+ return {
809
+ success: false,
810
+ errorCode: 'server_error',
811
+ errorMessage: 'A server error occurred.',
812
+ };
813
+ }
842
814
  }
843
815
  /**
844
816
  * Attempts to get information about the given studio.
845
817
  * @param studioId The ID of the studio.
846
818
  * @param userId The ID of the user that is making this request.
847
819
  */
848
- getStudio(studioId, userId) {
849
- return __awaiter(this, void 0, void 0, function* () {
850
- try {
851
- const studio = yield this._store.getStudioById(studioId);
852
- if (!studio) {
853
- return {
854
- success: false,
855
- errorCode: 'studio_not_found',
856
- errorMessage: 'The given studio was not found.',
857
- };
858
- }
859
- const assignments = yield this._store.listStudioAssignments(studio.id, {
860
- userId: userId,
861
- });
862
- if (assignments.length <= 0) {
863
- return {
864
- success: false,
865
- errorCode: 'not_authorized',
866
- errorMessage: 'You are not authorized to access this studio.',
867
- };
868
- }
869
- let features = {
870
- allowed: false,
871
- };
872
- let loomFeatures = {
873
- allowed: false,
874
- };
875
- let humeFeatures = {
876
- allowed: false,
877
- };
878
- let loomConfig = undefined;
879
- let humeConfig = undefined;
880
- if (studio.subscriptionId &&
881
- isActiveSubscription(studio.subscriptionStatus)) {
882
- const config = yield this._config.getSubscriptionConfiguration();
883
- features = getComIdFeatures(config, studio.subscriptionStatus, studio.subscriptionId);
884
- loomFeatures = getLoomFeatures(config, studio.subscriptionStatus, studio.subscriptionId);
885
- if (loomFeatures.allowed) {
886
- loomConfig = yield this._store.getStudioLoomConfig(studio.id);
887
- }
888
- humeFeatures = getHumeAiFeatures(config, studio.subscriptionStatus, studio.subscriptionId, 'studio');
889
- if (humeFeatures.allowed) {
890
- humeConfig = yield this._store.getStudioHumeConfig(studio.id);
891
- }
892
- }
820
+ async getStudio(studioId, userId) {
821
+ try {
822
+ const studio = await this._store.getStudioById(studioId);
823
+ if (!studio) {
893
824
  return {
894
- success: true,
895
- studio: {
896
- id: studio.id,
897
- displayName: studio.displayName,
898
- logoUrl: studio.logoUrl,
899
- comId: studio.comId,
900
- ownerStudioComId: studio.ownerStudioComId,
901
- comIdConfig: studio.comIdConfig,
902
- playerConfig: studio.playerConfig,
903
- loomConfig: loomConfig
904
- ? {
905
- appId: loomConfig.appId,
906
- }
907
- : undefined,
908
- humeConfig: humeConfig
909
- ? {
910
- apiKey: humeConfig.apiKey,
911
- }
912
- : undefined,
913
- comIdFeatures: features,
914
- loomFeatures,
915
- humeFeatures,
916
- },
825
+ success: false,
826
+ errorCode: 'studio_not_found',
827
+ errorMessage: 'The given studio was not found.',
917
828
  };
918
829
  }
919
- catch (err) {
920
- const span = trace.getActiveSpan();
921
- span === null || span === void 0 ? void 0 : span.recordException(err);
922
- span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
923
- console.error('[RecordsController] [getStudio] An error occurred while getting a studio:', err);
830
+ const assignments = await this._store.listStudioAssignments(studio.id, {
831
+ userId: userId,
832
+ });
833
+ if (assignments.length <= 0) {
924
834
  return {
925
835
  success: false,
926
- errorCode: 'server_error',
927
- errorMessage: 'A server error occurred.',
836
+ errorCode: 'not_authorized',
837
+ errorMessage: 'You are not authorized to access this studio.',
928
838
  };
929
839
  }
930
- });
840
+ let features = {
841
+ allowed: false,
842
+ };
843
+ let loomFeatures = {
844
+ allowed: false,
845
+ };
846
+ let humeFeatures = {
847
+ allowed: false,
848
+ };
849
+ let loomConfig = undefined;
850
+ let humeConfig = undefined;
851
+ if (studio.subscriptionId &&
852
+ isActiveSubscription(studio.subscriptionStatus)) {
853
+ const config = await this._config.getSubscriptionConfiguration();
854
+ features = getComIdFeatures(config, studio.subscriptionStatus, studio.subscriptionId);
855
+ loomFeatures = getLoomFeatures(config, studio.subscriptionStatus, studio.subscriptionId);
856
+ if (loomFeatures.allowed) {
857
+ loomConfig = await this._store.getStudioLoomConfig(studio.id);
858
+ }
859
+ humeFeatures = getHumeAiFeatures(config, studio.subscriptionStatus, studio.subscriptionId, 'studio');
860
+ if (humeFeatures.allowed) {
861
+ humeConfig = await this._store.getStudioHumeConfig(studio.id);
862
+ }
863
+ }
864
+ return {
865
+ success: true,
866
+ studio: {
867
+ id: studio.id,
868
+ displayName: studio.displayName,
869
+ logoUrl: studio.logoUrl,
870
+ comId: studio.comId,
871
+ ownerStudioComId: studio.ownerStudioComId,
872
+ comIdConfig: studio.comIdConfig,
873
+ playerConfig: studio.playerConfig,
874
+ loomConfig: loomConfig
875
+ ? {
876
+ appId: loomConfig.appId,
877
+ }
878
+ : undefined,
879
+ humeConfig: humeConfig
880
+ ? {
881
+ apiKey: humeConfig.apiKey,
882
+ }
883
+ : undefined,
884
+ comIdFeatures: features,
885
+ loomFeatures,
886
+ humeFeatures,
887
+ },
888
+ };
889
+ }
890
+ catch (err) {
891
+ const span = trace.getActiveSpan();
892
+ span === null || span === void 0 ? void 0 : span.recordException(err);
893
+ span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
894
+ console.error('[RecordsController] [getStudio] An error occurred while getting a studio:', err);
895
+ return {
896
+ success: false,
897
+ errorCode: 'server_error',
898
+ errorMessage: 'A server error occurred.',
899
+ };
900
+ }
931
901
  }
932
902
  /**
933
903
  * Attempts to get the player config for the given comId.
934
904
  * @param comId The comId.
935
905
  */
936
- getPlayerConfig(comId) {
906
+ async getPlayerConfig(comId) {
937
907
  var _a, _b;
938
- return __awaiter(this, void 0, void 0, function* () {
939
- try {
940
- const studio = yield this._store.getStudioByComId(comId);
941
- if (!studio) {
942
- return {
943
- success: false,
944
- errorCode: 'comId_not_found',
945
- errorMessage: 'The given comId was not found.',
946
- };
947
- }
948
- return {
949
- success: true,
950
- comId: studio.comId,
951
- displayName: studio.displayName,
952
- logoUrl: (_a = studio.logoUrl) !== null && _a !== void 0 ? _a : null,
953
- playerConfig: (_b = studio.playerConfig) !== null && _b !== void 0 ? _b : null,
954
- };
955
- }
956
- catch (err) {
957
- const span = trace.getActiveSpan();
958
- span === null || span === void 0 ? void 0 : span.recordException(err);
959
- span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
960
- console.error('[RecordsController] [getPlayerConfig] An error occurred while getting the player config:', err);
908
+ try {
909
+ const studio = await this._store.getStudioByComId(comId);
910
+ if (!studio) {
961
911
  return {
962
912
  success: false,
963
- errorCode: 'server_error',
964
- errorMessage: 'A server error occurred.',
913
+ errorCode: 'comId_not_found',
914
+ errorMessage: 'The given comId was not found.',
965
915
  };
966
916
  }
967
- });
917
+ return {
918
+ success: true,
919
+ comId: studio.comId,
920
+ displayName: studio.displayName,
921
+ logoUrl: (_a = studio.logoUrl) !== null && _a !== void 0 ? _a : null,
922
+ playerConfig: (_b = studio.playerConfig) !== null && _b !== void 0 ? _b : null,
923
+ };
924
+ }
925
+ catch (err) {
926
+ const span = trace.getActiveSpan();
927
+ span === null || span === void 0 ? void 0 : span.recordException(err);
928
+ span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
929
+ console.error('[RecordsController] [getPlayerConfig] An error occurred while getting the player config:', err);
930
+ return {
931
+ success: false,
932
+ errorCode: 'server_error',
933
+ errorMessage: 'A server error occurred.',
934
+ };
935
+ }
968
936
  }
969
937
  /**
970
938
  * Gets the list of studios that the user with the given ID has access to.
971
939
  * @param userId The ID of the user.
972
940
  */
973
- listStudios(userId) {
974
- return __awaiter(this, void 0, void 0, function* () {
975
- try {
976
- const studios = yield this._store.listStudiosForUser(userId);
977
- const config = yield this._config.getSubscriptionConfiguration();
978
- return {
979
- success: true,
980
- studios: studios.map((s) => {
981
- return {
982
- studioId: s.studioId,
983
- displayName: s.displayName,
984
- role: s.role,
985
- isPrimaryContact: s.isPrimaryContact,
986
- subscriptionTier: getSubscriptionTier(config, s.subscriptionStatus, s.subscriptionId),
987
- ownerStudioComId: s.ownerStudioComId,
988
- comId: s.comId,
989
- };
990
- }),
991
- };
992
- }
993
- catch (err) {
994
- const span = trace.getActiveSpan();
995
- span === null || span === void 0 ? void 0 : span.recordException(err);
996
- span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
997
- console.error('[RecordsController] [listStudios] An error occurred while listing studios:', err);
998
- return {
999
- success: false,
1000
- errorCode: 'server_error',
1001
- errorMessage: 'A server error occurred.',
1002
- };
1003
- }
1004
- });
941
+ async listStudios(userId) {
942
+ try {
943
+ const studios = await this._store.listStudiosForUser(userId);
944
+ const config = await this._config.getSubscriptionConfiguration();
945
+ return {
946
+ success: true,
947
+ studios: studios.map((s) => {
948
+ return {
949
+ studioId: s.studioId,
950
+ displayName: s.displayName,
951
+ role: s.role,
952
+ isPrimaryContact: s.isPrimaryContact,
953
+ subscriptionTier: getSubscriptionTier(config, s.subscriptionStatus, s.subscriptionId),
954
+ ownerStudioComId: s.ownerStudioComId,
955
+ comId: s.comId,
956
+ };
957
+ }),
958
+ };
959
+ }
960
+ catch (err) {
961
+ const span = trace.getActiveSpan();
962
+ span === null || span === void 0 ? void 0 : span.recordException(err);
963
+ span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
964
+ console.error('[RecordsController] [listStudios] An error occurred while listing studios:', err);
965
+ return {
966
+ success: false,
967
+ errorCode: 'server_error',
968
+ errorMessage: 'A server error occurred.',
969
+ };
970
+ }
1005
971
  }
1006
972
  /**
1007
973
  * Gets the list of studios that the user with the given ID has access to and that are owned by the given comId.
1008
974
  * @param userId The ID of the user.
1009
975
  * @param comId The comId.
1010
976
  */
1011
- listStudiosByComId(userId, comId) {
1012
- return __awaiter(this, void 0, void 0, function* () {
1013
- try {
1014
- const studios = yield this._store.listStudiosForUserAndComId(userId, comId);
1015
- const config = yield this._config.getSubscriptionConfiguration();
1016
- return {
1017
- success: true,
1018
- studios: studios.map((s) => {
1019
- return {
1020
- studioId: s.studioId,
1021
- displayName: s.displayName,
1022
- role: s.role,
1023
- isPrimaryContact: s.isPrimaryContact,
1024
- subscriptionTier: getSubscriptionTier(config, s.subscriptionStatus, s.subscriptionId),
1025
- ownerStudioComId: s.ownerStudioComId,
1026
- comId: s.comId,
1027
- };
1028
- }),
1029
- };
1030
- }
1031
- catch (err) {
1032
- const span = trace.getActiveSpan();
1033
- span === null || span === void 0 ? void 0 : span.recordException(err);
1034
- span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
1035
- console.error('[RecordsController] [listStudios] An error occurred while listing studios:', err);
1036
- return {
1037
- success: false,
1038
- errorCode: 'server_error',
1039
- errorMessage: 'A server error occurred.',
1040
- };
1041
- }
1042
- });
977
+ async listStudiosByComId(userId, comId) {
978
+ try {
979
+ const studios = await this._store.listStudiosForUserAndComId(userId, comId);
980
+ const config = await this._config.getSubscriptionConfiguration();
981
+ return {
982
+ success: true,
983
+ studios: studios.map((s) => {
984
+ return {
985
+ studioId: s.studioId,
986
+ displayName: s.displayName,
987
+ role: s.role,
988
+ isPrimaryContact: s.isPrimaryContact,
989
+ subscriptionTier: getSubscriptionTier(config, s.subscriptionStatus, s.subscriptionId),
990
+ ownerStudioComId: s.ownerStudioComId,
991
+ comId: s.comId,
992
+ };
993
+ }),
994
+ };
995
+ }
996
+ catch (err) {
997
+ const span = trace.getActiveSpan();
998
+ span === null || span === void 0 ? void 0 : span.recordException(err);
999
+ span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
1000
+ console.error('[RecordsController] [listStudios] An error occurred while listing studios:', err);
1001
+ return {
1002
+ success: false,
1003
+ errorCode: 'server_error',
1004
+ errorMessage: 'A server error occurred.',
1005
+ };
1006
+ }
1043
1007
  }
1044
1008
  /**
1045
1009
  * Gets the list of members in a studio.
1046
1010
  * @param studioId The ID of the studio.
1047
1011
  * @param userId The ID of the user that is currently logged in.
1048
1012
  */
1049
- listStudioMembers(studioId, userId) {
1050
- return __awaiter(this, void 0, void 0, function* () {
1051
- try {
1052
- const members = yield this._store.listStudioAssignments(studioId);
1053
- const userAssignment = members.find((m) => m.userId === userId);
1054
- let role;
1055
- if (!userAssignment) {
1056
- const user = yield this._auth.findUser(userId);
1057
- if (!isSuperUserRole(user === null || user === void 0 ? void 0 : user.role)) {
1058
- return {
1059
- success: false,
1060
- errorCode: 'not_authorized',
1061
- errorMessage: 'You are not authorized to access this studio.',
1062
- };
1063
- }
1064
- else {
1065
- role = 'admin';
1066
- }
1013
+ async listStudioMembers(studioId, userId) {
1014
+ try {
1015
+ const members = await this._store.listStudioAssignments(studioId);
1016
+ const userAssignment = members.find((m) => m.userId === userId);
1017
+ let role;
1018
+ if (!userAssignment) {
1019
+ const user = await this._auth.findUser(userId);
1020
+ if (!isSuperUserRole(user === null || user === void 0 ? void 0 : user.role)) {
1021
+ return {
1022
+ success: false,
1023
+ errorCode: 'not_authorized',
1024
+ errorMessage: 'You are not authorized to access this studio.',
1025
+ };
1067
1026
  }
1068
1027
  else {
1069
- role = userAssignment.role;
1028
+ role = 'admin';
1070
1029
  }
1071
- const resultMembers = yield Promise.all(members.map((m) => __awaiter(this, void 0, void 0, function* () {
1072
- if (this._privo && m.user.privoServiceId) {
1073
- const result = yield this._privo.getUserInfo(m.user.privoServiceId);
1074
- return {
1075
- studioId: m.studioId,
1076
- userId: m.userId,
1077
- isPrimaryContact: m.isPrimaryContact,
1078
- role: m.role,
1079
- user: {
1080
- id: m.user.id,
1081
- name: result.givenName,
1082
- displayName: result.displayName,
1083
- },
1084
- };
1085
- }
1086
- else {
1087
- return {
1088
- studioId: m.studioId,
1089
- userId: m.userId,
1090
- isPrimaryContact: m.isPrimaryContact,
1091
- role: m.role,
1092
- user: {
1093
- id: m.user.id,
1094
- name: m.user.name,
1095
- email: m.user.email,
1096
- phoneNumber: m.user.phoneNumber,
1097
- },
1098
- };
1099
- }
1100
- })));
1101
- if (role === 'admin') {
1030
+ }
1031
+ else {
1032
+ role = userAssignment.role;
1033
+ }
1034
+ const resultMembers = await Promise.all(members.map(async (m) => {
1035
+ if (this._privo && m.user.privoServiceId) {
1036
+ const result = await this._privo.getUserInfo(m.user.privoServiceId);
1102
1037
  return {
1103
- success: true,
1104
- members: resultMembers.map((m) => ({
1105
- studioId: m.studioId,
1106
- userId: m.userId,
1107
- isPrimaryContact: m.isPrimaryContact,
1108
- role: m.role,
1109
- user: {
1110
- id: m.user.id,
1111
- name: m.user.name,
1112
- email: m.user.email,
1113
- phoneNumber: m.user.phoneNumber,
1114
- displayName: m.user.displayName,
1115
- },
1116
- })),
1038
+ studioId: m.studioId,
1039
+ userId: m.userId,
1040
+ isPrimaryContact: m.isPrimaryContact,
1041
+ role: m.role,
1042
+ user: {
1043
+ id: m.user.id,
1044
+ name: result.givenName,
1045
+ displayName: result.displayName,
1046
+ },
1047
+ };
1048
+ }
1049
+ else {
1050
+ return {
1051
+ studioId: m.studioId,
1052
+ userId: m.userId,
1053
+ isPrimaryContact: m.isPrimaryContact,
1054
+ role: m.role,
1055
+ user: {
1056
+ id: m.user.id,
1057
+ name: m.user.name,
1058
+ email: m.user.email,
1059
+ phoneNumber: m.user.phoneNumber,
1060
+ },
1117
1061
  };
1118
1062
  }
1063
+ }));
1064
+ if (role === 'admin') {
1119
1065
  return {
1120
1066
  success: true,
1121
1067
  members: resultMembers.map((m) => ({
@@ -1126,238 +1072,248 @@ export class RecordsController {
1126
1072
  user: {
1127
1073
  id: m.user.id,
1128
1074
  name: m.user.name,
1075
+ email: m.user.email,
1076
+ phoneNumber: m.user.phoneNumber,
1129
1077
  displayName: m.user.displayName,
1130
1078
  },
1131
1079
  })),
1132
1080
  };
1133
1081
  }
1134
- catch (err) {
1135
- const span = trace.getActiveSpan();
1136
- span === null || span === void 0 ? void 0 : span.recordException(err);
1137
- span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
1138
- console.error('[RecordsController] [listStudioMembers] An error occurred while listing studio members:', err);
1082
+ return {
1083
+ success: true,
1084
+ members: resultMembers.map((m) => ({
1085
+ studioId: m.studioId,
1086
+ userId: m.userId,
1087
+ isPrimaryContact: m.isPrimaryContact,
1088
+ role: m.role,
1089
+ user: {
1090
+ id: m.user.id,
1091
+ name: m.user.name,
1092
+ displayName: m.user.displayName,
1093
+ },
1094
+ })),
1095
+ };
1096
+ }
1097
+ catch (err) {
1098
+ const span = trace.getActiveSpan();
1099
+ span === null || span === void 0 ? void 0 : span.recordException(err);
1100
+ span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
1101
+ console.error('[RecordsController] [listStudioMembers] An error occurred while listing studio members:', err);
1102
+ return {
1103
+ success: false,
1104
+ errorCode: 'server_error',
1105
+ errorMessage: 'A server error occurred.',
1106
+ };
1107
+ }
1108
+ }
1109
+ async addStudioMember(request) {
1110
+ var _a, _b, _c, _d;
1111
+ try {
1112
+ if (!request.userId) {
1139
1113
  return {
1140
1114
  success: false,
1141
- errorCode: 'server_error',
1142
- errorMessage: 'A server error occurred.',
1115
+ errorCode: 'not_logged_in',
1116
+ errorMessage: 'You must be logged in to add a studio member.',
1143
1117
  };
1144
1118
  }
1145
- });
1146
- }
1147
- addStudioMember(request) {
1148
- var _a, _b, _c, _d;
1149
- return __awaiter(this, void 0, void 0, function* () {
1150
- try {
1151
- if (!request.userId) {
1152
- return {
1153
- success: false,
1154
- errorCode: 'not_logged_in',
1155
- errorMessage: 'You must be logged in to add a studio member.',
1156
- };
1119
+ const list = await this._store.listStudioAssignments(request.studioId, {
1120
+ userId: request.userId,
1121
+ role: 'admin',
1122
+ });
1123
+ if (list.length <= 0) {
1124
+ return {
1125
+ success: false,
1126
+ errorCode: 'not_authorized',
1127
+ errorMessage: 'You are not authorized to perform this operation.',
1128
+ };
1129
+ }
1130
+ let addedUserId = null;
1131
+ if (request.addedUserId) {
1132
+ addedUserId = request.addedUserId;
1133
+ }
1134
+ else if (request.addedEmail || request.addedPhoneNumber) {
1135
+ const addedUser = await this._auth.findUserByAddress((_a = request.addedEmail) !== null && _a !== void 0 ? _a : request.addedPhoneNumber, request.addedEmail ? 'email' : 'phone');
1136
+ if (addedUser) {
1137
+ addedUserId = addedUser.id;
1157
1138
  }
1158
- const list = yield this._store.listStudioAssignments(request.studioId, {
1159
- userId: request.userId,
1160
- role: 'admin',
1139
+ }
1140
+ if (!addedUserId &&
1141
+ this._privo &&
1142
+ (request.addedEmail ||
1143
+ request.addedPhoneNumber ||
1144
+ request.addedDisplayName)) {
1145
+ const privoServiceId = await this._privo.lookupServiceId({
1146
+ displayName: (_b = request.addedDisplayName) !== null && _b !== void 0 ? _b : undefined,
1147
+ email: (_c = request.addedEmail) !== null && _c !== void 0 ? _c : undefined,
1148
+ phoneNumber: (_d = request.addedPhoneNumber) !== null && _d !== void 0 ? _d : undefined,
1161
1149
  });
1162
- if (list.length <= 0) {
1150
+ if (privoServiceId) {
1151
+ const user = await this._auth.findUserByPrivoServiceId(privoServiceId);
1152
+ if (user) {
1153
+ addedUserId = user.id;
1154
+ }
1155
+ }
1156
+ }
1157
+ if (!addedUserId) {
1158
+ if (this._privo &&
1159
+ !request.addedEmail &&
1160
+ !request.addedPhoneNumber &&
1161
+ !request.addedUserId &&
1162
+ !request.addedDisplayName) {
1163
1163
  return {
1164
1164
  success: false,
1165
- errorCode: 'not_authorized',
1166
- errorMessage: 'You are not authorized to perform this operation.',
1165
+ errorCode: 'unacceptable_request',
1166
+ errorMessage: 'You must provide a display name, email, phone number, or user ID to add a studio member.',
1167
1167
  };
1168
1168
  }
1169
- let addedUserId = null;
1170
- if (request.addedUserId) {
1171
- addedUserId = request.addedUserId;
1172
- }
1173
- else if (request.addedEmail || request.addedPhoneNumber) {
1174
- const addedUser = yield this._auth.findUserByAddress((_a = request.addedEmail) !== null && _a !== void 0 ? _a : request.addedPhoneNumber, request.addedEmail ? 'email' : 'phone');
1175
- if (addedUser) {
1176
- addedUserId = addedUser.id;
1177
- }
1178
- }
1179
- if (!addedUserId &&
1180
- this._privo &&
1181
- (request.addedEmail ||
1182
- request.addedPhoneNumber ||
1183
- request.addedDisplayName)) {
1184
- const privoServiceId = yield this._privo.lookupServiceId({
1185
- displayName: (_b = request.addedDisplayName) !== null && _b !== void 0 ? _b : undefined,
1186
- email: (_c = request.addedEmail) !== null && _c !== void 0 ? _c : undefined,
1187
- phoneNumber: (_d = request.addedPhoneNumber) !== null && _d !== void 0 ? _d : undefined,
1188
- });
1189
- if (privoServiceId) {
1190
- const user = yield this._auth.findUserByPrivoServiceId(privoServiceId);
1191
- if (user) {
1192
- addedUserId = user.id;
1193
- }
1194
- }
1195
- }
1196
- if (!addedUserId) {
1197
- if (this._privo &&
1198
- !request.addedEmail &&
1199
- !request.addedPhoneNumber &&
1200
- !request.addedUserId &&
1201
- !request.addedDisplayName) {
1202
- return {
1203
- success: false,
1204
- errorCode: 'unacceptable_request',
1205
- errorMessage: 'You must provide a display name, email, phone number, or user ID to add a studio member.',
1206
- };
1207
- }
1208
- else if (!this._privo &&
1209
- !request.addedEmail &&
1210
- !request.addedPhoneNumber &&
1211
- !request.addedUserId) {
1212
- return {
1213
- success: false,
1214
- errorCode: 'unacceptable_request',
1215
- errorMessage: 'You must provide an email, phone number, or user ID to add a studio member.',
1216
- };
1217
- }
1169
+ else if (!this._privo &&
1170
+ !request.addedEmail &&
1171
+ !request.addedPhoneNumber &&
1172
+ !request.addedUserId) {
1218
1173
  return {
1219
1174
  success: false,
1220
- errorCode: 'user_not_found',
1221
- errorMessage: 'The user was not able to be found.',
1175
+ errorCode: 'unacceptable_request',
1176
+ errorMessage: 'You must provide an email, phone number, or user ID to add a studio member.',
1222
1177
  };
1223
1178
  }
1224
- yield this._store.addStudioAssignment({
1225
- studioId: request.studioId,
1226
- userId: addedUserId,
1227
- isPrimaryContact: false,
1228
- role: request.role,
1229
- });
1230
1179
  return {
1231
- success: true,
1180
+ success: false,
1181
+ errorCode: 'user_not_found',
1182
+ errorMessage: 'The user was not able to be found.',
1232
1183
  };
1233
1184
  }
1234
- catch (err) {
1235
- const span = trace.getActiveSpan();
1236
- span === null || span === void 0 ? void 0 : span.recordException(err);
1237
- span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
1238
- console.error('[RecordsController] [addStudioMember] An error occurred while adding a studio member:', err);
1185
+ await this._store.addStudioAssignment({
1186
+ studioId: request.studioId,
1187
+ userId: addedUserId,
1188
+ isPrimaryContact: false,
1189
+ role: request.role,
1190
+ });
1191
+ return {
1192
+ success: true,
1193
+ };
1194
+ }
1195
+ catch (err) {
1196
+ const span = trace.getActiveSpan();
1197
+ span === null || span === void 0 ? void 0 : span.recordException(err);
1198
+ span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
1199
+ console.error('[RecordsController] [addStudioMember] An error occurred while adding a studio member:', err);
1200
+ return {
1201
+ success: false,
1202
+ errorCode: 'server_error',
1203
+ errorMessage: 'A server error occurred.',
1204
+ };
1205
+ }
1206
+ }
1207
+ async removeStudioMember(request) {
1208
+ try {
1209
+ if (!request.userId) {
1239
1210
  return {
1240
1211
  success: false,
1241
- errorCode: 'server_error',
1242
- errorMessage: 'A server error occurred.',
1212
+ errorCode: 'not_logged_in',
1213
+ errorMessage: 'You must be logged in to remove a studio member.',
1243
1214
  };
1244
1215
  }
1245
- });
1246
- }
1247
- removeStudioMember(request) {
1248
- return __awaiter(this, void 0, void 0, function* () {
1249
- try {
1250
- if (!request.userId) {
1251
- return {
1252
- success: false,
1253
- errorCode: 'not_logged_in',
1254
- errorMessage: 'You must be logged in to remove a studio member.',
1255
- };
1256
- }
1257
- if (request.userId === request.removedUserId) {
1258
- return {
1259
- success: false,
1260
- errorCode: 'not_authorized',
1261
- errorMessage: 'You are not authorized to perform this operation.',
1262
- };
1263
- }
1264
- const list = yield this._store.listStudioAssignments(request.studioId, {
1265
- userId: request.userId,
1266
- role: 'admin',
1267
- });
1268
- if (list.length <= 0) {
1269
- return {
1270
- success: false,
1271
- errorCode: 'not_authorized',
1272
- errorMessage: 'You are not authorized to perform this operation.',
1273
- };
1274
- }
1275
- yield this._store.removeStudioAssignment(request.studioId, request.removedUserId);
1216
+ if (request.userId === request.removedUserId) {
1276
1217
  return {
1277
- success: true,
1218
+ success: false,
1219
+ errorCode: 'not_authorized',
1220
+ errorMessage: 'You are not authorized to perform this operation.',
1278
1221
  };
1279
1222
  }
1280
- catch (err) {
1281
- const span = trace.getActiveSpan();
1282
- span === null || span === void 0 ? void 0 : span.recordException(err);
1283
- span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
1284
- console.error('[RecordsController] [removeStudioMember] An error occurred while removing a studio member:', err);
1223
+ const list = await this._store.listStudioAssignments(request.studioId, {
1224
+ userId: request.userId,
1225
+ role: 'admin',
1226
+ });
1227
+ if (list.length <= 0) {
1285
1228
  return {
1286
1229
  success: false,
1287
- errorCode: 'server_error',
1288
- errorMessage: 'A server error occurred.',
1230
+ errorCode: 'not_authorized',
1231
+ errorMessage: 'You are not authorized to perform this operation.',
1289
1232
  };
1290
1233
  }
1291
- });
1234
+ await this._store.removeStudioAssignment(request.studioId, request.removedUserId);
1235
+ return {
1236
+ success: true,
1237
+ };
1238
+ }
1239
+ catch (err) {
1240
+ const span = trace.getActiveSpan();
1241
+ span === null || span === void 0 ? void 0 : span.recordException(err);
1242
+ span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
1243
+ console.error('[RecordsController] [removeStudioMember] An error occurred while removing a studio member:', err);
1244
+ return {
1245
+ success: false,
1246
+ errorCode: 'server_error',
1247
+ errorMessage: 'A server error occurred.',
1248
+ };
1249
+ }
1292
1250
  }
1293
- requestComId(request) {
1294
- return __awaiter(this, void 0, void 0, function* () {
1295
- try {
1296
- const existingStudio = yield this._store.getStudioById(request.studioId);
1297
- if (!existingStudio) {
1298
- return {
1299
- success: false,
1300
- errorCode: 'studio_not_found',
1301
- errorMessage: 'The given studio was not found.',
1302
- };
1303
- }
1304
- const assignments = yield this._store.listStudioAssignments(request.studioId, {
1305
- role: 'admin',
1306
- userId: request.userId,
1307
- });
1308
- if (assignments.length <= 0) {
1309
- return {
1310
- success: false,
1311
- errorCode: 'not_authorized',
1312
- errorMessage: 'You are not authorized to perform this operation.',
1313
- };
1314
- }
1315
- const existingComIdStudio = yield this._store.getStudioByComId(request.requestedComId);
1316
- if (existingComIdStudio) {
1317
- return {
1318
- success: false,
1319
- errorCode: 'comId_already_taken',
1320
- errorMessage: 'The given comID is already taken.',
1321
- };
1322
- }
1323
- const id = uuid();
1324
- const now = Date.now();
1325
- const comIdRequest = {
1326
- id,
1327
- userId: request.userId,
1328
- studioId: request.studioId,
1329
- requestingIpAddress: request.ipAddress,
1330
- requestedComId: request.requestedComId,
1331
- createdAtMs: now,
1332
- updatedAtMs: now,
1251
+ async requestComId(request) {
1252
+ try {
1253
+ const existingStudio = await this._store.getStudioById(request.studioId);
1254
+ if (!existingStudio) {
1255
+ return {
1256
+ success: false,
1257
+ errorCode: 'studio_not_found',
1258
+ errorMessage: 'The given studio was not found.',
1333
1259
  };
1334
- yield this._store.saveComIdRequest(comIdRequest);
1335
- if (this._messenger) {
1336
- yield this._messenger.sendRecordNotification({
1337
- timeMs: now,
1338
- resource: 'studio_com_id_request',
1339
- action: 'created',
1340
- recordName: null,
1341
- resourceId: comIdRequest.studioId,
1342
- request: comIdRequest,
1343
- });
1344
- }
1260
+ }
1261
+ const assignments = await this._store.listStudioAssignments(request.studioId, {
1262
+ role: 'admin',
1263
+ userId: request.userId,
1264
+ });
1265
+ if (assignments.length <= 0) {
1345
1266
  return {
1346
- success: true,
1267
+ success: false,
1268
+ errorCode: 'not_authorized',
1269
+ errorMessage: 'You are not authorized to perform this operation.',
1347
1270
  };
1348
1271
  }
1349
- catch (err) {
1350
- const span = trace.getActiveSpan();
1351
- span === null || span === void 0 ? void 0 : span.recordException(err);
1352
- span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
1353
- console.error('[RecordsController] [requestComId] An error occurred while requesting a comId:', err);
1272
+ const existingComIdStudio = await this._store.getStudioByComId(request.requestedComId);
1273
+ if (existingComIdStudio) {
1354
1274
  return {
1355
1275
  success: false,
1356
- errorCode: 'server_error',
1357
- errorMessage: 'A server error occurred.',
1276
+ errorCode: 'comId_already_taken',
1277
+ errorMessage: 'The given comID is already taken.',
1358
1278
  };
1359
1279
  }
1360
- });
1280
+ const id = uuid();
1281
+ const now = Date.now();
1282
+ const comIdRequest = {
1283
+ id,
1284
+ userId: request.userId,
1285
+ studioId: request.studioId,
1286
+ requestingIpAddress: request.ipAddress,
1287
+ requestedComId: request.requestedComId,
1288
+ createdAtMs: now,
1289
+ updatedAtMs: now,
1290
+ };
1291
+ await this._store.saveComIdRequest(comIdRequest);
1292
+ if (this._messenger) {
1293
+ await this._messenger.sendRecordNotification({
1294
+ timeMs: now,
1295
+ resource: 'studio_com_id_request',
1296
+ action: 'created',
1297
+ recordName: null,
1298
+ resourceId: comIdRequest.studioId,
1299
+ request: comIdRequest,
1300
+ });
1301
+ }
1302
+ return {
1303
+ success: true,
1304
+ };
1305
+ }
1306
+ catch (err) {
1307
+ const span = trace.getActiveSpan();
1308
+ span === null || span === void 0 ? void 0 : span.recordException(err);
1309
+ span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
1310
+ console.error('[RecordsController] [requestComId] An error occurred while requesting a comId:', err);
1311
+ return {
1312
+ success: false,
1313
+ errorCode: 'server_error',
1314
+ errorMessage: 'A server error occurred.',
1315
+ };
1316
+ }
1361
1317
  }
1362
1318
  _createSalt() {
1363
1319
  return fromByteArray(randomBytes(16));
@@ -1420,116 +1376,4 @@ __decorate([
1420
1376
  __decorate([
1421
1377
  traced(TRACE_NAME)
1422
1378
  ], RecordsController.prototype, "_createSalt", null);
1423
- /**
1424
- * The default policy for keys that do not have a specified record key.
1425
- */
1426
- export const DEFAULT_RECORD_KEY_POLICY = 'subjectfull';
1427
- /**
1428
- * Formats the given record name and record secret into a record key.
1429
- * @param recordName The name of the record.
1430
- * @param recordSecret The secret that is used to access the record.
1431
- */
1432
- export function formatV1RecordKey(recordName, recordSecret) {
1433
- return `vRK1.${toBase64String(recordName)}.${toBase64String(recordSecret)}`;
1434
- }
1435
- /**
1436
- * Formats the given record name and record secret into a record key.
1437
- * @param recordName The name of the record.
1438
- * @param recordSecret The secret that is used to access the record.
1439
- * @param keyPolicy The policy that the key uses.
1440
- */
1441
- export function formatV2RecordKey(recordName, recordSecret, keyPolicy) {
1442
- return `vRK2.${toBase64String(recordName)}.${toBase64String(recordSecret)}.${keyPolicy !== null && keyPolicy !== void 0 ? keyPolicy : DEFAULT_RECORD_KEY_POLICY}`;
1443
- }
1444
- /**
1445
- * Parses the given record key into a name and password pair.
1446
- * Returns null if the key cannot be parsed.
1447
- * @param key The key to parse.
1448
- */
1449
- export function parseRecordKey(key) {
1450
- var _a;
1451
- return (_a = parseV2RecordKey(key)) !== null && _a !== void 0 ? _a : parseV1RecordKey(key);
1452
- }
1453
- /**
1454
- * Parses a version 2 record key into a name, password, and policy trio.
1455
- * Returns null if the key cannot be parsed or if it is not a V2 key.
1456
- * @param key The key to parse.
1457
- */
1458
- export function parseV2RecordKey(key) {
1459
- if (!key) {
1460
- return null;
1461
- }
1462
- if (!key.startsWith('vRK2.')) {
1463
- return null;
1464
- }
1465
- const withoutVersion = key.slice('vRK2.'.length);
1466
- let periodAfterName = withoutVersion.indexOf('.');
1467
- if (periodAfterName < 0) {
1468
- return null;
1469
- }
1470
- const nameBase64 = withoutVersion.slice(0, periodAfterName);
1471
- const passwordPlusPolicy = withoutVersion.slice(periodAfterName + 1);
1472
- if (nameBase64.length <= 0 || passwordPlusPolicy.length <= 0) {
1473
- return null;
1474
- }
1475
- const periodAfterPassword = passwordPlusPolicy.indexOf('.');
1476
- if (periodAfterPassword < 0) {
1477
- return null;
1478
- }
1479
- const passwordBase64 = passwordPlusPolicy.slice(0, periodAfterPassword);
1480
- const policy = passwordPlusPolicy.slice(periodAfterPassword + 1);
1481
- if (passwordBase64.length <= 0 || policy.length <= 0) {
1482
- return null;
1483
- }
1484
- if (policy !== 'subjectfull' && policy !== 'subjectless') {
1485
- return null;
1486
- }
1487
- try {
1488
- const name = fromBase64String(nameBase64);
1489
- const password = fromBase64String(passwordBase64);
1490
- return [name, password, policy];
1491
- }
1492
- catch (err) {
1493
- return null;
1494
- }
1495
- }
1496
- /**
1497
- * Parses a version 1 record key into a name and password pair.
1498
- * Returns null if the key cannot be parsed or if it is not a V1 key.
1499
- * @param key The key to parse.
1500
- */
1501
- export function parseV1RecordKey(key) {
1502
- if (!key) {
1503
- return null;
1504
- }
1505
- if (!key.startsWith('vRK1.')) {
1506
- return null;
1507
- }
1508
- const withoutVersion = key.slice('vRK1.'.length);
1509
- let nextPeriod = withoutVersion.indexOf('.');
1510
- if (nextPeriod < 0) {
1511
- return null;
1512
- }
1513
- const nameBase64 = withoutVersion.slice(0, nextPeriod);
1514
- const passwordBase64 = withoutVersion.slice(nextPeriod + 1);
1515
- if (nameBase64.length <= 0 || passwordBase64.length <= 0) {
1516
- return null;
1517
- }
1518
- try {
1519
- const name = fromBase64String(nameBase64);
1520
- const password = fromBase64String(passwordBase64);
1521
- return [name, password, DEFAULT_RECORD_KEY_POLICY];
1522
- }
1523
- catch (err) {
1524
- return null;
1525
- }
1526
- }
1527
- /**
1528
- * Determines if the given value is a record key.
1529
- * @param key The value to check.
1530
- * @returns
1531
- */
1532
- export function isRecordKey(key) {
1533
- return typeof key === 'string' && parseRecordKey(key) !== null;
1534
- }
1535
1379
  //# sourceMappingURL=RecordsController.js.map