@memberjunction/server 6.1.0-edge.1 → 6.1.0-edge.3
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.
- package/LICENSE +180 -4
- package/dist/auth/AuthProviderCatalogRouter.d.ts +31 -0
- package/dist/auth/AuthProviderCatalogRouter.d.ts.map +1 -0
- package/dist/auth/AuthProviderCatalogRouter.js +69 -0
- package/dist/auth/AuthProviderCatalogRouter.js.map +1 -0
- package/dist/auth/AuthProviderEngine.d.ts +96 -0
- package/dist/auth/AuthProviderEngine.d.ts.map +1 -0
- package/dist/auth/AuthProviderEngine.js +245 -0
- package/dist/auth/AuthProviderEngine.js.map +1 -0
- package/dist/auth/exampleNewUserSubClass.js +1 -1
- package/dist/auth/exampleNewUserSubClass.js.map +1 -1
- package/dist/auth/index.d.ts +11 -0
- package/dist/auth/index.d.ts.map +1 -1
- package/dist/auth/index.js +65 -18
- package/dist/auth/index.js.map +1 -1
- package/dist/auth/initializeProviders.d.ts +64 -1
- package/dist/auth/initializeProviders.d.ts.map +1 -1
- package/dist/auth/initializeProviders.js +117 -5
- package/dist/auth/initializeProviders.js.map +1 -1
- package/dist/auth/magicLink/MagicLinkService.js +1 -1
- package/dist/auth/magicLink/MagicLinkService.js.map +1 -1
- package/dist/auth/newUsers.js +1 -1
- package/dist/auth/newUsers.js.map +1 -1
- package/dist/config.d.ts +89 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +52 -35
- package/dist/config.js.map +1 -1
- package/dist/context.js +2 -2
- package/dist/context.js.map +1 -1
- package/dist/generated/generated.d.ts +540 -1595
- package/dist/generated/generated.d.ts.map +1 -1
- package/dist/generated/generated.js +2755 -16857
- package/dist/generated/generated.js.map +1 -1
- package/dist/generic/ResolverBase.d.ts +20 -4
- package/dist/generic/ResolverBase.d.ts.map +1 -1
- package/dist/generic/ResolverBase.js +58 -21
- package/dist/generic/ResolverBase.js.map +1 -1
- package/dist/generic/RunViewResolver.d.ts +4 -0
- package/dist/generic/RunViewResolver.d.ts.map +1 -1
- package/dist/generic/RunViewResolver.js +31 -0
- package/dist/generic/RunViewResolver.js.map +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +183 -54
- package/dist/index.js.map +1 -1
- package/dist/integration/RSUProgressBridge.d.ts +83 -0
- package/dist/integration/RSUProgressBridge.d.ts.map +1 -0
- package/dist/integration/RSUProgressBridge.js +230 -0
- package/dist/integration/RSUProgressBridge.js.map +1 -0
- package/dist/integration/SchemaRefreshLaunch.d.ts +52 -0
- package/dist/integration/SchemaRefreshLaunch.d.ts.map +1 -0
- package/dist/integration/SchemaRefreshLaunch.js +50 -0
- package/dist/integration/SchemaRefreshLaunch.js.map +1 -0
- package/dist/logging/secretRedactor.d.ts +9 -0
- package/dist/logging/secretRedactor.d.ts.map +1 -1
- package/dist/logging/secretRedactor.js +39 -0
- package/dist/logging/secretRedactor.js.map +1 -1
- package/dist/middleware/BaseServerMiddleware.d.ts +5 -0
- package/dist/middleware/BaseServerMiddleware.d.ts.map +1 -1
- package/dist/middleware/BaseServerMiddleware.js +5 -0
- package/dist/middleware/BaseServerMiddleware.js.map +1 -1
- package/dist/providerConfigUnits.d.ts +20 -0
- package/dist/providerConfigUnits.d.ts.map +1 -0
- package/dist/providerConfigUnits.js +22 -0
- package/dist/providerConfigUnits.js.map +1 -0
- package/dist/realtimeWidget/WidgetSessionService.js +1 -1
- package/dist/realtimeWidget/WidgetSessionService.js.map +1 -1
- package/dist/realtimeWidget/widgetGuestElevation.js +1 -1
- package/dist/realtimeWidget/widgetGuestElevation.js.map +1 -1
- package/dist/resolvers/ActionResolver.d.ts.map +1 -1
- package/dist/resolvers/ActionResolver.js +12 -0
- package/dist/resolvers/ActionResolver.js.map +1 -1
- package/dist/resolvers/ComponentRegistryResolver.js +1 -1
- package/dist/resolvers/ComponentRegistryResolver.js.map +1 -1
- package/dist/resolvers/EntityPermissionResolver.js +1 -1
- package/dist/resolvers/EntityPermissionResolver.js.map +1 -1
- package/dist/resolvers/FileResolver.d.ts +34 -4
- package/dist/resolvers/FileResolver.d.ts.map +1 -1
- package/dist/resolvers/FileResolver.js +218 -28
- package/dist/resolvers/FileResolver.js.map +1 -1
- package/dist/resolvers/IntegrationDiscoveryResolver.d.ts +85 -3
- package/dist/resolvers/IntegrationDiscoveryResolver.d.ts.map +1 -1
- package/dist/resolvers/IntegrationDiscoveryResolver.js +302 -82
- package/dist/resolvers/IntegrationDiscoveryResolver.js.map +1 -1
- package/dist/resolvers/PotentialDuplicateRecordResolver.js +1 -1
- package/dist/resolvers/PotentialDuplicateRecordResolver.js.map +1 -1
- package/dist/resolvers/QueryResolver.d.ts +5 -4
- package/dist/resolvers/QueryResolver.d.ts.map +1 -1
- package/dist/resolvers/QueryResolver.js +29 -14
- package/dist/resolvers/QueryResolver.js.map +1 -1
- package/dist/resolvers/QuerySystemUserResolver.d.ts +12 -3
- package/dist/resolvers/QuerySystemUserResolver.d.ts.map +1 -1
- package/dist/resolvers/QuerySystemUserResolver.js +33 -14
- package/dist/resolvers/QuerySystemUserResolver.js.map +1 -1
- package/dist/resolvers/RealtimeClientSessionResolver.d.ts +10 -0
- package/dist/resolvers/RealtimeClientSessionResolver.d.ts.map +1 -1
- package/dist/resolvers/RealtimeClientSessionResolver.js +5 -0
- package/dist/resolvers/RealtimeClientSessionResolver.js.map +1 -1
- package/dist/resolvers/RunAIAgentResolver.d.ts +3 -1
- package/dist/resolvers/RunAIAgentResolver.d.ts.map +1 -1
- package/dist/resolvers/RunAIAgentResolver.js +20 -7
- package/dist/resolvers/RunAIAgentResolver.js.map +1 -1
- package/dist/resolvers/SearchEntitiesResolver.js +1 -1
- package/dist/resolvers/SearchEntitiesResolver.js.map +1 -1
- package/dist/resolvers/SqlLoggingConfigResolver.d.ts.map +1 -1
- package/dist/resolvers/SqlLoggingConfigResolver.js +1 -1
- package/dist/resolvers/SqlLoggingConfigResolver.js.map +1 -1
- package/dist/resolvers/SyncRolesUsersResolver.js +2 -2
- package/dist/resolvers/SyncRolesUsersResolver.js.map +1 -1
- package/dist/resolvers/TaskGraphFrameResolver.d.ts +18 -0
- package/dist/resolvers/TaskGraphFrameResolver.d.ts.map +1 -1
- package/dist/resolvers/TaskGraphFrameResolver.js +75 -0
- package/dist/resolvers/TaskGraphFrameResolver.js.map +1 -1
- package/dist/resolvers/UserFavoriteResolver.js +1 -1
- package/dist/resolvers/UserFavoriteResolver.js.map +1 -1
- package/dist/resolvers/UserResolver.d.ts +19 -17
- package/dist/resolvers/UserResolver.d.ts.map +1 -1
- package/dist/resolvers/UserResolver.js +66 -67
- package/dist/resolvers/UserResolver.js.map +1 -1
- package/dist/resolvers/currentUserRoles.d.ts +19 -0
- package/dist/resolvers/currentUserRoles.d.ts.map +1 -0
- package/dist/resolvers/currentUserRoles.js +36 -0
- package/dist/resolvers/currentUserRoles.js.map +1 -0
- package/dist/rest/MediaAccessKeys.d.ts +17 -0
- package/dist/rest/MediaAccessKeys.d.ts.map +1 -1
- package/dist/rest/MediaAccessKeys.js +42 -1
- package/dist/rest/MediaAccessKeys.js.map +1 -1
- package/dist/rest/MediaStreamHandler.d.ts +3 -2
- package/dist/rest/MediaStreamHandler.d.ts.map +1 -1
- package/dist/rest/MediaStreamHandler.js +83 -2
- package/dist/rest/MediaStreamHandler.js.map +1 -1
- package/dist/rest/OAuthCallbackHandler.d.ts +49 -1
- package/dist/rest/OAuthCallbackHandler.d.ts.map +1 -1
- package/dist/rest/OAuthCallbackHandler.js +130 -44
- package/dist/rest/OAuthCallbackHandler.js.map +1 -1
- package/dist/rest/SignatureWebhookHandler.js +1 -1
- package/dist/rest/SignatureWebhookHandler.js.map +1 -1
- package/dist/rest/UploadTokenManager.d.ts +90 -0
- package/dist/rest/UploadTokenManager.d.ts.map +1 -0
- package/dist/rest/UploadTokenManager.js +156 -0
- package/dist/rest/UploadTokenManager.js.map +1 -0
- package/dist/services/DurableEntityActionTaskSubmitter.d.ts +26 -0
- package/dist/services/DurableEntityActionTaskSubmitter.d.ts.map +1 -0
- package/dist/services/DurableEntityActionTaskSubmitter.js +55 -0
- package/dist/services/DurableEntityActionTaskSubmitter.js.map +1 -0
- package/dist/services/IntegrationSyncWorkerService.d.ts +48 -0
- package/dist/services/IntegrationSyncWorkerService.d.ts.map +1 -0
- package/dist/services/IntegrationSyncWorkerService.js +132 -0
- package/dist/services/IntegrationSyncWorkerService.js.map +1 -0
- package/dist/services/ScheduledJobsService.js +1 -1
- package/dist/services/ScheduledJobsService.js.map +1 -1
- package/dist/services/StartTaskGraphDispatcher.d.ts +0 -10
- package/dist/services/StartTaskGraphDispatcher.d.ts.map +1 -1
- package/dist/services/StartTaskGraphDispatcher.js +37 -2
- package/dist/services/StartTaskGraphDispatcher.js.map +1 -1
- package/dist/services/TaskGraphActionRunner.d.ts +34 -0
- package/dist/services/TaskGraphActionRunner.d.ts.map +1 -0
- package/dist/services/TaskGraphActionRunner.js +95 -0
- package/dist/services/TaskGraphActionRunner.js.map +1 -0
- package/dist/services/TaskGraphAgentRunner.d.ts +20 -0
- package/dist/services/TaskGraphAgentRunner.d.ts.map +1 -1
- package/dist/services/TaskGraphAgentRunner.js +53 -0
- package/dist/services/TaskGraphAgentRunner.js.map +1 -1
- package/dist/services/TaskGraphContinuationDeliverer.d.ts.map +1 -1
- package/dist/services/TaskGraphContinuationDeliverer.js +12 -1
- package/dist/services/TaskGraphContinuationDeliverer.js.map +1 -1
- package/dist/services/TaskGraphPromptRunner.d.ts +31 -0
- package/dist/services/TaskGraphPromptRunner.d.ts.map +1 -0
- package/dist/services/TaskGraphPromptRunner.js +134 -0
- package/dist/services/TaskGraphPromptRunner.js.map +1 -0
- package/dist/telephony/RingCentralTelephonyService.js +1 -1
- package/dist/telephony/RingCentralTelephonyService.js.map +1 -1
- package/dist/telephony/TwilioTelephonyRouter.js +1 -1
- package/dist/telephony/TwilioTelephonyRouter.js.map +1 -1
- package/dist/telephony/VonageTelephonyRouter.js +1 -1
- package/dist/telephony/VonageTelephonyRouter.js.map +1 -1
- package/dist/types.d.ts +6 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +91 -91
- package/src/__tests__/APIKeyScopeAuth.test.ts +475 -0
- package/src/__tests__/AuthProviderEngine.test.ts +278 -0
- package/src/__tests__/EntityCRUDHandler.test.ts +378 -0
- package/src/__tests__/IntegrationSyncWorkerService.test.ts +275 -0
- package/src/__tests__/OAuthCallbackHandler.openRedirect.test.ts +117 -0
- package/src/__tests__/OAuthCallbackHandler.xss.test.ts +4 -1
- package/src/__tests__/RESTEndpointHandler.test.ts +672 -0
- package/src/__tests__/RSUProgressBridge.test.ts +250 -0
- package/src/__tests__/RealtimeBridgeResolver.test.ts +10 -2
- package/src/__tests__/RealtimeClientSessionResolver.test.ts +1 -1
- package/src/__tests__/ResolverBase.frozenRecordMapping.test.ts +133 -0
- package/src/__tests__/ResolverBase.transportMapping.test.ts +289 -0
- package/src/__tests__/SchemaRefreshLaunch.test.ts +114 -0
- package/src/__tests__/SessionManager.test.ts +1 -1
- package/src/__tests__/UserResolver.currentUser.test.ts +87 -0
- package/src/__tests__/ViewOperationsHandler.test.ts +277 -0
- package/src/__tests__/WidgetSessionService.test.ts +1 -1
- package/src/__tests__/config-units.test.ts +74 -0
- package/src/__tests__/databaseAbstraction.test.ts +1 -1
- package/src/__tests__/initializeProviders.refresh.test.ts +146 -0
- package/src/__tests__/magicLinkService.provisionLog.test.ts +1 -1
- package/src/__tests__/mjapi-bootstrap.test.ts +0 -6
- package/src/__tests__/newUsers.test.ts +726 -0
- package/src/__tests__/resolverBase.rls.test.ts +3 -0
- package/src/__tests__/secretRedactor.failOpen.test.ts +135 -0
- package/src/__tests__/uploadTokenManager.test.ts +159 -0
- package/src/__tests__/widgetGuestElevation.test.ts +1 -1
- package/src/auth/AuthProviderCatalogRouter.ts +76 -0
- package/src/auth/AuthProviderEngine.ts +253 -0
- package/src/auth/exampleNewUserSubClass.ts +1 -1
- package/src/auth/index.ts +69 -21
- package/src/auth/initializeProviders.ts +128 -7
- package/src/auth/magicLink/MagicLinkService.ts +1 -1
- package/src/auth/newUsers.ts +1 -1
- package/src/config.ts +55 -36
- package/src/context.ts +2 -2
- package/src/generated/generated.ts +2038 -10529
- package/src/generic/ResolverBase.ts +63 -21
- package/src/generic/RunViewResolver.ts +31 -0
- package/src/index.ts +199 -56
- package/src/integration/RSUProgressBridge.ts +248 -0
- package/src/integration/SchemaRefreshLaunch.ts +77 -0
- package/src/logging/secretRedactor.ts +43 -0
- package/src/middleware/BaseServerMiddleware.ts +5 -0
- package/src/providerConfigUnits.ts +21 -0
- package/src/realtimeWidget/WidgetSessionService.ts +1 -1
- package/src/realtimeWidget/widgetGuestElevation.ts +1 -1
- package/src/resolvers/ActionResolver.ts +13 -0
- package/src/resolvers/ComponentRegistryResolver.ts +1 -1
- package/src/resolvers/EntityPermissionResolver.ts +1 -1
- package/src/resolvers/FileResolver.ts +200 -40
- package/src/resolvers/IntegrationDiscoveryResolver.ts +328 -70
- package/src/resolvers/PotentialDuplicateRecordResolver.ts +1 -1
- package/src/resolvers/QueryResolver.ts +25 -11
- package/src/resolvers/QuerySystemUserResolver.ts +28 -13
- package/src/resolvers/RealtimeClientSessionResolver.ts +13 -0
- package/src/resolvers/RunAIAgentResolver.ts +21 -6
- package/src/resolvers/SearchEntitiesResolver.ts +1 -1
- package/src/resolvers/SqlLoggingConfigResolver.ts +1 -2
- package/src/resolvers/SyncRolesUsersResolver.ts +2 -2
- package/src/resolvers/TaskGraphFrameResolver.ts +67 -0
- package/src/resolvers/UserFavoriteResolver.ts +1 -1
- package/src/resolvers/UserResolver.ts +99 -60
- package/src/resolvers/currentUserRoles.ts +47 -0
- package/src/rest/MediaAccessKeys.ts +47 -1
- package/src/rest/MediaStreamHandler.ts +98 -3
- package/src/rest/OAuthCallbackHandler.ts +150 -42
- package/src/rest/SignatureWebhookHandler.ts +1 -1
- package/src/rest/UploadTokenManager.ts +211 -0
- package/src/services/DurableEntityActionTaskSubmitter.ts +78 -0
- package/src/services/IntegrationSyncWorkerService.ts +141 -0
- package/src/services/ScheduledJobsService.ts +1 -1
- package/src/services/StartTaskGraphDispatcher.ts +38 -1
- package/src/services/TaskGraphActionRunner.ts +99 -0
- package/src/services/TaskGraphAgentRunner.ts +58 -1
- package/src/services/TaskGraphContinuationDeliverer.ts +11 -1
- package/src/services/TaskGraphPromptRunner.ts +144 -0
- package/src/telephony/RingCentralTelephonyService.ts +1 -1
- package/src/telephony/TwilioTelephonyRouter.ts +1 -1
- package/src/telephony/VonageTelephonyRouter.ts +1 -1
- package/src/types.ts +6 -0
|
@@ -41,6 +41,7 @@ import { FieldMapper } from '@memberjunction/graphql-dataprovider';
|
|
|
41
41
|
import { GetReadOnlyProvider } from '../util.js';
|
|
42
42
|
import { configInfo } from '../config.js';
|
|
43
43
|
import { MediaAccessKeyManager } from '../rest/MediaAccessKeys.js';
|
|
44
|
+
import { UploadTokenManager } from '../rest/UploadTokenManager.js';
|
|
44
45
|
import { deriveSidecarPath, parsePeaksSidecar } from './peaksSidecar.js';
|
|
45
46
|
|
|
46
47
|
@InputType()
|
|
@@ -49,6 +50,63 @@ export class CreateUploadURLInput {
|
|
|
49
50
|
FileID: string;
|
|
50
51
|
}
|
|
51
52
|
|
|
53
|
+
@InputType()
|
|
54
|
+
export class UploadStorageFileInput {
|
|
55
|
+
@Field(() => String, { nullable: true })
|
|
56
|
+
FileName?: string;
|
|
57
|
+
|
|
58
|
+
@Field(() => String, { nullable: true })
|
|
59
|
+
Base64Data?: string;
|
|
60
|
+
|
|
61
|
+
@Field(() => String, { nullable: true })
|
|
62
|
+
UploadToken?: string;
|
|
63
|
+
|
|
64
|
+
@Field(() => String, { nullable: true })
|
|
65
|
+
MimeType?: string;
|
|
66
|
+
|
|
67
|
+
@Field(() => String, { nullable: true })
|
|
68
|
+
AccountID?: string;
|
|
69
|
+
|
|
70
|
+
@Field(() => String, { nullable: true })
|
|
71
|
+
CategoryID?: string;
|
|
72
|
+
|
|
73
|
+
@Field(() => String, { nullable: true })
|
|
74
|
+
Description?: string;
|
|
75
|
+
|
|
76
|
+
@Field(() => String, { nullable: true })
|
|
77
|
+
PathPrefix?: string;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
@ObjectType()
|
|
81
|
+
export class UploadStorageFilePayload {
|
|
82
|
+
@Field(() => Boolean)
|
|
83
|
+
Success: boolean;
|
|
84
|
+
|
|
85
|
+
@Field(() => String, { nullable: true })
|
|
86
|
+
FileID?: string;
|
|
87
|
+
|
|
88
|
+
@Field(() => MJFile_, { nullable: true })
|
|
89
|
+
File?: MJFile_;
|
|
90
|
+
|
|
91
|
+
@Field(() => String, { nullable: true })
|
|
92
|
+
ErrorMessage?: string;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
@ObjectType()
|
|
96
|
+
export class CreateUploadStageTokenPayload {
|
|
97
|
+
@Field(() => Boolean)
|
|
98
|
+
Success: boolean;
|
|
99
|
+
|
|
100
|
+
@Field(() => String, { nullable: true })
|
|
101
|
+
Token?: string;
|
|
102
|
+
|
|
103
|
+
@Field(() => String, { nullable: true })
|
|
104
|
+
Url?: string;
|
|
105
|
+
|
|
106
|
+
@Field(() => String, { nullable: true })
|
|
107
|
+
ErrorMessage?: string;
|
|
108
|
+
}
|
|
109
|
+
|
|
52
110
|
@ObjectType()
|
|
53
111
|
export class CreateFilePayload {
|
|
54
112
|
@Field(() => MJFile_)
|
|
@@ -414,7 +472,8 @@ export class FileResolver extends FileResolverBase {
|
|
|
414
472
|
|
|
415
473
|
// Access authorized — mint the capability token.
|
|
416
474
|
const { Token, ExpiresAt } = MediaAccessKeyManager.Instance.Sign(fileId, contextUser.ID);
|
|
417
|
-
const
|
|
475
|
+
const fileNameSuffix = fileEntity.Name ? `/${encodeURIComponent(fileEntity.Name)}` : '';
|
|
476
|
+
const url = `${this.resolvePublicBaseUrl()}/media/${encodeURIComponent(fileId)}${fileNameSuffix}?token=${encodeURIComponent(Token)}`;
|
|
418
477
|
|
|
419
478
|
// Best-effort: surface precomputed waveform peaks from a peaks.json sidecar beside the file, so
|
|
420
479
|
// the player renders the real waveform instantly without fetching/decoding the audio. Never
|
|
@@ -573,6 +632,85 @@ export class FileResolver extends FileResolverBase {
|
|
|
573
632
|
return { File, UploadUrl, NameExists };
|
|
574
633
|
}
|
|
575
634
|
|
|
635
|
+
/**
|
|
636
|
+
* Direct server-side file upload using MJ Storage subsystem.
|
|
637
|
+
* Uploads file contents directly via the configured storage driver (Box, Azure, S3, Google Drive, Dropbox, etc.)
|
|
638
|
+
* and creates/persists the MJ: Files database record.
|
|
639
|
+
*/
|
|
640
|
+
@Mutation(() => UploadStorageFilePayload)
|
|
641
|
+
async UploadStorageFile(
|
|
642
|
+
@Arg('input', () => UploadStorageFileInput) input: UploadStorageFileInput,
|
|
643
|
+
@Ctx() context: AppContext
|
|
644
|
+
): Promise<UploadStorageFilePayload> {
|
|
645
|
+
try {
|
|
646
|
+
const provider = GetReadOnlyProvider(context.providers, { allowFallbackToReadWrite: true });
|
|
647
|
+
const user = this.GetUserFromPayload(context.userPayload);
|
|
648
|
+
|
|
649
|
+
// Permission check on MJ: Files
|
|
650
|
+
const fileEntity = await provider.GetEntityObject<MJFileEntity>('MJ: Files', user);
|
|
651
|
+
fileEntity.CheckPermissions(EntityPermissionType.Create, true);
|
|
652
|
+
|
|
653
|
+
let buffer: Buffer;
|
|
654
|
+
let fileName: string = input.FileName || 'file';
|
|
655
|
+
let mimeType: string = input.MimeType || 'application/octet-stream';
|
|
656
|
+
|
|
657
|
+
if (input.UploadToken) {
|
|
658
|
+
const staged = UploadTokenManager.Instance.Consume(input.UploadToken, user.ID);
|
|
659
|
+
if (!staged) {
|
|
660
|
+
return {
|
|
661
|
+
Success: false,
|
|
662
|
+
ErrorMessage: 'Upload token is invalid, expired, or has already been used.',
|
|
663
|
+
};
|
|
664
|
+
}
|
|
665
|
+
buffer = staged.buffer;
|
|
666
|
+
fileName = input.FileName || staged.fileName || 'file';
|
|
667
|
+
mimeType = input.MimeType || staged.mimeType || 'application/octet-stream';
|
|
668
|
+
} else if (input.Base64Data) {
|
|
669
|
+
buffer = Buffer.from(input.Base64Data, 'base64');
|
|
670
|
+
} else {
|
|
671
|
+
return {
|
|
672
|
+
Success: false,
|
|
673
|
+
ErrorMessage: 'Either UploadToken or Base64Data must be provided.',
|
|
674
|
+
};
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
// Ensure FileStorageEngine is configured under the user context
|
|
678
|
+
await FileStorageEngine.Instance.Config(false, user, provider);
|
|
679
|
+
if (input.AccountID && !FileStorageEngine.Instance.GetAccountById(input.AccountID)) {
|
|
680
|
+
await FileStorageEngine.Instance.Config(true, user, provider);
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
const uploadResult = await FileStorageEngine.Instance.UploadFile({
|
|
684
|
+
content: buffer,
|
|
685
|
+
fileName,
|
|
686
|
+
mimeType,
|
|
687
|
+
contextUser: user,
|
|
688
|
+
storageAccountId: input.AccountID,
|
|
689
|
+
categoryID: input.CategoryID,
|
|
690
|
+
description: input.Description,
|
|
691
|
+
pathPrefix: input.PathPrefix,
|
|
692
|
+
provider,
|
|
693
|
+
});
|
|
694
|
+
|
|
695
|
+
const loaded = await fileEntity.Load(uploadResult.FileID);
|
|
696
|
+
const mapper = new FieldMapper();
|
|
697
|
+
const File = loaded ? (mapper.MapFields({ ...fileEntity.GetAll() }) as unknown as MJFile_) : undefined;
|
|
698
|
+
|
|
699
|
+
return {
|
|
700
|
+
Success: true,
|
|
701
|
+
FileID: uploadResult.FileID,
|
|
702
|
+
File,
|
|
703
|
+
};
|
|
704
|
+
} catch (error) {
|
|
705
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
706
|
+
LogError(`UploadStorageFile failed for '${input.FileName}': ${message}`);
|
|
707
|
+
return {
|
|
708
|
+
Success: false,
|
|
709
|
+
ErrorMessage: message,
|
|
710
|
+
};
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
|
|
576
714
|
@FieldResolver(() => String)
|
|
577
715
|
async DownloadUrl(@Root() file: MJFile_, @Ctx() context: AppContext) {
|
|
578
716
|
const md = GetReadOnlyProvider(context.providers, { allowFallbackToReadWrite: true });
|
|
@@ -580,6 +718,19 @@ export class FileResolver extends FileResolverBase {
|
|
|
580
718
|
const fileEntity = await md.GetEntityObject<MJFileEntity>('MJ: Files', user);
|
|
581
719
|
fileEntity.CheckPermissions(EntityPermissionType.Read, true);
|
|
582
720
|
|
|
721
|
+
await FileStorageEngine.Instance.Config(false, user, md);
|
|
722
|
+
let accounts = FileStorageEngine.Instance.GetAccountsByProviderID(file.ProviderID);
|
|
723
|
+
if (accounts.length === 0) {
|
|
724
|
+
await FileStorageEngine.Instance.Config(true, user, md);
|
|
725
|
+
accounts = FileStorageEngine.Instance.GetAccountsByProviderID(file.ProviderID);
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
if (accounts.length > 0) {
|
|
729
|
+
const account = accounts[0];
|
|
730
|
+
const driver = await FileStorageEngine.Instance.GetDriver(account.ID, user);
|
|
731
|
+
return await driver.CreatePreAuthDownloadUrl(file.ProviderKey ?? file.Name);
|
|
732
|
+
}
|
|
733
|
+
|
|
583
734
|
const providerEntity = await md.GetEntityObject<MJFileStorageProviderEntity>('MJ: File Storage Providers', user);
|
|
584
735
|
await providerEntity.Load(file.ProviderID);
|
|
585
736
|
|
|
@@ -734,16 +885,13 @@ export class FileResolver extends FileResolverBase {
|
|
|
734
885
|
const md = GetReadOnlyProvider(context.providers, { allowFallbackToReadWrite: true });
|
|
735
886
|
const user = this.GetUserFromPayload(context.userPayload);
|
|
736
887
|
|
|
737
|
-
// Load the account and its provider
|
|
738
|
-
const { account, provider: providerEntity } = await this.loadAccountAndProvider(input.AccountID, context);
|
|
739
|
-
|
|
740
888
|
// Check permissions
|
|
741
889
|
const fileEntity = await md.GetEntityObject<MJFileEntity>('MJ: Files', user);
|
|
742
890
|
fileEntity.CheckPermissions(EntityPermissionType.Read, true);
|
|
743
891
|
|
|
744
|
-
|
|
745
|
-
const
|
|
746
|
-
const downloadUrl = await
|
|
892
|
+
await FileStorageEngine.Instance.Config(false, user, md);
|
|
893
|
+
const driver = await FileStorageEngine.Instance.GetDriver(input.AccountID, user);
|
|
894
|
+
const downloadUrl = await driver.CreatePreAuthDownloadUrl(input.ObjectName);
|
|
747
895
|
return downloadUrl;
|
|
748
896
|
}
|
|
749
897
|
|
|
@@ -762,67 +910,79 @@ export class FileResolver extends FileResolverBase {
|
|
|
762
910
|
* @see CreateFile for the legacy path that also creates a File entity record.
|
|
763
911
|
*/
|
|
764
912
|
@Mutation(() => CreatePreAuthUploadUrlPayload)
|
|
765
|
-
async CreatePreAuthUploadUrl(
|
|
913
|
+
async CreatePreAuthUploadUrl(
|
|
914
|
+
@Arg('input', () => CreatePreAuthUploadUrlInput) input: CreatePreAuthUploadUrlInput,
|
|
915
|
+
@Ctx() context: AppContext
|
|
916
|
+
): Promise<CreatePreAuthUploadUrlPayload> {
|
|
766
917
|
const md = GetReadOnlyProvider(context.providers, { allowFallbackToReadWrite: true });
|
|
767
918
|
const user = this.GetUserFromPayload(context.userPayload);
|
|
768
919
|
|
|
769
|
-
// Load the account and its provider
|
|
770
|
-
const { account, provider: providerEntity } = await this.loadAccountAndProvider(input.AccountID, context);
|
|
771
|
-
|
|
772
920
|
// Check permissions
|
|
773
921
|
const fileEntity = await md.GetEntityObject<MJFileEntity>('MJ: Files', user);
|
|
774
922
|
fileEntity.CheckPermissions(EntityPermissionType.Create, true);
|
|
775
923
|
|
|
776
|
-
|
|
777
|
-
const
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
ProviderID: providerEntity.ID,
|
|
784
|
-
ContentType: input.ContentType,
|
|
785
|
-
},
|
|
786
|
-
userContext,
|
|
787
|
-
);
|
|
788
|
-
|
|
789
|
-
// Extract ProviderKey if it exists (spread into updatedInput by createUploadUrl)
|
|
790
|
-
const providerKey = (updatedInput as { ProviderKey?: string }).ProviderKey;
|
|
924
|
+
await FileStorageEngine.Instance.Config(false, user, md);
|
|
925
|
+
const driver = await FileStorageEngine.Instance.GetDriver(input.AccountID, user);
|
|
926
|
+
if (!driver.SupportsPreAuthUpload) {
|
|
927
|
+
throw new Error(`Storage provider '${driver.constructor.name}' does not support pre-authenticated direct uploads.`);
|
|
928
|
+
}
|
|
929
|
+
|
|
930
|
+
const result = await driver.CreatePreAuthUploadUrl(input.ObjectName);
|
|
791
931
|
|
|
792
932
|
return {
|
|
793
|
-
UploadUrl,
|
|
794
|
-
ProviderKey:
|
|
933
|
+
UploadUrl: result.UploadUrl,
|
|
934
|
+
ProviderKey: result.ProviderKey,
|
|
795
935
|
};
|
|
796
936
|
}
|
|
797
937
|
|
|
938
|
+
/**
|
|
939
|
+
* Mints a cryptographically signed, short-lived media-upload token for staging raw binary files.
|
|
940
|
+
* Checks user permissions on `MJ: Files` before issuing.
|
|
941
|
+
*/
|
|
942
|
+
@Mutation(() => CreateUploadStageTokenPayload)
|
|
943
|
+
async CreateUploadStageToken(
|
|
944
|
+
@Ctx() context: AppContext
|
|
945
|
+
): Promise<CreateUploadStageTokenPayload> {
|
|
946
|
+
try {
|
|
947
|
+
const provider = GetReadOnlyProvider(context.providers, { allowFallbackToReadWrite: true });
|
|
948
|
+
const user = this.GetUserFromPayload(context.userPayload);
|
|
949
|
+
|
|
950
|
+
// Permission check on MJ: Files
|
|
951
|
+
const fileEntity = await provider.GetEntityObject<MJFileEntity>('MJ: Files', user);
|
|
952
|
+
fileEntity.CheckPermissions(EntityPermissionType.Create, true);
|
|
953
|
+
|
|
954
|
+
const mint = MediaAccessKeyManager.Instance.SignUpload(user.ID);
|
|
955
|
+
|
|
956
|
+
return {
|
|
957
|
+
Success: true,
|
|
958
|
+
Token: mint.Token,
|
|
959
|
+
Url: '/media/upload-stage',
|
|
960
|
+
};
|
|
961
|
+
} catch (err) {
|
|
962
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
963
|
+
return {
|
|
964
|
+
Success: false,
|
|
965
|
+
ErrorMessage: message,
|
|
966
|
+
};
|
|
967
|
+
}
|
|
968
|
+
}
|
|
969
|
+
|
|
798
970
|
@Mutation(() => Boolean)
|
|
799
971
|
async DeleteStorageObject(@Arg('input', () => DeleteStorageObjectInput) input: DeleteStorageObjectInput, @Ctx() context: AppContext) {
|
|
800
|
-
console.log('[FileResolver] DeleteStorageObject called:', input);
|
|
801
|
-
|
|
802
972
|
const md = GetReadOnlyProvider(context.providers, { allowFallbackToReadWrite: true });
|
|
803
973
|
const user = this.GetUserFromPayload(context.userPayload);
|
|
804
974
|
|
|
805
975
|
// Load the account and its provider
|
|
806
976
|
const { account, provider: providerEntity } = await this.loadAccountAndProvider(input.AccountID, context);
|
|
807
977
|
|
|
808
|
-
console.log('[FileResolver] Provider loaded:', {
|
|
809
|
-
providerID: providerEntity.ID,
|
|
810
|
-
providerName: providerEntity.Name,
|
|
811
|
-
serverDriverKey: providerEntity.ServerDriverKey,
|
|
812
|
-
});
|
|
813
|
-
|
|
814
978
|
// Check permissions
|
|
815
979
|
const fileEntity = await md.GetEntityObject<MJFileEntity>('MJ: Files', user);
|
|
816
980
|
fileEntity.CheckPermissions(EntityPermissionType.Delete, true);
|
|
817
981
|
|
|
818
|
-
console.log('[FileResolver] Permissions checked, calling deleteObject...');
|
|
819
|
-
|
|
820
982
|
// Delete the object with extended user context (includes account for credential lookup)
|
|
821
983
|
const userContext = this.buildExtendedUserContext(context, account);
|
|
822
984
|
const success = await deleteObject(providerEntity, input.ObjectName, userContext);
|
|
823
985
|
|
|
824
|
-
console.log('[FileResolver] deleteObject returned:', success);
|
|
825
|
-
|
|
826
986
|
return success;
|
|
827
987
|
}
|
|
828
988
|
|