Skip to content

Commit

Permalink
Migrate from callbacks to promises (#40)
Browse files Browse the repository at this point in the history
* Migrate callback logic to promise

- Add timeout option to throw an error if no response is returned
- Downgrade the Dropbox dependency to 7.0.0
- Add Upgrading.md for v2.0.0

* Add upgrading.md
  • Loading branch information
rogebrd authored Nov 13, 2020
1 parent dbe35c6 commit 4c96c44
Show file tree
Hide file tree
Showing 6 changed files with 81 additions and 40 deletions.
32 changes: 32 additions & 0 deletions UPGRADING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Upgrading the OAuth Popup

This document shows you how to upgrade to the latest version of the popup, accomodating any breaking changes introduced by major version updates. If you find any issues with either this guide on upgrading or the changes introduced in the new version, please see file an issue.

# Upgrading from v1.X.X to v2.X.X

## Updating from callbacks to promises

We have updated the library to use the newer promises over callbacks. Previously this would have looked like this:

```
var popup = new DropboxPopup();
popup.authUser((auth) => {
// Do logic with auth
});
```

This now becomes:

```
var popup = new DropboxPopup();
popup.authUser().then((auth) => {
// Do logic with auth
}).catch((error) => {
// Handle Error
});
```

## Timeout Functionality

We have also added timeout functionality. When attempting to authenticate, we will timeout and throw an error if the request is not fulfilled in the time specified. The default is 5 minutes but can be configured to any time in milliseconds.

2 changes: 1 addition & 1 deletion examples/browser.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<script src="https://cdn.jsdelivr.net/npm/promise-polyfill@7/dist/polyfill.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fetch/2.0.3/fetch.js"></script>
<script src="https://cdn.jsdelivr.net/npm/dropbox/dist/Dropbox-sdk.js"></script>
<script src="https://cdn.jsdelivr.net/npm/dropbox-oauth-popup@1.4.1/dist/dropboxPopup.js"></script>
<script src="https://cdn.jsdelivr.net/npm/dropbox-oauth-popup@2.0.0/dist/dropboxPopup.js"></script>
</head>

<body>
Expand Down
2 changes: 1 addition & 1 deletion package-lock.json

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

5 changes: 2 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "dropbox-oauth-popup",
"version": "1.4.1",
"version": "2.0.0",
"registry": "npm",
"description": "This is a simple addition built onto the Dropbox SDK that allows for OAuth in the browser to be done via a popup window.",
"homepage": "https://github.com/rogebrd/dropbox-oauth-popup",
Expand Down Expand Up @@ -30,7 +30,7 @@
"rollup-plugin-terser": "^7.0.2"
},
"dependencies": {
"dropbox": "^7.1.0"
"dropbox": "^7.0.0"
},
"browserslist": [
"> 0.25%",
Expand All @@ -40,7 +40,6 @@
"*.md",
"LICENSE",
"src",
"test",
"dist"
],
"repository": {
Expand Down
74 changes: 41 additions & 33 deletions src/dropboxPopup.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ const defaultWindowOptions = {
left: 100,
};

const defaultTimeout = 300000; // 5 minutes

/**
* @class DropboxPopup
* @classdesc The DropboxPopup class is to provide a simple popup window to preform OAuth in.
Expand Down Expand Up @@ -57,16 +59,18 @@ const defaultWindowOptions = {
* @param {object} [windowOptions.additionalParams] - Any additional parameters desired to be used
* with the window.open() command. Note, by default, we add the parameters toolbar=no and menubar=no
* in order to ensure this opens as a popup.
* @param {number} timeout - The timeout for when to give up on the promise and throw an error
*/
export default class DropboxPopup {
constructor(options, windowOptions) {
constructor(options, windowOptions, timeout) {
this.clientId = options.clientId;
this.redirectUri = options.redirectUri;
this.clientSecret = options.clientSecret || '';
this.tokenAccessType = options.tokenAccessType || 'offline';
this.scope = options.scope || null;
this.includeGrantedScopes = options.includeGrantedScopes || 'none';
this.usePKCE = options.usePKCE || false;
this.timeout = timeout || defaultTimeout;

this.authObject = new DropboxAuth({
clientId: this.clientId,
Expand All @@ -90,40 +94,44 @@ export default class DropboxPopup {
/**
* The main function to handle authentication via a popup window.
*
* @param {Function} callback - The callback function which will utilize the DropboxAuth object.
* @returns {void}
* @returns {Promise<DropboxAuth>} The promise which contains the end auth object
*/
authUser(callback) {
window.removeEventListener('message', this.handleRedirect);
this.callback = callback;
this.callback.bind(this);
const authUrl = this.authObject.getAuthenticationUrl(this.redirectUri, this.state, 'code', this.tokenAccessType, this.scope, this.includeGrantedScopes, this.usePKCE);
const popupWindow = window.open(authUrl, windowName, this.windowOptions);
popupWindow.focus();
authUser() {
const popup = this;
return new Promise((resolve, reject) => {
setTimeout(() => {
reject(new Error('Request timed out'));
}, popup.timeout);

window.addEventListener('message', (event) => this.handleRedirect(event), false);
}
/**
* The function in charge of handling the redirect once the popup has completed.
*
* @param {MessageEvent} event - The incoming message from the popup window.
* @returns {void}
*/
function handleRedirect(event) {
window.removeEventListener('message', popup.handleRedirect);

/**
* The function in charge of handling the redirect once the popup has completed.
*
* @param {MessageEvent} event - The incoming message from the popup window.
* @returns {void}
*/
handleRedirect(event) {
const { data } = event;
const urlParams = new URLSearchParams(data);
const code = urlParams.get('code');
this.authObject.getAccessTokenFromCode(this.redirectUri, code)
.then((response) => {
const { result } = response;
this.authObject.setAccessToken(result.access_token);
this.authObject.setRefreshToken(result.refresh_token);
this.authObject.setAccessTokenExpiresAt(new Date(Date.now() + result.expires_in));
this.callback(this.authObject);
})
.catch((error) => {
throw error;
});
const { data } = event;
const urlParams = new URLSearchParams(data);
const code = urlParams.get('code');

popup.authObject.getAccessTokenFromCode(popup.redirectUri, code).then((response) => {
const { result } = response;
popup.authObject.setAccessToken(result.access_token);
popup.authObject.setRefreshToken(result.refresh_token);
popup.authObject.setAccessTokenExpiresAt(new Date(Date.now() + result.expires_in));
resolve(popup.authObject);
})
.catch((error) => {
reject(error);
});
}

const authUrl = popup.authObject.getAuthenticationUrl(popup.redirectUri, popup.state, 'code', popup.tokenAccessType, popup.scope, popup.includeGrantedScopes, popup.usePKCE);
const popupWindow = window.open(authUrl, windowName, popup.windowOptions);
popupWindow.focus();
window.addEventListener('message', handleRedirect, false);
});
}
}
6 changes: 4 additions & 2 deletions test/static/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,10 @@ <h1>Dropbox OAuth Popup Window</h1>
width: 400,
top: 100,
left: 100
});
}, 200000);
function runAuth() {
document.getElementById("result").innerHTML = "Waiting for auth...";
popup.authUser((auth) => {
popup.authUser().then((auth) => {
const dbx = new Dropbox.Dropbox(auth);
dbx.usersGetCurrentAccount()
.then((response) => {
Expand All @@ -43,6 +43,8 @@ <h1>Dropbox OAuth Popup Window</h1>
.catch((error) => {
document.getElementById("result").innerHTML = error;
});
}).catch((error) => {
document.getElementById("result").innerHTML = error;
});
}
</script>
Expand Down

0 comments on commit 4c96c44

Please sign in to comment.