diff --git a/packages/@uppy/companion-client/src/Provider.js b/packages/@uppy/companion-client/src/Provider.js index d575a6a4c..138f6975e 100644 --- a/packages/@uppy/companion-client/src/Provider.js +++ b/packages/@uppy/companion-client/src/Provider.js @@ -58,9 +58,9 @@ module.exports = class Provider extends RequestClient { return this.get(`${this.id}/list/${directory || ''}`) } - logout (redirect = location.href) { + logout () { return new Promise((resolve, reject) => { - this.get(`${this.id}/logout?redirect=${redirect}`) + this.get(`${this.id}/logout`) .then((res) => { this.uppy.getPlugin(this.pluginId).storage.removeItem(this.tokenKey) .then(() => resolve(res)) diff --git a/packages/@uppy/companion/src/server/controllers/logout.js b/packages/@uppy/companion/src/server/controllers/logout.js index f5b1c696a..3155827f3 100644 --- a/packages/@uppy/companion/src/server/controllers/logout.js +++ b/packages/@uppy/companion/src/server/controllers/logout.js @@ -5,20 +5,30 @@ const tokenService = require('../helpers/jwt') * @param {object} req * @param {object} res */ -function logout (req, res) { - const session = req.session +function logout (req, res, next) { + const cleanSession = () => { + if (req.session.grant) { + req.session.grant.state = null + req.session.grant.dynamic = null + } + } const providerName = req.params.providerName + const token = req.uppy.providerTokens ? req.uppy.providerTokens[providerName] : null + if (token) { + req.uppy.provider.logout({ token }, (err, data) => { + if (err) { + return next(err) + } - if (req.uppy.providerTokens && req.uppy.providerTokens[providerName]) { - delete req.uppy.providerTokens[providerName] - tokenService.removeFromCookies(res, req.uppy.options, req.uppy.provider.authProviderName) + delete req.uppy.providerTokens[providerName] + tokenService.removeFromCookies(res, req.uppy.options, req.uppy.provider.authProviderName) + cleanSession() + res.json(Object.assign({ ok: true }, data)) + }) + } else { + cleanSession() + res.json({ ok: true, revoked: false }) } - - if (session.grant) { - session.grant.state = null - session.grant.dynamic = null - } - res.json({ ok: true }) } module.exports = logout diff --git a/packages/@uppy/companion/src/server/provider/drive/index.js b/packages/@uppy/companion/src/server/provider/drive/index.js index 19c1c7a69..635c2b0af 100644 --- a/packages/@uppy/companion/src/server/provider/drive/index.js +++ b/packages/@uppy/companion/src/server/provider/drive/index.js @@ -133,6 +133,20 @@ class Drive { }) } + logout ({ token }, done) { + return this.client + .get('https://accounts.google.com/o/oauth2/revoke') + .qs({ token }) + .request((err, resp) => { + if (err || resp.statusCode !== 200) { + logger.error(err, 'provider.drive.logout.error') + done(this._error(err, resp)) + return + } + done(null, { revoked: true }) + }) + } + adaptData (res, teamDrivesResp, uppy, directory, query) { const adaptItem = (item) => ({ isFolder: adapter.isFolder(item), diff --git a/packages/@uppy/companion/src/server/provider/dropbox/index.js b/packages/@uppy/companion/src/server/provider/dropbox/index.js index a6c73db3d..a31c3f740 100644 --- a/packages/@uppy/companion/src/server/provider/dropbox/index.js +++ b/packages/@uppy/companion/src/server/provider/dropbox/index.js @@ -160,6 +160,21 @@ class DropBox { }) } + logout ({ token }, done) { + return this.client + .post('auth/token/revoke') + .options({ version: '2' }) + .auth(token) + .request((err, resp) => { + if (err || resp.statusCode !== 200) { + logger.error(err, 'provider.dropbox.size.error') + done(this._error(err, resp)) + return + } + done(null, { revoked: true }) + }) + } + adaptData (res, uppy) { const data = { username: adapter.getUsername(res), items: [] } const items = adapter.getItemSubList(res) diff --git a/packages/@uppy/companion/src/server/provider/facebook/index.js b/packages/@uppy/companion/src/server/provider/facebook/index.js index 6bd5026e9..d5226b25c 100644 --- a/packages/@uppy/companion/src/server/provider/facebook/index.js +++ b/packages/@uppy/companion/src/server/provider/facebook/index.js @@ -112,6 +112,20 @@ class Facebook { }) } + logout ({ token }, done) { + return this.client + .delete('me/permissions') + .auth(token) + .request((err, resp) => { + if (err || resp.statusCode !== 200) { + logger.error(err, 'provider.facebook.logout.error') + done(this._error(err, resp)) + return + } + done(null, { revoked: true }) + }) + } + adaptData (res, username, directory, currentQuery) { const data = { username: username, items: [] } const items = adapter.getItemSubList(res) diff --git a/packages/@uppy/companion/src/server/provider/instagram/index.js b/packages/@uppy/companion/src/server/provider/instagram/index.js index ccbc94431..a5865e344 100644 --- a/packages/@uppy/companion/src/server/provider/instagram/index.js +++ b/packages/@uppy/companion/src/server/provider/instagram/index.js @@ -108,6 +108,11 @@ class Instagram { }) } + logout (_, done) { + // access revoke is not supported by Instagram's API + done(null, { revoked: false, manual_revoke_url: 'https://www.instagram.com/accounts/manage_access/' }) + } + adaptData (res, username) { const data = { username: username, items: [] } const items = adapter.getItemSubList(res) diff --git a/packages/@uppy/core/src/index.js b/packages/@uppy/core/src/index.js index ece5c08f8..c15a2221b 100644 --- a/packages/@uppy/core/src/index.js +++ b/packages/@uppy/core/src/index.js @@ -49,6 +49,7 @@ class Uppy { youCanOnlyUploadFileTypes: 'You can only upload: %{types}', companionError: 'Connection with Companion failed', companionAuthError: 'Authorization required', + companionUnauthorizeHint: 'To unauthorize to your %{provider} account, please go to %{url}', failedToUpload: 'Failed to upload %{file}', noInternetConnection: 'No Internet connection', connectedToInternet: 'Connected to the Internet', diff --git a/packages/@uppy/provider-views/src/index.js b/packages/@uppy/provider-views/src/index.js index dec9cc946..8c1c74451 100644 --- a/packages/@uppy/provider-views/src/index.js +++ b/packages/@uppy/provider-views/src/index.js @@ -200,9 +200,17 @@ module.exports = class ProviderView { * Removes session token on client side. */ logout () { - this.provider.logout(location.href) + this.provider.logout() .then((res) => { if (res.ok) { + if (!res.revoked) { + const message = this.plugin.uppy.i18n('companionUnauthorizeHint', { + provider: this.plugin.title, + url: res.manual_revoke_url + }) + this.plugin.uppy.info(message) + } + const newState = { authenticated: false, files: [],