Page MenuHomePhabricator

D10913.diff
No OneTemporary

D10913.diff

diff --git a/lib/actions/upload-actions.js b/lib/actions/upload-actions.js
--- a/lib/actions/upload-actions.js
+++ b/lib/actions/upload-actions.js
@@ -1,10 +1,14 @@
// @flow
+import invariant from 'invariant';
+import * as React from 'react';
import uuid from 'uuid';
import blobService from '../facts/blob-service.js';
import { extractKeyserverIDFromID } from '../keyserver-conn/keyserver-call-utils.js';
import type { CallKeyserverEndpoint } from '../keyserver-conn/keyserver-conn-types.js';
+import { IdentityClientContext } from '../shared/identity-client-context.js';
+import type { AuthMetadata } from '../shared/identity-client-context.js';
import type { UploadMultimediaResult, Dimensions } from '../types/media-types';
import { toBase64URL } from '../utils/base64.js';
import {
@@ -15,7 +19,10 @@
import type { CallSingleKeyserverEndpoint } from '../utils/call-single-keyserver-endpoint.js';
import { getMessageForException } from '../utils/errors.js';
import { useKeyserverCall } from '../utils/keyserver-call.js';
-import { handleHTTPResponseError } from '../utils/services-utils.js';
+import {
+ handleHTTPResponseError,
+ createDefaultHTTPRequestHeaders,
+} from '../utils/services-utils.js';
import { type UploadBlob } from '../utils/upload-blob.js';
export type MultimediaUploadCallbacks = Partial<{
@@ -144,13 +151,17 @@
}) => Promise<BlobServiceUploadResult>;
const blobServiceUpload =
- (callKeyserverEndpoint: CallKeyserverEndpoint): BlobServiceUploadAction =>
+ (
+ callKeyserverEndpoint: CallKeyserverEndpoint,
+ authMetadata: AuthMetadata,
+ ): BlobServiceUploadAction =>
async input => {
const { uploadInput, callbacks, keyserverOrThreadID } = input;
const { encryptionKey, loop, dimensions, thumbHash, blobInput } =
uploadInput;
const blobHolder = uuid.v4();
const blobHash = toBase64URL(uploadInput.blobHash);
+ const defaultHeaders = createDefaultHTTPRequestHeaders(authMetadata);
// 1. Assign new holder for blob with given blobHash
let blobAlreadyExists: boolean;
@@ -165,6 +176,7 @@
blob_hash: blobHash,
}),
headers: {
+ ...defaultHeaders,
'content-type': 'application/json',
},
},
@@ -196,6 +208,7 @@
blobHash,
blobInput,
},
+ authMetadata,
{ ...callbacks },
);
} catch (e) {
@@ -240,7 +253,25 @@
};
function useBlobServiceUpload(): BlobServiceUploadAction {
- return useKeyserverCall(blobServiceUpload);
+ const identityContext = React.useContext(IdentityClientContext);
+ invariant(identityContext, 'Identity context should be set');
+ const { getAuthMetadata } = identityContext;
+
+ const blobUploadAction = React.useCallback(
+ (
+ callSingleKeyserverEndpoint: CallSingleKeyserverEndpoint,
+ ): BlobServiceUploadAction =>
+ async input => {
+ const authMetadata = await getAuthMetadata();
+ const authenticatedUploadAction = blobServiceUpload(
+ callSingleKeyserverEndpoint,
+ authMetadata,
+ );
+ return authenticatedUploadAction(input);
+ },
+ [getAuthMetadata],
+ );
+ return useKeyserverCall(blobUploadAction);
}
export {
diff --git a/lib/utils/blob-service-upload.js b/lib/utils/blob-service-upload.js
--- a/lib/utils/blob-service-upload.js
+++ b/lib/utils/blob-service-upload.js
@@ -3,10 +3,12 @@
import invariant from 'invariant';
import _throttle from 'lodash/throttle.js';
+import { createHTTPAuthorizationHeader } from './services-utils.js';
import type {
MultimediaUploadCallbacks,
BlobServiceUploadFile,
} from '../actions/upload-actions.js';
+import type { AuthMetadata } from '../shared/identity-client-context.js';
function blobServiceUploadHandler(
url: string,
@@ -15,6 +17,7 @@
blobHash: string,
blobInput: BlobServiceUploadFile,
},
+ authMetadata: AuthMetadata,
options?: ?MultimediaUploadCallbacks,
): Promise<void> {
if (input.blobInput.type !== 'file') {
@@ -28,6 +31,9 @@
const xhr = new XMLHttpRequest();
xhr.open(method, url);
+ const authHeader = createHTTPAuthorizationHeader(authMetadata);
+ xhr.setRequestHeader('Authorization', authHeader);
+
const { timeout, onProgress, abortHandler } = options ?? {};
if (timeout) {
diff --git a/native/utils/blob-service-upload.js b/native/utils/blob-service-upload.js
--- a/native/utils/blob-service-upload.js
+++ b/native/utils/blob-service-upload.js
@@ -6,11 +6,13 @@
import { pathFromURI } from 'lib/media/file-utils.js';
import type { BlobServiceUploadHandler } from 'lib/utils/blob-service-upload.js';
import { getMessageForException } from 'lib/utils/errors.js';
+import { createDefaultHTTPRequestHeaders } from 'lib/utils/services-utils.js';
const blobServiceUploadHandler: BlobServiceUploadHandler = async (
url,
method,
input,
+ authMetadata,
options,
) => {
if (input.blobInput.type !== 'uri') {
@@ -23,6 +25,7 @@
path = resolvedPath;
}
}
+ const headers = authMetadata && createDefaultHTTPRequestHeaders(authMetadata);
const uploadTask = FileSystem.createUploadTask(
url,
path,
@@ -31,6 +34,7 @@
fieldName: 'blob_data',
httpMethod: method,
parameters: { blob_hash: input.blobHash },
+ headers,
},
uploadProgress => {
if (options?.onProgress) {
diff --git a/web/input/input-state-container.react.js b/web/input/input-state-container.react.js
--- a/web/input/input-state-container.react.js
+++ b/web/input/input-state-container.react.js
@@ -41,6 +41,8 @@
import commStaffCommunity from 'lib/facts/comm-staff-community.js';
import { getNextLocalUploadID } from 'lib/media/media-utils.js';
import { pendingToRealizedThreadIDsSelector } from 'lib/selectors/thread-selectors.js';
+import { IdentityClientContext } from 'lib/shared/identity-client-context.js';
+import type { IdentityClientContextType } from 'lib/shared/identity-client-context.js';
import {
createMediaMessageInfo,
localIDPrefix,
@@ -95,6 +97,7 @@
} from 'lib/utils/redux-promise-utils.js';
import { useDispatch } from 'lib/utils/redux-utils.js';
import { generateReportID } from 'lib/utils/report-utils.js';
+import { createDefaultHTTPRequestHeaders } from 'lib/utils/services-utils.js';
import {
type BaseInputState,
@@ -151,6 +154,7 @@
+registerSendCallback: (() => mixed) => void,
+unregisterSendCallback: (() => mixed) => void,
+textMessageCreationSideEffectsFunc: CreationSideEffectsFunc<RawTextMessageInfo>,
+ +identityContext: ?IdentityClientContextType,
};
type WritableState = {
pendingUploads: {
@@ -867,6 +871,9 @@
const steps = [...upload.steps];
let userTime;
+ const { identityContext } = this.props;
+ invariant(identityContext, 'Identity context should be set');
+
const sendReport = (missionResult: MediaMissionResult) => {
const newThreadID = this.getRealizedOrPendingThreadID(threadID);
const latestUpload = this.state.pendingUploads[newThreadID][localID];
@@ -907,6 +914,7 @@
encryptionKey && blobHash && dimensions,
'incomplete encrypted upload',
);
+
uploadResult = await this.props.blobServiceUpload({
uploadInput: {
blobInput: {
@@ -1011,7 +1019,11 @@
});
if (encryptionKey) {
- const { steps: preloadSteps } = await preloadMediaResource(result.uri);
+ const authMetadata = await identityContext.getAuthMetadata();
+ const { steps: preloadSteps } = await preloadMediaResource(
+ result.uri,
+ authMetadata,
+ );
steps.push(...preloadSteps);
} else {
const { steps: preloadSteps } = await preloadImage(result.uri);
@@ -1202,6 +1214,8 @@
keyserverOrThreadID: threadID,
});
if (isBlobServiceURI(pendingUpload.uri)) {
+ const identityContext = this.props.identityContext;
+ invariant(identityContext, 'Identity context should be set');
invariant(
pendingUpload.blobHolder,
'blob service upload has no holder',
@@ -1209,16 +1223,22 @@
const endpoint = blobService.httpEndpoints.DELETE_BLOB;
const holder = pendingUpload.blobHolder;
const blobHash = blobHashFromBlobServiceURI(pendingUpload.uri);
- void fetch(makeBlobServiceEndpointURL(endpoint), {
- method: endpoint.method,
- body: JSON.stringify({
- holder,
- blob_hash: blobHash,
- }),
- headers: {
- 'content-type': 'application/json',
- },
- });
+ void (async () => {
+ const authMetadata = await identityContext.getAuthMetadata();
+ const defaultHeaders =
+ createDefaultHTTPRequestHeaders(authMetadata);
+ await fetch(makeBlobServiceEndpointURL(endpoint), {
+ method: endpoint.method,
+ body: JSON.stringify({
+ holder,
+ blob_hash: blobHash,
+ }),
+ headers: {
+ ...defaultHeaders,
+ 'content-type': 'application/json',
+ },
+ });
+ })();
}
}
const newPendingUploads = _omit([localUploadID])(currentPendingUploads);
@@ -1656,6 +1676,7 @@
const dispatch = useDispatch();
const dispatchActionPromise = useDispatchActionPromise();
const modalContext = useModalContext();
+ const identityContext = React.useContext(IdentityClientContext);
const [sendCallbacks, setSendCallbacks] = React.useState<
$ReadOnlyArray<() => mixed>,
@@ -1696,6 +1717,7 @@
registerSendCallback={registerSendCallback}
unregisterSendCallback={unregisterSendCallback}
textMessageCreationSideEffectsFunc={textMessageCreationSideEffectsFunc}
+ identityContext={identityContext}
/>
);
});
diff --git a/web/media/media-utils.js b/web/media/media-utils.js
--- a/web/media/media-utils.js
+++ b/web/media/media-utils.js
@@ -5,13 +5,16 @@
import { thumbHashToDataURL } from 'thumbhash';
import { fetchableMediaURI } from 'lib/media/media-utils.js';
+import type { AuthMetadata } from 'lib/shared/identity-client-context.js';
import type {
MediaType,
Dimensions,
MediaMissionStep,
MediaMissionFailure,
} from 'lib/types/media-types.js';
+import { isBlobServiceURI } from 'lib/utils/blob-service.js';
import { getMessageForException } from 'lib/utils/errors.js';
+import { createDefaultHTTPRequestHeaders } from 'lib/utils/services-utils.js';
import { probeFile } from './blob-utils.js';
import { decryptThumbhashToDataURL } from './encryption-utils.js';
@@ -64,15 +67,23 @@
* @returns Steps and the result of the preload. The preload is successful
* if the HTTP response is OK (20x).
*/
-async function preloadMediaResource(uri: string): Promise<{
+async function preloadMediaResource(
+ uri: string,
+ authMetadata: AuthMetadata,
+): Promise<{
steps: $ReadOnlyArray<MediaMissionStep>,
result: { +success: boolean },
}> {
+ let headers;
+ if (isBlobServiceURI(uri)) {
+ headers = createDefaultHTTPRequestHeaders(authMetadata);
+ }
+
const start = Date.now();
const mediaURI = fetchableMediaURI(uri);
let success, exceptionMessage;
try {
- const response = await fetch(mediaURI);
+ const response = await fetch(mediaURI, { headers });
// we need to read the blob to make sure the browser caches it
await response.blob();
success = response.ok;

File Metadata

Mime Type
text/plain
Expires
Sun, Nov 24, 10:33 PM (21 h, 56 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2577496
Default Alt Text
D10913.diff (11 KB)

Event Timeline