@memberjunction/server 3.1.0 → 3.2.0

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.
@@ -10,9 +10,9 @@ var __metadata = (this && this.__metadata) || function (k, v) {
10
10
  var __param = (this && this.__param) || function (paramIndex, decorator) {
11
11
  return function (target, key) { decorator(target, key, paramIndex); }
12
12
  };
13
- import { EntityPermissionType, Metadata, FieldValueCollection } from '@memberjunction/core';
14
- import { Arg, Ctx, DeleteOptionsInput, Field, FieldResolver, InputType, Mutation, ObjectType, PubSub, PubSubEngine, Resolver, Root, } from '@memberjunction/server';
15
- import { createDownloadUrl, createUploadUrl, deleteObject, moveObject } from '@memberjunction/storage';
13
+ import { EntityPermissionType, Metadata, FieldValueCollection, RunView } from '@memberjunction/core';
14
+ import { Arg, Ctx, DeleteOptionsInput, Field, FieldResolver, InputType, Int, Mutation, ObjectType, PubSub, PubSubEngine, Query, Resolver, Root, } from '@memberjunction/server';
15
+ import { createDownloadUrl, createUploadUrl, deleteObject, moveObject, copyObject, listObjects, copyObjectBetweenProviders, searchAcrossAccounts, initializeDriverWithAccountCredentials, } from '@memberjunction/storage';
16
16
  import { CreateMJFileInput, MJFileResolver as FileResolverBase, MJFile_, UpdateMJFileInput } from '../generated/generated.js';
17
17
  import { FieldMapper } from '@memberjunction/graphql-dataprovider';
18
18
  import { GetReadOnlyProvider } from '../util.js';
@@ -59,7 +59,470 @@ FileExt = __decorate([
59
59
  ObjectType()
60
60
  ], FileExt);
61
61
  export { FileExt };
62
+ let StorageObjectMetadata = class StorageObjectMetadata {
63
+ name;
64
+ path;
65
+ fullPath;
66
+ size;
67
+ contentType;
68
+ lastModified;
69
+ isDirectory;
70
+ etag;
71
+ cacheControl;
72
+ };
73
+ __decorate([
74
+ Field(() => String),
75
+ __metadata("design:type", String)
76
+ ], StorageObjectMetadata.prototype, "name", void 0);
77
+ __decorate([
78
+ Field(() => String),
79
+ __metadata("design:type", String)
80
+ ], StorageObjectMetadata.prototype, "path", void 0);
81
+ __decorate([
82
+ Field(() => String),
83
+ __metadata("design:type", String)
84
+ ], StorageObjectMetadata.prototype, "fullPath", void 0);
85
+ __decorate([
86
+ Field(() => Int),
87
+ __metadata("design:type", Number)
88
+ ], StorageObjectMetadata.prototype, "size", void 0);
89
+ __decorate([
90
+ Field(() => String),
91
+ __metadata("design:type", String)
92
+ ], StorageObjectMetadata.prototype, "contentType", void 0);
93
+ __decorate([
94
+ Field(() => String),
95
+ __metadata("design:type", String)
96
+ ], StorageObjectMetadata.prototype, "lastModified", void 0);
97
+ __decorate([
98
+ Field(() => Boolean),
99
+ __metadata("design:type", Boolean)
100
+ ], StorageObjectMetadata.prototype, "isDirectory", void 0);
101
+ __decorate([
102
+ Field(() => String, { nullable: true }),
103
+ __metadata("design:type", String)
104
+ ], StorageObjectMetadata.prototype, "etag", void 0);
105
+ __decorate([
106
+ Field(() => String, { nullable: true }),
107
+ __metadata("design:type", String)
108
+ ], StorageObjectMetadata.prototype, "cacheControl", void 0);
109
+ StorageObjectMetadata = __decorate([
110
+ ObjectType()
111
+ ], StorageObjectMetadata);
112
+ export { StorageObjectMetadata };
113
+ let StorageListResult = class StorageListResult {
114
+ objects;
115
+ prefixes;
116
+ };
117
+ __decorate([
118
+ Field(() => [StorageObjectMetadata]),
119
+ __metadata("design:type", Array)
120
+ ], StorageListResult.prototype, "objects", void 0);
121
+ __decorate([
122
+ Field(() => [String]),
123
+ __metadata("design:type", Array)
124
+ ], StorageListResult.prototype, "prefixes", void 0);
125
+ StorageListResult = __decorate([
126
+ ObjectType()
127
+ ], StorageListResult);
128
+ export { StorageListResult };
129
+ let ListStorageObjectsInput = class ListStorageObjectsInput {
130
+ AccountID;
131
+ Prefix;
132
+ Delimiter;
133
+ };
134
+ __decorate([
135
+ Field(() => String),
136
+ __metadata("design:type", String)
137
+ ], ListStorageObjectsInput.prototype, "AccountID", void 0);
138
+ __decorate([
139
+ Field(() => String),
140
+ __metadata("design:type", String)
141
+ ], ListStorageObjectsInput.prototype, "Prefix", void 0);
142
+ __decorate([
143
+ Field(() => String, { nullable: true }),
144
+ __metadata("design:type", String)
145
+ ], ListStorageObjectsInput.prototype, "Delimiter", void 0);
146
+ ListStorageObjectsInput = __decorate([
147
+ InputType()
148
+ ], ListStorageObjectsInput);
149
+ export { ListStorageObjectsInput };
150
+ let CreatePreAuthDownloadUrlInput = class CreatePreAuthDownloadUrlInput {
151
+ AccountID;
152
+ ObjectName;
153
+ };
154
+ __decorate([
155
+ Field(() => String),
156
+ __metadata("design:type", String)
157
+ ], CreatePreAuthDownloadUrlInput.prototype, "AccountID", void 0);
158
+ __decorate([
159
+ Field(() => String),
160
+ __metadata("design:type", String)
161
+ ], CreatePreAuthDownloadUrlInput.prototype, "ObjectName", void 0);
162
+ CreatePreAuthDownloadUrlInput = __decorate([
163
+ InputType()
164
+ ], CreatePreAuthDownloadUrlInput);
165
+ export { CreatePreAuthDownloadUrlInput };
166
+ let CreatePreAuthUploadUrlInput = class CreatePreAuthUploadUrlInput {
167
+ AccountID;
168
+ ObjectName;
169
+ ContentType;
170
+ };
171
+ __decorate([
172
+ Field(() => String),
173
+ __metadata("design:type", String)
174
+ ], CreatePreAuthUploadUrlInput.prototype, "AccountID", void 0);
175
+ __decorate([
176
+ Field(() => String),
177
+ __metadata("design:type", String)
178
+ ], CreatePreAuthUploadUrlInput.prototype, "ObjectName", void 0);
179
+ __decorate([
180
+ Field(() => String, { nullable: true }),
181
+ __metadata("design:type", String)
182
+ ], CreatePreAuthUploadUrlInput.prototype, "ContentType", void 0);
183
+ CreatePreAuthUploadUrlInput = __decorate([
184
+ InputType()
185
+ ], CreatePreAuthUploadUrlInput);
186
+ export { CreatePreAuthUploadUrlInput };
187
+ let CreatePreAuthUploadUrlPayload = class CreatePreAuthUploadUrlPayload {
188
+ UploadUrl;
189
+ ProviderKey;
190
+ };
191
+ __decorate([
192
+ Field(() => String),
193
+ __metadata("design:type", String)
194
+ ], CreatePreAuthUploadUrlPayload.prototype, "UploadUrl", void 0);
195
+ __decorate([
196
+ Field(() => String, { nullable: true }),
197
+ __metadata("design:type", String)
198
+ ], CreatePreAuthUploadUrlPayload.prototype, "ProviderKey", void 0);
199
+ CreatePreAuthUploadUrlPayload = __decorate([
200
+ ObjectType()
201
+ ], CreatePreAuthUploadUrlPayload);
202
+ export { CreatePreAuthUploadUrlPayload };
203
+ let DeleteStorageObjectInput = class DeleteStorageObjectInput {
204
+ AccountID;
205
+ ObjectName;
206
+ };
207
+ __decorate([
208
+ Field(() => String),
209
+ __metadata("design:type", String)
210
+ ], DeleteStorageObjectInput.prototype, "AccountID", void 0);
211
+ __decorate([
212
+ Field(() => String),
213
+ __metadata("design:type", String)
214
+ ], DeleteStorageObjectInput.prototype, "ObjectName", void 0);
215
+ DeleteStorageObjectInput = __decorate([
216
+ InputType()
217
+ ], DeleteStorageObjectInput);
218
+ export { DeleteStorageObjectInput };
219
+ let MoveStorageObjectInput = class MoveStorageObjectInput {
220
+ AccountID;
221
+ OldName;
222
+ NewName;
223
+ };
224
+ __decorate([
225
+ Field(() => String),
226
+ __metadata("design:type", String)
227
+ ], MoveStorageObjectInput.prototype, "AccountID", void 0);
228
+ __decorate([
229
+ Field(() => String),
230
+ __metadata("design:type", String)
231
+ ], MoveStorageObjectInput.prototype, "OldName", void 0);
232
+ __decorate([
233
+ Field(() => String),
234
+ __metadata("design:type", String)
235
+ ], MoveStorageObjectInput.prototype, "NewName", void 0);
236
+ MoveStorageObjectInput = __decorate([
237
+ InputType()
238
+ ], MoveStorageObjectInput);
239
+ export { MoveStorageObjectInput };
240
+ let CopyStorageObjectInput = class CopyStorageObjectInput {
241
+ AccountID;
242
+ SourceName;
243
+ DestinationName;
244
+ };
245
+ __decorate([
246
+ Field(() => String),
247
+ __metadata("design:type", String)
248
+ ], CopyStorageObjectInput.prototype, "AccountID", void 0);
249
+ __decorate([
250
+ Field(() => String),
251
+ __metadata("design:type", String)
252
+ ], CopyStorageObjectInput.prototype, "SourceName", void 0);
253
+ __decorate([
254
+ Field(() => String),
255
+ __metadata("design:type", String)
256
+ ], CopyStorageObjectInput.prototype, "DestinationName", void 0);
257
+ CopyStorageObjectInput = __decorate([
258
+ InputType()
259
+ ], CopyStorageObjectInput);
260
+ export { CopyStorageObjectInput };
261
+ let CreateDirectoryInput = class CreateDirectoryInput {
262
+ AccountID;
263
+ Path;
264
+ };
265
+ __decorate([
266
+ Field(() => String),
267
+ __metadata("design:type", String)
268
+ ], CreateDirectoryInput.prototype, "AccountID", void 0);
269
+ __decorate([
270
+ Field(() => String),
271
+ __metadata("design:type", String)
272
+ ], CreateDirectoryInput.prototype, "Path", void 0);
273
+ CreateDirectoryInput = __decorate([
274
+ InputType()
275
+ ], CreateDirectoryInput);
276
+ export { CreateDirectoryInput };
277
+ let CopyObjectBetweenAccountsInput = class CopyObjectBetweenAccountsInput {
278
+ SourceAccountID;
279
+ DestinationAccountID;
280
+ SourcePath;
281
+ DestinationPath;
282
+ };
283
+ __decorate([
284
+ Field(() => String),
285
+ __metadata("design:type", String)
286
+ ], CopyObjectBetweenAccountsInput.prototype, "SourceAccountID", void 0);
287
+ __decorate([
288
+ Field(() => String),
289
+ __metadata("design:type", String)
290
+ ], CopyObjectBetweenAccountsInput.prototype, "DestinationAccountID", void 0);
291
+ __decorate([
292
+ Field(() => String),
293
+ __metadata("design:type", String)
294
+ ], CopyObjectBetweenAccountsInput.prototype, "SourcePath", void 0);
295
+ __decorate([
296
+ Field(() => String),
297
+ __metadata("design:type", String)
298
+ ], CopyObjectBetweenAccountsInput.prototype, "DestinationPath", void 0);
299
+ CopyObjectBetweenAccountsInput = __decorate([
300
+ InputType()
301
+ ], CopyObjectBetweenAccountsInput);
302
+ export { CopyObjectBetweenAccountsInput };
303
+ let CopyObjectBetweenAccountsPayload = class CopyObjectBetweenAccountsPayload {
304
+ success;
305
+ message;
306
+ bytesTransferred;
307
+ sourceAccount;
308
+ destinationAccount;
309
+ sourcePath;
310
+ destinationPath;
311
+ };
312
+ __decorate([
313
+ Field(() => Boolean),
314
+ __metadata("design:type", Boolean)
315
+ ], CopyObjectBetweenAccountsPayload.prototype, "success", void 0);
316
+ __decorate([
317
+ Field(() => String),
318
+ __metadata("design:type", String)
319
+ ], CopyObjectBetweenAccountsPayload.prototype, "message", void 0);
320
+ __decorate([
321
+ Field(() => Int, { nullable: true }),
322
+ __metadata("design:type", Number)
323
+ ], CopyObjectBetweenAccountsPayload.prototype, "bytesTransferred", void 0);
324
+ __decorate([
325
+ Field(() => String),
326
+ __metadata("design:type", String)
327
+ ], CopyObjectBetweenAccountsPayload.prototype, "sourceAccount", void 0);
328
+ __decorate([
329
+ Field(() => String),
330
+ __metadata("design:type", String)
331
+ ], CopyObjectBetweenAccountsPayload.prototype, "destinationAccount", void 0);
332
+ __decorate([
333
+ Field(() => String),
334
+ __metadata("design:type", String)
335
+ ], CopyObjectBetweenAccountsPayload.prototype, "sourcePath", void 0);
336
+ __decorate([
337
+ Field(() => String),
338
+ __metadata("design:type", String)
339
+ ], CopyObjectBetweenAccountsPayload.prototype, "destinationPath", void 0);
340
+ CopyObjectBetweenAccountsPayload = __decorate([
341
+ ObjectType()
342
+ ], CopyObjectBetweenAccountsPayload);
343
+ export { CopyObjectBetweenAccountsPayload };
344
+ let SearchAcrossAccountsInput = class SearchAcrossAccountsInput {
345
+ AccountIDs;
346
+ Query;
347
+ MaxResultsPerAccount;
348
+ FileTypes;
349
+ SearchContent;
350
+ };
351
+ __decorate([
352
+ Field(() => [String]),
353
+ __metadata("design:type", Array)
354
+ ], SearchAcrossAccountsInput.prototype, "AccountIDs", void 0);
355
+ __decorate([
356
+ Field(() => String),
357
+ __metadata("design:type", String)
358
+ ], SearchAcrossAccountsInput.prototype, "Query", void 0);
359
+ __decorate([
360
+ Field(() => Int, { nullable: true }),
361
+ __metadata("design:type", Number)
362
+ ], SearchAcrossAccountsInput.prototype, "MaxResultsPerAccount", void 0);
363
+ __decorate([
364
+ Field(() => [String], { nullable: true }),
365
+ __metadata("design:type", Array)
366
+ ], SearchAcrossAccountsInput.prototype, "FileTypes", void 0);
367
+ __decorate([
368
+ Field(() => Boolean, { nullable: true }),
369
+ __metadata("design:type", Boolean)
370
+ ], SearchAcrossAccountsInput.prototype, "SearchContent", void 0);
371
+ SearchAcrossAccountsInput = __decorate([
372
+ InputType()
373
+ ], SearchAcrossAccountsInput);
374
+ export { SearchAcrossAccountsInput };
375
+ let FileSearchResultPayload = class FileSearchResultPayload {
376
+ path;
377
+ name;
378
+ size;
379
+ contentType;
380
+ lastModified;
381
+ relevance;
382
+ excerpt;
383
+ matchInFilename;
384
+ objectId;
385
+ };
386
+ __decorate([
387
+ Field(() => String),
388
+ __metadata("design:type", String)
389
+ ], FileSearchResultPayload.prototype, "path", void 0);
390
+ __decorate([
391
+ Field(() => String),
392
+ __metadata("design:type", String)
393
+ ], FileSearchResultPayload.prototype, "name", void 0);
394
+ __decorate([
395
+ Field(() => Int),
396
+ __metadata("design:type", Number)
397
+ ], FileSearchResultPayload.prototype, "size", void 0);
398
+ __decorate([
399
+ Field(() => String),
400
+ __metadata("design:type", String)
401
+ ], FileSearchResultPayload.prototype, "contentType", void 0);
402
+ __decorate([
403
+ Field(() => String),
404
+ __metadata("design:type", String)
405
+ ], FileSearchResultPayload.prototype, "lastModified", void 0);
406
+ __decorate([
407
+ Field(() => Number, { nullable: true }),
408
+ __metadata("design:type", Number)
409
+ ], FileSearchResultPayload.prototype, "relevance", void 0);
410
+ __decorate([
411
+ Field(() => String, { nullable: true }),
412
+ __metadata("design:type", String)
413
+ ], FileSearchResultPayload.prototype, "excerpt", void 0);
414
+ __decorate([
415
+ Field(() => Boolean, { nullable: true }),
416
+ __metadata("design:type", Boolean)
417
+ ], FileSearchResultPayload.prototype, "matchInFilename", void 0);
418
+ __decorate([
419
+ Field(() => String, { nullable: true }),
420
+ __metadata("design:type", String)
421
+ ], FileSearchResultPayload.prototype, "objectId", void 0);
422
+ FileSearchResultPayload = __decorate([
423
+ ObjectType()
424
+ ], FileSearchResultPayload);
425
+ export { FileSearchResultPayload };
426
+ let AccountSearchResultPayload = class AccountSearchResultPayload {
427
+ accountID;
428
+ accountName;
429
+ success;
430
+ errorMessage;
431
+ results;
432
+ totalMatches;
433
+ hasMore;
434
+ nextPageToken;
435
+ };
436
+ __decorate([
437
+ Field(() => String),
438
+ __metadata("design:type", String)
439
+ ], AccountSearchResultPayload.prototype, "accountID", void 0);
440
+ __decorate([
441
+ Field(() => String),
442
+ __metadata("design:type", String)
443
+ ], AccountSearchResultPayload.prototype, "accountName", void 0);
444
+ __decorate([
445
+ Field(() => Boolean),
446
+ __metadata("design:type", Boolean)
447
+ ], AccountSearchResultPayload.prototype, "success", void 0);
448
+ __decorate([
449
+ Field(() => String, { nullable: true }),
450
+ __metadata("design:type", String)
451
+ ], AccountSearchResultPayload.prototype, "errorMessage", void 0);
452
+ __decorate([
453
+ Field(() => [FileSearchResultPayload]),
454
+ __metadata("design:type", Array)
455
+ ], AccountSearchResultPayload.prototype, "results", void 0);
456
+ __decorate([
457
+ Field(() => Int, { nullable: true }),
458
+ __metadata("design:type", Number)
459
+ ], AccountSearchResultPayload.prototype, "totalMatches", void 0);
460
+ __decorate([
461
+ Field(() => Boolean),
462
+ __metadata("design:type", Boolean)
463
+ ], AccountSearchResultPayload.prototype, "hasMore", void 0);
464
+ __decorate([
465
+ Field(() => String, { nullable: true }),
466
+ __metadata("design:type", String)
467
+ ], AccountSearchResultPayload.prototype, "nextPageToken", void 0);
468
+ AccountSearchResultPayload = __decorate([
469
+ ObjectType()
470
+ ], AccountSearchResultPayload);
471
+ export { AccountSearchResultPayload };
472
+ let SearchAcrossAccountsPayload = class SearchAcrossAccountsPayload {
473
+ accountResults;
474
+ totalResultsReturned;
475
+ successfulAccounts;
476
+ failedAccounts;
477
+ };
478
+ __decorate([
479
+ Field(() => [AccountSearchResultPayload]),
480
+ __metadata("design:type", Array)
481
+ ], SearchAcrossAccountsPayload.prototype, "accountResults", void 0);
482
+ __decorate([
483
+ Field(() => Int),
484
+ __metadata("design:type", Number)
485
+ ], SearchAcrossAccountsPayload.prototype, "totalResultsReturned", void 0);
486
+ __decorate([
487
+ Field(() => Int),
488
+ __metadata("design:type", Number)
489
+ ], SearchAcrossAccountsPayload.prototype, "successfulAccounts", void 0);
490
+ __decorate([
491
+ Field(() => Int),
492
+ __metadata("design:type", Number)
493
+ ], SearchAcrossAccountsPayload.prototype, "failedAccounts", void 0);
494
+ SearchAcrossAccountsPayload = __decorate([
495
+ ObjectType()
496
+ ], SearchAcrossAccountsPayload);
497
+ export { SearchAcrossAccountsPayload };
62
498
  let FileResolver = class FileResolver extends FileResolverBase {
499
+ buildUserContext(context) {
500
+ const user = this.GetUserFromPayload(context.userPayload);
501
+ return {
502
+ userID: user.ID,
503
+ contextUser: user,
504
+ };
505
+ }
506
+ buildExtendedUserContext(context, accountEntity) {
507
+ const user = this.GetUserFromPayload(context.userPayload);
508
+ return {
509
+ userID: user.ID,
510
+ contextUser: user,
511
+ accountEntity,
512
+ };
513
+ }
514
+ async loadAccountAndProvider(accountId, context) {
515
+ const md = GetReadOnlyProvider(context.providers, { allowFallbackToReadWrite: true });
516
+ const user = this.GetUserFromPayload(context.userPayload);
517
+ const account = await md.GetEntityObject('MJ: File Storage Accounts', user);
518
+ const loaded = await account.Load(accountId);
519
+ if (!loaded) {
520
+ throw new Error(`Storage account with ID ${accountId} not found`);
521
+ }
522
+ const provider = await md.GetEntityObject('File Storage Providers', user);
523
+ await provider.Load(account.ProviderID);
524
+ return { account, provider };
525
+ }
63
526
  async CreateFile(input, context, pubSub) {
64
527
  const provider = GetReadOnlyProvider(context.providers, { allowFallbackToReadWrite: true });
65
528
  const user = this.GetUserFromPayload(context.userPayload);
@@ -72,21 +535,23 @@ let FileResolver = class FileResolver extends FileResolverBase {
72
535
  if (!success) {
73
536
  return null;
74
537
  }
75
- const { updatedInput, UploadUrl } = await createUploadUrl(providerEntity, fileEntity);
538
+ const userContext = this.buildUserContext(context);
539
+ const { updatedInput, UploadUrl } = await createUploadUrl(providerEntity, fileEntity, userContext);
76
540
  const mapper = new FieldMapper();
77
541
  fileEntity.SetMany(mapper.ReverseMapFields({ ...updatedInput }), true, true);
78
542
  await fileEntity.Save();
79
543
  const File = mapper.MapFields({ ...fileEntity.GetAll() });
80
544
  return { File, UploadUrl, NameExists };
81
545
  }
82
- async DownloadUrl(file, { userPayload }) {
546
+ async DownloadUrl(file, context) {
83
547
  const md = new Metadata();
84
- const user = this.GetUserFromPayload(userPayload);
548
+ const user = this.GetUserFromPayload(context.userPayload);
85
549
  const fileEntity = await md.GetEntityObject('Files', user);
86
550
  fileEntity.CheckPermissions(EntityPermissionType.Read, true);
87
551
  const providerEntity = await md.GetEntityObject('File Storage Providers', user);
88
552
  await providerEntity.Load(file.ProviderID);
89
- const url = await createDownloadUrl(providerEntity, file.ProviderKey ?? file.Name);
553
+ const userContext = this.buildUserContext(context);
554
+ const url = await createDownloadUrl(providerEntity, file.ProviderKey ?? file.Name, userContext);
90
555
  return url;
91
556
  }
92
557
  async UpdateFile(input, context, pubSub) {
@@ -98,7 +563,8 @@ let FileResolver = class FileResolver extends FileResolverBase {
98
563
  if (fileEntity.Name !== input.Name) {
99
564
  const providerEntity = await md.GetEntityObject('File Storage Providers', user);
100
565
  await providerEntity.Load(fileEntity.ProviderID);
101
- const success = await moveObject(providerEntity, fileEntity.Name, input.Name);
566
+ const userContext = this.buildUserContext(context);
567
+ const success = await moveObject(providerEntity, fileEntity.Name, input.Name, userContext);
102
568
  if (!success) {
103
569
  throw new Error('Error updating object name');
104
570
  }
@@ -118,10 +584,247 @@ let FileResolver = class FileResolver extends FileResolverBase {
118
584
  if (fileEntity.Status === 'Uploaded') {
119
585
  const providerEntity = await md.GetEntityObject('File Storage Providers', userInfo);
120
586
  await providerEntity.Load(fileEntity.ProviderID);
121
- await deleteObject(providerEntity, fileEntity.ProviderKey ?? fileEntity.Name);
587
+ const userContext = this.buildUserContext(context);
588
+ await deleteObject(providerEntity, fileEntity.ProviderKey ?? fileEntity.Name, userContext);
122
589
  }
123
590
  return super.DeleteMJFile(ID, options, context, pubSub);
124
591
  }
592
+ async ListStorageObjects(input, context) {
593
+ console.log('[FileResolver] ListStorageObjects called with:', {
594
+ AccountID: input.AccountID,
595
+ Prefix: input.Prefix,
596
+ Delimiter: input.Delimiter,
597
+ });
598
+ const md = GetReadOnlyProvider(context.providers, { allowFallbackToReadWrite: true });
599
+ const user = this.GetUserFromPayload(context.userPayload);
600
+ const { account, provider: providerEntity } = await this.loadAccountAndProvider(input.AccountID, context);
601
+ console.log('[FileResolver] Provider loaded:', {
602
+ Name: providerEntity.Name,
603
+ ServerDriverKey: providerEntity.ServerDriverKey,
604
+ HasConfiguration: !!providerEntity.Get('Configuration'),
605
+ });
606
+ const fileEntity = await md.GetEntityObject('Files', user);
607
+ fileEntity.CheckPermissions(EntityPermissionType.Read, true);
608
+ const userContext = this.buildExtendedUserContext(context, account);
609
+ const result = await listObjects(providerEntity, input.Prefix, input.Delimiter || '/', userContext);
610
+ console.log('[FileResolver] listObjects result:', {
611
+ objectsCount: result.objects.length,
612
+ prefixesCount: result.prefixes.length,
613
+ objects: result.objects.map((o) => ({ name: o.name, isDirectory: o.isDirectory })),
614
+ prefixes: result.prefixes,
615
+ });
616
+ const objects = result.objects.map((obj) => ({
617
+ ...obj,
618
+ lastModified: obj.lastModified.toISOString(),
619
+ }));
620
+ return {
621
+ objects,
622
+ prefixes: result.prefixes,
623
+ };
624
+ }
625
+ async CreatePreAuthDownloadUrl(input, context) {
626
+ const md = GetReadOnlyProvider(context.providers, { allowFallbackToReadWrite: true });
627
+ const user = this.GetUserFromPayload(context.userPayload);
628
+ const { account, provider: providerEntity } = await this.loadAccountAndProvider(input.AccountID, context);
629
+ const fileEntity = await md.GetEntityObject('Files', user);
630
+ fileEntity.CheckPermissions(EntityPermissionType.Read, true);
631
+ const userContext = this.buildExtendedUserContext(context, account);
632
+ const downloadUrl = await createDownloadUrl(providerEntity, input.ObjectName, userContext);
633
+ return downloadUrl;
634
+ }
635
+ async CreatePreAuthUploadUrl(input, context) {
636
+ const md = GetReadOnlyProvider(context.providers, { allowFallbackToReadWrite: true });
637
+ const user = this.GetUserFromPayload(context.userPayload);
638
+ const { account, provider: providerEntity } = await this.loadAccountAndProvider(input.AccountID, context);
639
+ const fileEntity = await md.GetEntityObject('Files', user);
640
+ fileEntity.CheckPermissions(EntityPermissionType.Create, true);
641
+ const userContext = this.buildExtendedUserContext(context, account);
642
+ const { UploadUrl, updatedInput } = await createUploadUrl(providerEntity, {
643
+ ID: '',
644
+ Name: input.ObjectName,
645
+ ProviderID: providerEntity.ID,
646
+ ContentType: input.ContentType,
647
+ }, userContext);
648
+ const providerKey = updatedInput.ProviderKey;
649
+ return {
650
+ UploadUrl,
651
+ ProviderKey: providerKey,
652
+ };
653
+ }
654
+ async DeleteStorageObject(input, context) {
655
+ console.log('[FileResolver] DeleteStorageObject called:', input);
656
+ const md = GetReadOnlyProvider(context.providers, { allowFallbackToReadWrite: true });
657
+ const user = this.GetUserFromPayload(context.userPayload);
658
+ const { account, provider: providerEntity } = await this.loadAccountAndProvider(input.AccountID, context);
659
+ console.log('[FileResolver] Provider loaded:', {
660
+ providerID: providerEntity.ID,
661
+ providerName: providerEntity.Name,
662
+ serverDriverKey: providerEntity.ServerDriverKey,
663
+ });
664
+ const fileEntity = await md.GetEntityObject('Files', user);
665
+ fileEntity.CheckPermissions(EntityPermissionType.Delete, true);
666
+ console.log('[FileResolver] Permissions checked, calling deleteObject...');
667
+ const userContext = this.buildExtendedUserContext(context, account);
668
+ const success = await deleteObject(providerEntity, input.ObjectName, userContext);
669
+ console.log('[FileResolver] deleteObject returned:', success);
670
+ return success;
671
+ }
672
+ async MoveStorageObject(input, context) {
673
+ const md = GetReadOnlyProvider(context.providers, { allowFallbackToReadWrite: true });
674
+ const user = this.GetUserFromPayload(context.userPayload);
675
+ const { account, provider: providerEntity } = await this.loadAccountAndProvider(input.AccountID, context);
676
+ const fileEntity = await md.GetEntityObject('Files', user);
677
+ fileEntity.CheckPermissions(EntityPermissionType.Update, true);
678
+ const userContext = this.buildExtendedUserContext(context, account);
679
+ const success = await moveObject(providerEntity, input.OldName, input.NewName, userContext);
680
+ return success;
681
+ }
682
+ async CopyStorageObject(input, context) {
683
+ const md = GetReadOnlyProvider(context.providers, { allowFallbackToReadWrite: true });
684
+ const user = this.GetUserFromPayload(context.userPayload);
685
+ const { account, provider: providerEntity } = await this.loadAccountAndProvider(input.AccountID, context);
686
+ const fileEntity = await md.GetEntityObject('Files', user);
687
+ fileEntity.CheckPermissions(EntityPermissionType.Read, true);
688
+ fileEntity.CheckPermissions(EntityPermissionType.Create, true);
689
+ const userContext = this.buildExtendedUserContext(context, account);
690
+ const success = await copyObject(providerEntity, input.SourceName, input.DestinationName, userContext);
691
+ return success;
692
+ }
693
+ async CreateDirectory(input, context) {
694
+ const md = GetReadOnlyProvider(context.providers, { allowFallbackToReadWrite: true });
695
+ const user = this.GetUserFromPayload(context.userPayload);
696
+ const { account: accountEntity, provider: providerEntity } = await this.loadAccountAndProvider(input.AccountID, context);
697
+ const fileEntity = await md.GetEntityObject('Files', user);
698
+ fileEntity.CheckPermissions(EntityPermissionType.Create, true);
699
+ const driver = await initializeDriverWithAccountCredentials({
700
+ accountEntity,
701
+ providerEntity,
702
+ contextUser: user,
703
+ });
704
+ const success = await driver.CreateDirectory(input.Path);
705
+ return success;
706
+ }
707
+ async CopyObjectBetweenAccounts(input, context) {
708
+ console.log('[FileResolver] CopyObjectBetweenAccounts called:', {
709
+ sourceAccountID: input.SourceAccountID,
710
+ destinationAccountID: input.DestinationAccountID,
711
+ sourcePath: input.SourcePath,
712
+ destinationPath: input.DestinationPath,
713
+ });
714
+ const md = GetReadOnlyProvider(context.providers, { allowFallbackToReadWrite: true });
715
+ const user = this.GetUserFromPayload(context.userPayload);
716
+ const fileEntity = await md.GetEntityObject('Files', user);
717
+ fileEntity.CheckPermissions(EntityPermissionType.Read, true);
718
+ fileEntity.CheckPermissions(EntityPermissionType.Create, true);
719
+ const { account: sourceAccount, provider: sourceProviderEntity } = await this.loadAccountAndProvider(input.SourceAccountID, context);
720
+ const { account: destAccount, provider: destProviderEntity } = await this.loadAccountAndProvider(input.DestinationAccountID, context);
721
+ const sourceUserContext = this.buildExtendedUserContext(context, sourceAccount);
722
+ const destUserContext = this.buildExtendedUserContext(context, destAccount);
723
+ const result = await copyObjectBetweenProviders(sourceProviderEntity, destProviderEntity, input.SourcePath, input.DestinationPath, {
724
+ sourceUserContext,
725
+ destinationUserContext: destUserContext,
726
+ });
727
+ console.log('[FileResolver] CopyObjectBetweenAccounts result:', result);
728
+ return {
729
+ success: result.success,
730
+ message: result.message,
731
+ bytesTransferred: result.bytesTransferred,
732
+ sourceAccount: sourceAccount.Name,
733
+ destinationAccount: destAccount.Name,
734
+ sourcePath: result.sourcePath,
735
+ destinationPath: result.destinationPath,
736
+ };
737
+ }
738
+ async SearchAcrossAccounts(input, context) {
739
+ console.log('[FileResolver] SearchAcrossAccounts called:', {
740
+ accountIDs: input.AccountIDs,
741
+ query: input.Query,
742
+ maxResultsPerAccount: input.MaxResultsPerAccount,
743
+ fileTypes: input.FileTypes,
744
+ searchContent: input.SearchContent,
745
+ });
746
+ const md = GetReadOnlyProvider(context.providers, { allowFallbackToReadWrite: true });
747
+ const user = this.GetUserFromPayload(context.userPayload);
748
+ const fileEntity = await md.GetEntityObject('Files', user);
749
+ fileEntity.CheckPermissions(EntityPermissionType.Read, true);
750
+ const rv = new RunView();
751
+ const quotedIDs = input.AccountIDs.map((id) => `'${id}'`).join(', ');
752
+ const accountResult = await rv.RunView({
753
+ EntityName: 'MJ: File Storage Accounts',
754
+ ExtraFilter: `ID IN (${quotedIDs})`,
755
+ ResultType: 'entity_object',
756
+ }, user);
757
+ if (!accountResult.Success) {
758
+ throw new Error(`Failed to load storage accounts: ${accountResult.ErrorMessage}`);
759
+ }
760
+ const accountEntities = accountResult.Results;
761
+ if (accountEntities.length === 0) {
762
+ throw new Error('No valid storage accounts found for the provided IDs');
763
+ }
764
+ if (accountEntities.length < input.AccountIDs.length) {
765
+ const foundIDs = new Set(accountEntities.map((a) => a.ID));
766
+ const missingIDs = input.AccountIDs.filter((id) => !foundIDs.has(id));
767
+ console.warn(`[FileResolver] Accounts not found: ${missingIDs.join(', ')}`);
768
+ }
769
+ const providerIDs = [...new Set(accountEntities.map((a) => a.ProviderID))];
770
+ const quotedProviderIDs = providerIDs.map((id) => `'${id}'`).join(', ');
771
+ const providerResult = await rv.RunView({
772
+ EntityName: 'File Storage Providers',
773
+ ExtraFilter: `ID IN (${quotedProviderIDs})`,
774
+ ResultType: 'entity_object',
775
+ }, user);
776
+ if (!providerResult.Success) {
777
+ throw new Error(`Failed to load storage providers: ${providerResult.ErrorMessage}`);
778
+ }
779
+ const providerMap = new Map();
780
+ for (const provider of providerResult.Results) {
781
+ providerMap.set(provider.ID, provider);
782
+ }
783
+ const accountInputs = [];
784
+ for (const account of accountEntities) {
785
+ const provider = providerMap.get(account.ProviderID);
786
+ if (provider) {
787
+ accountInputs.push({ accountEntity: account, providerEntity: provider });
788
+ }
789
+ }
790
+ const result = await searchAcrossAccounts(accountInputs, input.Query, {
791
+ maxResultsPerAccount: input.MaxResultsPerAccount,
792
+ fileTypes: input.FileTypes,
793
+ searchContent: input.SearchContent,
794
+ contextUser: user,
795
+ });
796
+ console.log('[FileResolver] SearchAcrossAccounts result:', {
797
+ totalResultsReturned: result.totalResultsReturned,
798
+ successfulAccounts: result.successfulAccounts,
799
+ failedAccounts: result.failedAccounts,
800
+ });
801
+ const accountResults = result.accountResults.map((ar) => ({
802
+ accountID: ar.accountID,
803
+ accountName: ar.accountName,
804
+ success: ar.success,
805
+ errorMessage: ar.errorMessage,
806
+ results: ar.results.map((r) => ({
807
+ path: r.path,
808
+ name: r.name,
809
+ size: r.size,
810
+ contentType: r.contentType,
811
+ lastModified: r.lastModified.toISOString(),
812
+ relevance: r.relevance,
813
+ excerpt: r.excerpt,
814
+ matchInFilename: r.matchInFilename,
815
+ objectId: r.objectId,
816
+ })),
817
+ totalMatches: ar.totalMatches,
818
+ hasMore: ar.hasMore,
819
+ nextPageToken: ar.nextPageToken,
820
+ }));
821
+ return {
822
+ accountResults,
823
+ totalResultsReturned: result.totalResultsReturned,
824
+ successfulAccounts: result.successfulAccounts,
825
+ failedAccounts: result.failedAccounts,
826
+ };
827
+ }
125
828
  };
126
829
  __decorate([
127
830
  Mutation(() => CreateFilePayload),
@@ -159,6 +862,78 @@ __decorate([
159
862
  __metadata("design:paramtypes", [String, DeleteOptionsInput, Object, PubSubEngine]),
160
863
  __metadata("design:returntype", Promise)
161
864
  ], FileResolver.prototype, "DeleteFile", null);
865
+ __decorate([
866
+ Query(() => StorageListResult),
867
+ __param(0, Arg('input', () => ListStorageObjectsInput)),
868
+ __param(1, Ctx()),
869
+ __metadata("design:type", Function),
870
+ __metadata("design:paramtypes", [ListStorageObjectsInput, Object]),
871
+ __metadata("design:returntype", Promise)
872
+ ], FileResolver.prototype, "ListStorageObjects", null);
873
+ __decorate([
874
+ Query(() => String),
875
+ __param(0, Arg('input', () => CreatePreAuthDownloadUrlInput)),
876
+ __param(1, Ctx()),
877
+ __metadata("design:type", Function),
878
+ __metadata("design:paramtypes", [CreatePreAuthDownloadUrlInput, Object]),
879
+ __metadata("design:returntype", Promise)
880
+ ], FileResolver.prototype, "CreatePreAuthDownloadUrl", null);
881
+ __decorate([
882
+ Mutation(() => CreatePreAuthUploadUrlPayload),
883
+ __param(0, Arg('input', () => CreatePreAuthUploadUrlInput)),
884
+ __param(1, Ctx()),
885
+ __metadata("design:type", Function),
886
+ __metadata("design:paramtypes", [CreatePreAuthUploadUrlInput, Object]),
887
+ __metadata("design:returntype", Promise)
888
+ ], FileResolver.prototype, "CreatePreAuthUploadUrl", null);
889
+ __decorate([
890
+ Mutation(() => Boolean),
891
+ __param(0, Arg('input', () => DeleteStorageObjectInput)),
892
+ __param(1, Ctx()),
893
+ __metadata("design:type", Function),
894
+ __metadata("design:paramtypes", [DeleteStorageObjectInput, Object]),
895
+ __metadata("design:returntype", Promise)
896
+ ], FileResolver.prototype, "DeleteStorageObject", null);
897
+ __decorate([
898
+ Mutation(() => Boolean),
899
+ __param(0, Arg('input', () => MoveStorageObjectInput)),
900
+ __param(1, Ctx()),
901
+ __metadata("design:type", Function),
902
+ __metadata("design:paramtypes", [MoveStorageObjectInput, Object]),
903
+ __metadata("design:returntype", Promise)
904
+ ], FileResolver.prototype, "MoveStorageObject", null);
905
+ __decorate([
906
+ Mutation(() => Boolean),
907
+ __param(0, Arg('input', () => CopyStorageObjectInput)),
908
+ __param(1, Ctx()),
909
+ __metadata("design:type", Function),
910
+ __metadata("design:paramtypes", [CopyStorageObjectInput, Object]),
911
+ __metadata("design:returntype", Promise)
912
+ ], FileResolver.prototype, "CopyStorageObject", null);
913
+ __decorate([
914
+ Mutation(() => Boolean),
915
+ __param(0, Arg('input', () => CreateDirectoryInput)),
916
+ __param(1, Ctx()),
917
+ __metadata("design:type", Function),
918
+ __metadata("design:paramtypes", [CreateDirectoryInput, Object]),
919
+ __metadata("design:returntype", Promise)
920
+ ], FileResolver.prototype, "CreateDirectory", null);
921
+ __decorate([
922
+ Mutation(() => CopyObjectBetweenAccountsPayload),
923
+ __param(0, Arg('input', () => CopyObjectBetweenAccountsInput)),
924
+ __param(1, Ctx()),
925
+ __metadata("design:type", Function),
926
+ __metadata("design:paramtypes", [CopyObjectBetweenAccountsInput, Object]),
927
+ __metadata("design:returntype", Promise)
928
+ ], FileResolver.prototype, "CopyObjectBetweenAccounts", null);
929
+ __decorate([
930
+ Query(() => SearchAcrossAccountsPayload),
931
+ __param(0, Arg('input', () => SearchAcrossAccountsInput)),
932
+ __param(1, Ctx()),
933
+ __metadata("design:type", Function),
934
+ __metadata("design:paramtypes", [SearchAcrossAccountsInput, Object]),
935
+ __metadata("design:returntype", Promise)
936
+ ], FileResolver.prototype, "SearchAcrossAccounts", null);
162
937
  FileResolver = __decorate([
163
938
  Resolver(MJFile_)
164
939
  ], FileResolver);