Skip to content

Commit 9a83861

Browse files
committed
Generate tokens just-in-time
Auth tokens are now retrieved just-in-time by the permanent file system (rather than being passed during the creation of the permanent file system). This is a critical fix because (1) it prevents certain paths that would lead to stale tokens but also (2) it means that creating a permanent file system becomes a synchronous operation. This also resolves a bug where the failure to generate a token could result in a hanging sftp connection. Issue #288 Permanent file system errors can result in hung connections
1 parent 04c7d3c commit 9a83861

File tree

3 files changed

+354
-412
lines changed

3 files changed

+354
-412
lines changed

src/classes/PermanentFileSystem.ts

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ import type {
4343
Attributes,
4444
FileEntry,
4545
} from 'ssh2';
46+
import type { AuthTokenManager } from './AuthTokenManager';
4647

4748
const isRootPath = (requestedPath: string): boolean => (
4849
requestedPath === '/'
@@ -79,10 +80,10 @@ export class PermanentFileSystem {
7980

8081
private archivesCache?: Archive[];
8182

82-
private readonly authToken;
83+
private readonly authTokenManager;
8384

84-
public constructor(authToken: string) {
85-
this.authToken = authToken;
85+
public constructor(authTokenManager: AuthTokenManager) {
86+
this.authTokenManager = authTokenManager;
8687
}
8788

8889
private static loadRootFileEntries(): FileEntry[] {
@@ -191,7 +192,7 @@ export class PermanentFileSystem {
191192
const childName = path.basename(requestedPath);
192193
const parentFolder = await this.loadFolder(parentPath);
193194
return createFolder(
194-
this.getClientConfiguration(),
195+
await this.getClientConfiguration(),
195196
{
196197
name: childName,
197198
},
@@ -201,7 +202,7 @@ export class PermanentFileSystem {
201202

202203
public async deleteDirectory(requestedPath: string): Promise<void> {
203204
const account = await getAuthenticatedAccount(
204-
this.getClientConfiguration(),
205+
await this.getClientConfiguration(),
205206
);
206207
if (!account.isSftpDeletionEnabled) {
207208
throw new OperationNotAllowedError('You must enable SFTP deletion directly in your account settings.');
@@ -220,7 +221,7 @@ export class PermanentFileSystem {
220221
const folder = await this.loadFolder(requestedPath);
221222

222223
await deleteFolder(
223-
this.getClientConfiguration(),
224+
await this.getClientConfiguration(),
224225
folder.id,
225226
);
226227
}
@@ -242,14 +243,14 @@ export class PermanentFileSystem {
242243
fileSystemCompatibleName: archiveRecordName,
243244
};
244245
const s3Url = await uploadFile(
245-
this.getClientConfiguration(),
246+
await this.getClientConfiguration(),
246247
dataStream,
247248
fileFragment,
248249
archiveRecordfragment,
249250
parentFolder,
250251
);
251252
await createArchiveRecord(
252-
this.getClientConfiguration(),
253+
await this.getClientConfiguration(),
253254
s3Url,
254255
fileFragment,
255256
archiveRecordfragment,
@@ -259,7 +260,7 @@ export class PermanentFileSystem {
259260

260261
public async deleteFile(requestedPath: string): Promise<void> {
261262
const account = await getAuthenticatedAccount(
262-
this.getClientConfiguration(),
263+
await this.getClientConfiguration(),
263264
);
264265
if (!account.isSftpDeletionEnabled) {
265266
throw new OperationNotAllowedError('You must enable SFTP deletion directly in your account settings.');
@@ -274,7 +275,7 @@ export class PermanentFileSystem {
274275
);
275276

276277
await deleteArchiveRecord(
277-
this.getClientConfiguration(),
278+
await this.getClientConfiguration(),
278279
archiveRecord.id,
279280
);
280281
}
@@ -338,7 +339,7 @@ export class PermanentFileSystem {
338339
childName,
339340
);
340341
const populatedArchiveRecord = await getArchiveRecord(
341-
this.getClientConfiguration(),
342+
await this.getClientConfiguration(),
342343
archiveRecord.id,
343344
archiveId,
344345
);
@@ -380,17 +381,18 @@ export class PermanentFileSystem {
380381
return this.loadArchiveRecords(archiveRecordPaths);
381382
}
382383

383-
private getClientConfiguration(): ClientConfiguration {
384+
private async getClientConfiguration(): Promise<ClientConfiguration> {
385+
const authToken = await this.authTokenManager.getAuthToken();
384386
return {
385-
bearerToken: this.authToken,
387+
bearerToken: authToken,
386388
baseUrl: process.env.PERMANENT_API_BASE_PATH,
387389
};
388390
}
389391

390392
private async loadArchives(): Promise<Archive[]> {
391393
if (!this.archivesCache) {
392394
this.archivesCache = await getArchives(
393-
this.getClientConfiguration(),
395+
await this.getClientConfiguration(),
394396
);
395397
}
396398
return this.archivesCache;
@@ -417,7 +419,7 @@ export class PermanentFileSystem {
417419
return cachedArchiveFolders;
418420
}
419421
const archiveFolders = await getArchiveFolders(
420-
this.getClientConfiguration(),
422+
await this.getClientConfiguration(),
421423
archiveId,
422424
);
423425
this.archiveFoldersCache.set(archiveId, archiveFolders);
@@ -506,7 +508,7 @@ export class PermanentFileSystem {
506508
childName,
507509
);
508510
const populatedTargetFolder = await getFolder(
509-
this.getClientConfiguration(),
511+
await this.getClientConfiguration(),
510512
targetFolder.id,
511513
archiveId,
512514
);

src/classes/PermanentFileSystemManager.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { logger } from '../logger';
22
import { PermanentFileSystem } from './PermanentFileSystem';
3+
import type { AuthTokenManager } from './AuthTokenManager';
34

45
export class PermanentFileSystemManager {
56
private readonly permanentFileSystems = new Map<string, PermanentFileSystem>();
@@ -8,15 +9,15 @@ export class PermanentFileSystemManager {
89

910
public getCurrentPermanentFileSystemForUser(
1011
user: string,
11-
authToken: string,
12+
authTokenManager: AuthTokenManager,
1213
): PermanentFileSystem {
1314
logger.silly('Get permanent file system for user', { user });
1415
this.resetDeletionTimeout(user);
1516
const existingFileSystem = this.permanentFileSystems.get(user);
1617
if (existingFileSystem !== undefined) {
1718
return existingFileSystem;
1819
}
19-
const permanentFileSystem = new PermanentFileSystem(authToken);
20+
const permanentFileSystem = new PermanentFileSystem(authTokenManager);
2021
this.permanentFileSystems.set(
2122
user,
2223
permanentFileSystem,

0 commit comments

Comments
 (0)