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

Add cookie auth and custom header feature #814

Merged
merged 1 commit into from
Oct 1, 2021
Merged
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
2 changes: 2 additions & 0 deletions generator/typescript/index.d.tstemplate
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,8 @@ export interface DropboxOptions {
domain?: string;
// A custom delimiter to use when separating domain subdomain. This should only be used for testing as scaffolding.
domainDelimiter?: string;
// An object (in the form of header: value) designed to set custom headers to use during a request.
customHeaders?: object;
}

export class DropboxResponseError<T> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file is the template, you need to re-generate the sdk to get this into the generated code. Make sure your submodules are at the same place as main is (just pull from main in each repo)

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "dropbox",
"version": "10.11.0",
"version": "10.12.0",
"registry": "npm",
"description": "The Dropbox JavaScript SDK is a lightweight, promise based interface to the Dropbox v2 API that works in both nodejs and browser environments.",
"main": "cjs/index.js",
Expand Down
1 change: 1 addition & 0 deletions src/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export const APP_AUTH = 'app';
export const USER_AUTH = 'user';
export const TEAM_AUTH = 'team';
export const NO_AUTH = 'noauth';
export const COOKIE = 'cookie';

export const DEFAULT_API_DOMAIN = 'dropboxapi.com';
export const DEFAULT_DOMAIN = 'dropbox.com';
Expand Down
12 changes: 12 additions & 0 deletions src/dropbox.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
TEAM_AUTH,
USER_AUTH,
NO_AUTH,
COOKIE,
} from './constants.js';
import { routes } from '../lib/routes.js';
import DropboxAuth from './auth.js';
Expand Down Expand Up @@ -50,6 +51,8 @@ const b64 = typeof btoa === 'undefined'
* should only be used for testing as scaffolding to avoid making network requests.
* @arg {String} [options.domainDelimiter] - A custom delimiter to use when separating domain from
* subdomain. This should only be used for testing as scaffolding.
* @arg {Object} [options.customHeaders] - An object (in the form of header: value) designed to set
* custom headers to use during a request.
*/
export default class Dropbox {
constructor(options) {
Expand All @@ -68,6 +71,7 @@ export default class Dropbox {

this.domain = options.domain;
this.domainDelimiter = options.domainDelimiter;
this.customHeaders = options.customHeaders;

Object.assign(this, routes);
}
Expand Down Expand Up @@ -125,6 +129,8 @@ export default class Dropbox {
break;
case NO_AUTH:
break;
case COOKIE:
break;
default:
throw new Error(`Unhandled auth type: ${auth}`);
}
Expand Down Expand Up @@ -206,5 +212,11 @@ export default class Dropbox {
if (this.pathRoot) {
options.headers['Dropbox-API-Path-Root'] = this.pathRoot;
}
if (this.customHeaders) {
const headerKeys = Object.keys(this.customHeaders);
headerKeys.forEach((header) => {
options.headers[header] = this.customHeaders[header];
});
}
}
}
56 changes: 56 additions & 0 deletions test/unit/dropbox.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
TEAM_AUTH,
APP_AUTH,
NO_AUTH,
COOKIE,
} from '../../src/constants.js';
import { Dropbox, DropboxAuth } from '../../index.js';

Expand All @@ -28,6 +29,18 @@ describe('Dropbox', () => {
});
});

describe('customHeaders', () => {
it('can be set in the constructor', () => {
const dbx = new Dropbox({ customHeaders: { foo: 'bar' } });
chai.assert.equal(dbx.customHeaders.foo, 'bar');
});

it('is undefined if not set in constructor', () => {
const dbx = new Dropbox();
chai.assert.equal(dbx.customHeaders, undefined);
});
});

describe('RPC requests', () => {
it('request() calls the correct request method', () => {
const dbx = new Dropbox();
Expand Down Expand Up @@ -86,6 +99,20 @@ describe('Dropbox', () => {
chai.assert.equal(APP_AUTH, dbx.rpcRequest.getCall(0).args[2]);
});

it('completes a cookie auth RPC request', () => {
const dbxAuth = new DropboxAuth();
const dbx = new Dropbox({ auth: dbxAuth });
const rpcSpy = sinon.spy(dbx, 'rpcRequest');
dbx.request('path', {}, COOKIE, 'api', RPC)
.catch((error) => {
fail(error);
});
chai.assert.isTrue(rpcSpy.calledOnce);
chai.assert.equal('path', dbx.rpcRequest.getCall(0).args[0]);
chai.assert.deepEqual({}, dbx.rpcRequest.getCall(0).args[1]);
chai.assert.equal(COOKIE, dbx.rpcRequest.getCall(0).args[2]);
});

it('throws an error for invalid request styles', () => {
chai.assert.throws(
Dropbox.prototype.request.bind(Dropbox, '', {}, 'user', 'api', 'BADTYPE'),
Expand Down Expand Up @@ -120,6 +147,10 @@ describe('Dropbox', () => {
const dbx = new Dropbox();
return chai.assert.isRejected(dbx.uploadRequest('path', {}, NO_AUTH, 'api'), Error, `Unexpected auth type: ${NO_AUTH}`);
});
it('throws an error for cookie auth', () => {
const dbx = new Dropbox();
return chai.assert.isRejected(dbx.uploadRequest('path', {}, COOKIE, 'api'), Error, `Unexpected auth type: ${COOKIE}`);
});
});

describe('Download Requests', () => {
Expand Down Expand Up @@ -149,6 +180,11 @@ describe('Dropbox', () => {
const dbx = new Dropbox();
return chai.assert.isRejected(dbx.downloadRequest('path', {}, NO_AUTH, 'api'), Error, `Unexpected auth type: ${NO_AUTH}`);
});

it('throws an error for cookie auth', () => {
const dbx = new Dropbox();
return chai.assert.isRejected(dbx.downloadRequest('path', {}, COOKIE, 'api'), Error, `Unexpected auth type: ${COOKIE}`);
});
});

describe('pathRoot', () => {
Expand Down Expand Up @@ -186,5 +222,25 @@ describe('Dropbox', () => {
}
}
});

it('sets custom headers correctly', () => {
const dbx = new Dropbox({
customHeaders: {
foo: 'bar',
milk: 'shake',
cookie: 'hash',
},
});

const fetchOptions = {
headers: {},
};

dbx.setCommonHeaders(fetchOptions);
const { headers } = fetchOptions;
chai.assert.equal(headers.foo, 'bar');
chai.assert.equal(headers.milk, 'shake');
chai.assert.equal(headers.cookie, 'hash');
});
});
});
2 changes: 2 additions & 0 deletions types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,8 @@ export interface DropboxOptions {
domain?: string;
// A custom delimiter to use when separating domain subdomain. This should only be used for testing as scaffolding.
domainDelimiter?: string;
// An object (in the form of header: value) designed to set custom headers to use during a request.
customHeaders?: object;
}

export class DropboxResponseError<T> {
Expand Down