Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Uppy refresh token logic #1152

Open
wants to merge 5 commits into
base: refactor/thumbnail-view-logic
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 44 additions & 1 deletion src/api/api.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@
return new Promise((resolve, reject) => {
failedAuthRequestQueue.push((shouldReject?: boolean) => {
if (shouldReject) reject(error);
else resolve(imsApi(originalRequest));
else resolve(apiClient(originalRequest));

Check warning on line 82 in src/api/api.tsx

View check run for this annotation

Codecov / codecov/patch

src/api/api.tsx#L82

Added line #L82 was not covered by tests
});
});
}
Expand All @@ -91,6 +91,49 @@
return apiClient;
};

export function uppyOnAfterResponse(xhr: XMLHttpRequest) {
if (xhr.status >= 400 && xhr.status < 600) {
const errorMessage: string = (
JSON.parse(xhr.responseText) as APIError
).detail.toLocaleLowerCase();

Check warning on line 98 in src/api/api.tsx

View check run for this annotation

Codecov / codecov/patch

src/api/api.tsx#L96-L98

Added lines #L96 - L98 were not covered by tests

// Check if the token is invalid and needs refreshing
if (
xhr.status === 403 &&
errorMessage.includes('expired token') &&
localStorage.getItem('scigateway:token')
) {

Check warning on line 105 in src/api/api.tsx

View check run for this annotation

Codecov / codecov/patch

src/api/api.tsx#L101-L105

Added lines #L101 - L105 were not covered by tests
// Prevent other requests from also attempting to refresh while waiting for
// SciGateway to refresh the token

if (!isFetchingAccessToken) {
isFetchingAccessToken = true;

Check warning on line 110 in src/api/api.tsx

View check run for this annotation

Codecov / codecov/patch

src/api/api.tsx#L109-L110

Added lines #L109 - L110 were not covered by tests

// Request SciGateway to refresh the token
document.dispatchEvent(
new CustomEvent(MicroFrontendId, {
detail: {
type: InvalidateTokenType,
},
})
);
}

Check warning on line 120 in src/api/api.tsx

View check run for this annotation

Codecov / codecov/patch

src/api/api.tsx#L113-L120

Added lines #L113 - L120 were not covered by tests

// Create a new promise to wait for the token to be refreshed
return new Promise<void>((resolve, reject) => {
failedAuthRequestQueue.push((shouldReject?: boolean) => {
if (shouldReject) reject(xhr);
else resolve();
});
});
}
}

Check warning on line 130 in src/api/api.tsx

View check run for this annotation

Codecov / codecov/patch

src/api/api.tsx#L123-L130

Added lines #L123 - L130 were not covered by tests
}

export function uppyOnBeforeRequest(xhr: XMLHttpRequest) {
xhr.setRequestHeader('Authorization', `Bearer ${readSciGatewayToken()}`);
}

export const imsApi = createAuthenticatedClient({
getURL: (settings) => settings.imsApiUrl,
});
Expand Down
19 changes: 11 additions & 8 deletions src/common/images/uploadImagesDialog.component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import ProgressBar from '@uppy/progress-bar'; // Import the ProgressBar plugin
import { DashboardModal } from '@uppy/react';
import XHR from '@uppy/xhr-upload';
import React from 'react';
import { uppyOnAfterResponse, uppyOnBeforeRequest } from '../../api/api';
import { settings } from '../../settings';
import { getNonEmptyTrimmedString } from '../../utils';

Expand Down Expand Up @@ -47,6 +48,16 @@ const UploadImagesDialog = (props: UploadImagesDialogProps) => {
endpoint: `${url}/images`,
method: 'POST',
fieldName: 'upload_file',
limit: 1, // Limit uploads to one file at a time
// Reason 1: To avoid overloading the memory of the object-store API.
// Reason 2: To prevent multiple simultaneous uploads from triggering
// the token refresh process multiple times, which could lead to race conditions.
async onBeforeRequest(xhr) {
uppyOnBeforeRequest(xhr);
},
async onAfterResponse(xhr) {
await uppyOnAfterResponse(xhr);
},
});
});

Expand Down Expand Up @@ -86,14 +97,6 @@ const UploadImagesDialog = (props: UploadImagesDialogProps) => {
}
});

uppy.on('upload-error', (_file, _error, response) => {
if (response?.body?.id) {
// TODO: Implement logic to delete metadata using id
// If metadata exists for the given id, remove it from the api
// If not, do nothing and exit the function
}
});

return (
<DashboardModal
open={open}
Expand Down
Loading