Skip to content

Commit ccf293f

Browse files
committed
[keyserver] Refresh Dropbox upload tokens
Summary: Depends on D15618 Test Plan: Test on prod Subscribers: tomek Differential Revision: https://phab.comm.dev/D15619
1 parent 413b7df commit ccf293f

1 file changed

Lines changed: 69 additions & 38 deletions

File tree

keyserver/src/backups/dropbox-backup-storage-adapter.js

Lines changed: 69 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -93,17 +93,24 @@ class DropboxBackupStorageAdapter {
9393
sessionID: ?string,
9494
offset: number,
9595
chunk: Buffer,
96-
): Promise<string> {
96+
): Promise<{
97+
+accessToken: string,
98+
+sessionID: string,
99+
}> {
97100
if (!sessionID) {
98-
const response = await this.contentRequest(
99-
accessToken,
100-
'files/upload_session/start',
101-
{ close: false },
102-
chunk,
103-
);
104-
return response.session_id;
101+
const { accessToken: currentAccessToken, response } =
102+
await this.contentRequest(
103+
accessToken,
104+
'files/upload_session/start',
105+
{ close: false },
106+
chunk,
107+
);
108+
return {
109+
accessToken: currentAccessToken,
110+
sessionID: response.session_id,
111+
};
105112
}
106-
await this.contentRequest(
113+
const { accessToken: currentAccessToken } = await this.contentRequest(
107114
accessToken,
108115
'files/upload_session/append_v2',
109116
{
@@ -115,7 +122,10 @@ class DropboxBackupStorageAdapter {
115122
},
116123
chunk,
117124
);
118-
return sessionID;
125+
return {
126+
accessToken: currentAccessToken,
127+
sessionID,
128+
};
119129
}
120130

121131
async finishUpload(
@@ -124,9 +134,9 @@ class DropboxBackupStorageAdapter {
124134
sessionID: ?string,
125135
offset: number,
126136
chunk: Buffer,
127-
): Promise<void> {
137+
): Promise<string> {
128138
if (!sessionID) {
129-
await this.contentRequest(
139+
const { accessToken: currentAccessToken } = await this.contentRequest(
130140
accessToken,
131141
'files/upload',
132142
{
@@ -137,9 +147,9 @@ class DropboxBackupStorageAdapter {
137147
},
138148
chunk,
139149
);
140-
return;
150+
return currentAccessToken;
141151
}
142-
await this.contentRequest(
152+
const { accessToken: currentAccessToken } = await this.contentRequest(
143153
accessToken,
144154
'files/upload_session/finish',
145155
{
@@ -156,6 +166,7 @@ class DropboxBackupStorageAdapter {
156166
},
157167
chunk,
158168
);
169+
return currentAccessToken;
159170
}
160171

161172
filePath(filename: string): string {
@@ -212,36 +223,54 @@ class DropboxBackupStorageAdapter {
212223
endpoint: string,
213224
args: Object,
214225
content: Buffer,
215-
): Promise<any> {
216-
const response = await nodeFetch(
217-
`https://content.dropboxapi.com/2/${endpoint}`,
218-
{
219-
method: 'POST',
220-
body: content,
221-
headers: {
222-
'Authorization': `Bearer ${accessToken}`,
223-
'Content-Type': 'application/octet-stream',
224-
'Dropbox-API-Arg': JSON.stringify(args),
226+
): Promise<{
227+
+accessToken: string,
228+
+response: any,
229+
}> {
230+
const tryContentRequest = async (
231+
currentAccessToken: string,
232+
): Promise<{
233+
+accessToken: string,
234+
+response: any,
235+
}> => {
236+
const response = await nodeFetch(
237+
`https://content.dropboxapi.com/2/${endpoint}`,
238+
{
239+
method: 'POST',
240+
body: content,
241+
headers: {
242+
'Authorization': `Bearer ${currentAccessToken}`,
243+
'Content-Type': 'application/octet-stream',
244+
'Dropbox-API-Arg': JSON.stringify(args),
245+
},
225246
},
226-
},
227-
);
228-
if (!response.ok) {
229-
const responseText = await response.text();
230-
throw mapDropboxError(response.status, responseText);
231-
}
247+
);
248+
if (!response.ok) {
249+
const responseText = await response.text();
250+
if (
251+
response.status === 401 &&
252+
responseText.includes('expired_access_token')
253+
) {
254+
const refreshedAccessToken = await this.refreshAccessToken();
255+
return await tryContentRequest(refreshedAccessToken);
256+
}
257+
throw mapDropboxError(response.status, responseText);
258+
}
232259

233-
const responseText = await response.text();
234-
if (!responseText) {
235-
return {};
236-
}
237-
return JSON.parse(responseText);
260+
const responseText = await response.text();
261+
return {
262+
accessToken: currentAccessToken,
263+
response: responseText ? JSON.parse(responseText) : {},
264+
};
265+
};
266+
return await tryContentRequest(accessToken);
238267
}
239268
}
240269

241270
const dropboxChunkSize = 16 * 1024 * 1024;
242271
class DropboxUploadWriteStream extends Writable {
243272
+adapter: DropboxBackupStorageAdapter;
244-
+accessToken: string;
273+
accessToken: string;
245274
+filename: string;
246275
sessionID: ?string;
247276
offset: number;
@@ -290,19 +319,21 @@ class DropboxUploadWriteStream extends Writable {
290319
this.bufferedChunk = Buffer.concat([this.bufferedChunk, buffer]);
291320
while (this.bufferedChunk.length >= dropboxChunkSize) {
292321
const uploadChunk = this.bufferedChunk.subarray(0, dropboxChunkSize);
293-
this.sessionID = await this.adapter.uploadChunk(
322+
const uploadResponse = await this.adapter.uploadChunk(
294323
this.accessToken,
295324
this.sessionID,
296325
this.offset,
297326
uploadChunk,
298327
);
328+
this.accessToken = uploadResponse.accessToken;
329+
this.sessionID = uploadResponse.sessionID;
299330
this.offset += uploadChunk.length;
300331
this.bufferedChunk = this.bufferedChunk.subarray(dropboxChunkSize);
301332
}
302333
}
303334

304335
async finish(): Promise<void> {
305-
await this.adapter.finishUpload(
336+
this.accessToken = await this.adapter.finishUpload(
306337
this.accessToken,
307338
this.filename,
308339
this.sessionID,

0 commit comments

Comments
 (0)