Skip to content

Commit

Permalink
feat: upgrade dropbox client to v8.1.0
Browse files Browse the repository at this point in the history
  • Loading branch information
klieber committed Nov 22, 2020
1 parent 0fb1675 commit f914b50
Show file tree
Hide file tree
Showing 5 changed files with 121 additions and 49 deletions.
33 changes: 21 additions & 12 deletions lib/provider/dropbox/dropbox-client-factory.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
const DropboxTokenStore = require('./dropbox-token-store');
const { Dropbox } = require('dropbox');
const { Dropbox, DropboxAuth } = require('dropbox');
const fetch = require('node-fetch');
const logger = require('../../support/logger').create('lib/provider/dropbox/dropbox-client-factory');

Expand All @@ -11,7 +11,7 @@ module.exports = {

if (!token && !authorizationCode) {
logger.debug('no access token or authorization code available');
const authenticationUrl = new Dropbox({
const authenticationUrl = new DropboxAuth({
fetch: fetch,
clientId: config.client_id
}).getAuthenticationUrl(null, null, 'code', 'offline', null, 'none', false);
Expand All @@ -20,32 +20,41 @@ module.exports = {
} else {
if (!token) {
logger.debug('retrieving access token using authorization code');
const tempClient = new Dropbox({
const tempAuth = new DropboxAuth({
fetch: fetch,
clientId: config.client_id,
clientSecret: config.client_secret
});

token = await tempClient.getAccessTokenFromCode(null, authorizationCode);
const response = await tempAuth.getAccessTokenFromCode(null, authorizationCode);
if (response.status < 200 || response.status >= 300) {
throw new Error('Unable to get access token from code');
}
token = response.result;
}

const dropboxClient = new Dropbox({
const dropboxAuth = new DropboxAuth({
fetch: fetch,
clientId: config.client_id,
clientSecret: config.client_secret,
accessToken: token.accessToken,
refreshToken: token.refreshToken,
accessTokenExpiresAt: token.accessTokenExpiresAt
accessToken: token.access_token,
refreshToken: token.refresh_token,
accessTokenExpiresAt: new Date(Date.now() + token.expires_in)
});

logger.debug('refreshing access token');
await dropboxClient.checkAndRefreshAccessToken();
await dropboxAuth.checkAndRefreshAccessToken();

logger.debug('storing access token');
tokenStore.store({
accessToken: dropboxClient.getAccessToken(),
refreshToken: dropboxClient.getRefreshToken(),
accessTokenExpiresAt: dropboxClient.getAccessTokenExpiresAt()
accessToken: dropboxAuth.getAccessToken(),
refreshToken: dropboxAuth.getRefreshToken(),
accessTokenExpiresAt: dropboxAuth.getAccessTokenExpiresAt()
});

const dropboxClient = new Dropbox({
fetch: fetch,
auth: dropboxAuth
});

return dropboxClient;
Expand Down
37 changes: 29 additions & 8 deletions lib/provider/dropbox/dropbox-service.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@ const https = require('https');
const assert = require('assert').strict;
const DropboxContentHasher = require('./dropbox-content-hasher');

function isFailure(statusCode) {
let result = statusCode < 200 || statusCode >= 300;
return result;
}

class DropboxService {
#dropboxClient;

Expand All @@ -11,11 +16,15 @@ class DropboxService {
}

async listFiles(path) {
await this.#dropboxClient.checkAndRefreshAccessToken();
return await this.#dropboxClient.filesListFolder({
await this.#dropboxClient.auth.checkAndRefreshAccessToken();
let response = await this.#dropboxClient.filesListFolder({
path: path,
include_non_downloadable_files: false
});
if (isFailure(response.status)) {
throw new Error(`Unable to list files in path '${path}': ${response.status}`);
}
return response.result;
}

async downloadAndVerify(file, target) {
Expand All @@ -28,9 +37,13 @@ class DropboxService {
}

async download(filePath, target) {
await this.#dropboxClient.checkAndRefreshAccessToken();
await this.#dropboxClient.auth.checkAndRefreshAccessToken();

const data = await this.#dropboxClient.filesDownload({ path: filePath });
const response = await this.#dropboxClient.filesDownload({ path: filePath });
if (isFailure(response.status)) {
throw new Error(`Unable to download '${filePath}': ${response.status}`);
}
const data = response.result;
const fileDate = new Date(data.client_modified);

await fs.promises.mkdir(target, { recursive: true });
Expand All @@ -41,9 +54,13 @@ class DropboxService {
}

async downloadLargeFile(path, target) {
await this.#dropboxClient.checkAndRefreshAccessToken();
await this.#dropboxClient.auth.checkAndRefreshAccessToken();

const { metadata, link } = await this.#dropboxClient.filesGetTemporaryLink({ path: path });
const response = await this.#dropboxClient.filesGetTemporaryLink({ path: path });
if (isFailure(response.status)) {
throw new Error(`Unable to download '${path}': ${response.status}`);
}
const { metadata, link } = response.result;

await fs.promises.mkdir(target, { recursive: true });

Expand All @@ -67,8 +84,12 @@ class DropboxService {
}

async delete(file) {
await this.#dropboxClient.checkAndRefreshAccessToken();
return await this.#dropboxClient.filesDelete({ path: file.path_lower });
await this.#dropboxClient.auth.checkAndRefreshAccessToken();
const response = await this.#dropboxClient.filesDelete({ path: file.path_lower });
if (isFailure(response.status)) {
throw new Error(`Unable to delete '${file.path_lower}': ${response.status}`);
}
return response.result;
}

async hash(filename) {
Expand Down
89 changes: 66 additions & 23 deletions lib/provider/dropbox/dropbox-service.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ const dropboxClient = {
filesDownload: jest.fn(),
filesGetTemporaryLink: jest.fn(),
filesDelete: jest.fn(),
checkAndRefreshAccessToken: jest.fn()
auth: {
checkAndRefreshAccessToken: jest.fn()
}
};

const DROPBOX_FILE_NAME = 'mockFile.jpg';
Expand Down Expand Up @@ -65,9 +67,12 @@ describe('DropboxService', () => {
when(dropboxClient.filesDownload)
.calledWith({ path: `${SOURCE_PATH}/${DROPBOX_FILE_NAME}` })
.mockResolvedValue({
name: DROPBOX_FILE_NAME,
client_modified: MODIFY_DATE_STRING,
fileBinary: DROPBOX_FILE_BINARY
status: 200,
result: {
name: DROPBOX_FILE_NAME,
client_modified: MODIFY_DATE_STRING,
fileBinary: DROPBOX_FILE_BINARY
}
});

const expectedFilename = `${TARGET_PATH}/${DROPBOX_FILE_NAME}`;
Expand All @@ -79,6 +84,16 @@ describe('DropboxService', () => {
expect(fs.promises.writeFile).toHaveBeenCalledWith(expectedFilename, DROPBOX_FILE_BINARY, 'binary');
expect(fs.promises.utimes).toHaveBeenCalledWith(expectedFilename, MODIFY_DATE, MODIFY_DATE);
});

test('unable to download file', async () => {
when(dropboxClient.filesDownload)
.calledWith({ path: `${SOURCE_PATH}/${DROPBOX_FILE_NAME}` })
.mockResolvedValue({ status: 500 });

await expect(dropboxService.download(`${SOURCE_PATH}/${DROPBOX_FILE_NAME}`, TARGET_PATH)).rejects.toThrowError(
"Unable to download './source-path/mockFile.jpg': 500"
);
});
});

describe('downloadLargeFile', () => {
Expand All @@ -91,10 +106,13 @@ describe('DropboxService', () => {
when(dropboxClient.filesGetTemporaryLink)
.calledWith({ path: `${SOURCE_PATH}/${DROPBOX_FILE_NAME}` })
.mockResolvedValue({
link: FAKE_DOWNLOAD_LINK,
metadata: {
name: DROPBOX_FILE_NAME,
client_modified: MODIFY_DATE_STRING
status: 200,
result: {
link: FAKE_DOWNLOAD_LINK,
metadata: {
name: DROPBOX_FILE_NAME,
client_modified: MODIFY_DATE_STRING
}
}
});

Expand Down Expand Up @@ -127,10 +145,13 @@ describe('DropboxService', () => {
when(dropboxClient.filesGetTemporaryLink)
.calledWith({ path: `${SOURCE_PATH}/${DROPBOX_FILE_NAME}` })
.mockResolvedValue({
link: FAKE_DOWNLOAD_LINK,
metadata: {
name: DROPBOX_FILE_NAME,
client_modified: MODIFY_DATE_STRING
status: 200,
result: {
link: FAKE_DOWNLOAD_LINK,
metadata: {
name: DROPBOX_FILE_NAME,
client_modified: MODIFY_DATE_STRING
}
}
});

Expand Down Expand Up @@ -161,10 +182,13 @@ describe('DropboxService', () => {
when(dropboxClient.filesGetTemporaryLink)
.calledWith({ path: `${SOURCE_PATH}/${DROPBOX_FILE_NAME}` })
.mockResolvedValue({
link: FAKE_DOWNLOAD_LINK,
metadata: {
name: DROPBOX_FILE_NAME,
client_modified: MODIFY_DATE_STRING
status: 200,
result: {
link: FAKE_DOWNLOAD_LINK,
metadata: {
name: DROPBOX_FILE_NAME,
client_modified: MODIFY_DATE_STRING
}
}
});

Expand Down Expand Up @@ -197,10 +221,13 @@ describe('DropboxService', () => {
when(dropboxClient.filesGetTemporaryLink)
.calledWith({ path: `${DROPBOX_FILE_NAME}` })
.mockResolvedValue({
link: FAKE_DOWNLOAD_LINK,
metadata: {
name: DROPBOX_FILE_NAME,
client_modified: MODIFY_DATE_STRING
status: 200,
result: {
link: FAKE_DOWNLOAD_LINK,
metadata: {
name: DROPBOX_FILE_NAME,
client_modified: MODIFY_DATE_STRING
}
}
});

Expand All @@ -223,24 +250,40 @@ describe('DropboxService', () => {
});

describe('listFiles', () => {
test('lists files all files', async () => {
test('lists the files', async () => {
dropboxClient.filesListFolder.mockResolvedValue({
entries: [DROPBOX_FILE]
status: 200,
result: {
entries: [DROPBOX_FILE]
}
});

const response = await dropboxService.listFiles();
expect(response).not.toBeNull();
expect(response.entries).toHaveLength(1);
expect(response.entries).toMatchObject([DROPBOX_FILE]);
});

test('unable to list files', async () => {
dropboxClient.filesListFolder.mockResolvedValue({ status: 500 });
await expect(dropboxService.listFiles()).rejects.toThrowError("Unable to list files in path 'undefined': 500");
});
});

describe('delete', () => {
test('file is deleted', async () => {
when(dropboxClient.filesDelete).calledWith({ path: DROPBOX_FILE_NAME }).mockResolvedValue(DROPBOX_FILE);
when(dropboxClient.filesDelete)
.calledWith({ path: DROPBOX_FILE_NAME })
.mockResolvedValue({ status: 200, result: DROPBOX_FILE });

await expect(dropboxService.delete(DROPBOX_FILE)).resolves.toBe(DROPBOX_FILE);
});

test('unable to delete file', async () => {
when(dropboxClient.filesDelete).calledWith({ path: DROPBOX_FILE_NAME }).mockResolvedValue({ status: 500 });

await expect(dropboxService.delete(DROPBOX_FILE)).rejects.toThrowError("Unable to delete 'mockFile.jpg': 500");
});
});

describe('hash', () => {
Expand Down
9 changes: 4 additions & 5 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
"cron": "1.8.2",
"date-fns": "2.16.1",
"dist-exiftool": "10.53.0",
"dropbox": "5.2.1",
"dropbox": "8.1.0",
"ffprobe": "1.1.2",
"ffprobe-static": "3.0.0",
"node-exiftool": "2.3.0",
Expand Down

0 comments on commit f914b50

Please sign in to comment.