瀏覽代碼

feat(sync): add revoke button

close violentmonkey/violentmonkey#83
Gerald 9 年之前
父節點
當前提交
36cfd18cba

+ 6 - 2
src/background/app.js

@@ -155,8 +155,12 @@ var commands = {
     setBadge(num, src);
     setBadge(num, src);
     return false;
     return false;
   },
   },
-  Authenticate: function (_data, _src) {
-    sync.authenticate();
+  SyncAuthorize: function (_data, _src) {
+    sync.authorize();
+    return false;
+  },
+  SyncRevoke: function (_data, _src) {
+    sync.revoke();
     return false;
     return false;
   },
   },
   SyncStart: function (_data, _src) {
   SyncStart: function (_data, _src) {

+ 42 - 23
src/background/sync/base.js

@@ -66,8 +66,17 @@ ServiceConfig.prototype.get = function (key, def) {
   return syncConfig.get(keys, def);
   return syncConfig.get(keys, def);
 };
 };
 ServiceConfig.prototype.set = function (key, val) {
 ServiceConfig.prototype.set = function (key, val) {
-  var keys = this.normalizeKeys(key);
-  return syncConfig.set(keys, val);
+  var _this = this;
+  if (typeof key === 'object') {
+    var data = key;
+    Object.keys(data).forEach(function (key) {
+      var keys = _this.normalizeKeys(key);
+      syncConfig.set(keys, data[key]);
+    });
+  } else {
+    var keys = _this.normalizeKeys(key);
+    syncConfig.set(keys, val);
+  }
 };
 };
 ServiceConfig.prototype.clear = function () {
 ServiceConfig.prototype.clear = function () {
   syncConfig.set(this.normalizeKeys(), {});
   syncConfig.set(this.normalizeKeys(), {});
@@ -145,14 +154,14 @@ var BaseService = serviceFactory({
       'authorized',
       'authorized',
       'unauthorized',
       'unauthorized',
       'error',
       'error',
-    ], null, _this.onStateChange),
-      _this.syncState = serviceState([
-        'idle',
-        'ready',
-        'syncing',
-        'error',
-      ], null, _this.onStateChange),
-      _this.initHeaders();
+    ], null, _this.onStateChange);
+    _this.syncState = serviceState([
+      'idle',
+      'ready',
+      'syncing',
+      'error',
+    ], null, _this.onStateChange);
+    // _this.initToken();
     _this.events = events.getEventEmitter();
     _this.events = events.getEventEmitter();
     _this.lastFetch = Promise.resolve();
     _this.lastFetch = Promise.resolve();
     _this.startSync = _this.syncFactory();
     _this.startSync = _this.syncFactory();
@@ -207,12 +216,13 @@ var BaseService = serviceFactory({
       return promise;
       return promise;
     };
     };
   },
   },
+  prepareHeaders: function () {
+    this.headers = {};
+  },
   prepare: function () {
   prepare: function () {
     var _this = this;
     var _this = this;
     _this.authState.set('initializing');
     _this.authState.set('initializing');
-    var token = _this.token = _this.config.get('token');
-    _this.initHeaders();
-    return (token ? Promise.resolve(_this.user()) : Promise.reject({
+    return (_this.initToken() ? Promise.resolve(_this.user()) : Promise.reject({
       type: 'unauthorized',
       type: 'unauthorized',
     }))
     }))
     .then(function () {
     .then(function () {
@@ -244,10 +254,14 @@ var BaseService = serviceFactory({
       return JSON.parse(data);
       return JSON.parse(data);
     });
     });
   },
   },
-  initHeaders: function () {
-    var headers = this.headers = {};
-    var token = this.token;
-    if (token) headers.Authorization = 'Bearer ' + token;
+  initToken: function () {
+    var _this = this;
+    _this.prepareHeaders();
+    var token = _this.config.get('token');
+    if (token) {
+      _this.headers.Authorization = 'Bearer ' + token;
+      return true;
+    }
   },
   },
   request: function (options) {
   request: function (options) {
     var _this = this;
     var _this = this;
@@ -496,16 +510,20 @@ function sync() {
   return service && syncOne(service).then(autoSync);
   return service && syncOne(service).then(autoSync);
 }
 }
 
 
-function checkAuthenticateUrl(url) {
+function checkAuthUrl(url) {
   return serviceNames.some(function (name) {
   return serviceNames.some(function (name) {
     var service = services[name];
     var service = services[name];
-    return service.checkAuthenticate && service.checkAuthenticate(url);
+    return service.checkAuth && service.checkAuth(url);
   });
   });
 }
 }
 
 
-function authenticate() {
+function authorize() {
+  var service = getService();
+  service && service.authorize();
+}
+function revoke() {
   var service = getService();
   var service = getService();
-  service && service.authenticate && service.authenticate();
+  service && service.revoke();
 }
 }
 
 
 options.hook(function (data) {
 options.hook(function (data) {
@@ -520,8 +538,9 @@ exports.utils = {
 exports.initialize = initialize;
 exports.initialize = initialize;
 exports.sync = sync;
 exports.sync = sync;
 exports.getStates = getStates;
 exports.getStates = getStates;
-exports.checkAuthenticateUrl = checkAuthenticateUrl;
+exports.checkAuthUrl = checkAuthUrl;
 exports.BaseService = BaseService;
 exports.BaseService = BaseService;
 exports.register = register;
 exports.register = register;
 exports.service = getService;
 exports.service = getService;
-exports.authenticate = authenticate;
+exports.authorize = authorize;
+exports.revoke = revoke;

+ 14 - 4
src/background/sync/dropbox.js

@@ -6,7 +6,7 @@ var config = {
   redirect_uri: 'https://violentmonkey.github.io/auth_dropbox.html',
   redirect_uri: 'https://violentmonkey.github.io/auth_dropbox.html',
 };
 };
 
 
-function authenticate() {
+function authorize() {
   var params = {
   var params = {
     response_type: 'token',
     response_type: 'token',
     client_id: config.client_id,
     client_id: config.client_id,
@@ -17,7 +17,7 @@ function authenticate() {
   url += '?' + qs;
   url += '?' + qs;
   tabsUtils.create(url);
   tabsUtils.create(url);
 }
 }
-function checkAuthenticate(url) {
+function checkAuth(url) {
   var redirect_uri = config.redirect_uri + '#';
   var redirect_uri = config.redirect_uri + '#';
   if (url.startsWith(redirect_uri)) {
   if (url.startsWith(redirect_uri)) {
     authorized(url.slice(redirect_uri.length));
     authorized(url.slice(redirect_uri.length));
@@ -34,6 +34,12 @@ function authorized(raw) {
     });
     });
   }
   }
 }
 }
+function revoke() {
+  dropbox.config.set({
+    uid: null,
+    token: null,
+  });
+}
 function normalize(item) {
 function normalize(item) {
   return {
   return {
     size: item.size,
     size: item.size,
@@ -124,7 +130,11 @@ var Dropbox = base.BaseService.extend({
     })
     })
     .then(normalize);
     .then(normalize);
   },
   },
-  authenticate: authenticate,
-  checkAuthenticate: checkAuthenticate,
+  authorize: authorize,
+  checkAuth: checkAuth,
+  revoke: function () {
+    revoke();
+    return this.prepare();
+  },
 });
 });
 var dropbox = base.register(Dropbox);
 var dropbox = base.register(Dropbox);

+ 3 - 2
src/background/sync/index.js

@@ -2,7 +2,7 @@ var tabs = require('../utils/tabs');
 var base = require('./base');
 var base = require('./base');
 
 
 tabs.update(function (tab) {
 tabs.update(function (tab) {
-  tab.url && base.checkAuthenticateUrl(tab.url) && tabs.remove(tab.id);
+  tab.url && base.checkAuthUrl(tab.url) && tabs.remove(tab.id);
 });
 });
 
 
 // import sync modules
 // import sync modules
@@ -14,5 +14,6 @@ module.exports = {
   sync: base.sync,
   sync: base.sync,
   states: base.getStates,
   states: base.getStates,
   service: base.getService,
   service: base.getService,
-  authenticate: base.authenticate,
+  authorize: base.authorize,
+  revoke: base.revoke,
 };
 };

+ 26 - 14
src/background/sync/onedrive.js

@@ -13,7 +13,7 @@ var config = Object.assign({
   window.atob('eyJjbGllbnRfc2VjcmV0Ijoiajl4M09WRXRIdmhpSEtEV09HcXV5TWZaS2s5NjA0MEgifQ==')
   window.atob('eyJjbGllbnRfc2VjcmV0Ijoiajl4M09WRXRIdmhpSEtEV09HcXV5TWZaS2s5NjA0MEgifQ==')
 ));
 ));
 
 
-function authenticate() {
+function authorize() {
   var params = {
   var params = {
     client_id: config.client_id,
     client_id: config.client_id,
     scope: 'onedrive.appfolder wl.offline_access',
     scope: 'onedrive.appfolder wl.offline_access',
@@ -25,7 +25,7 @@ function authenticate() {
   url += '?' + qs;
   url += '?' + qs;
   tabsUtils.create(url);
   tabsUtils.create(url);
 }
 }
-function checkAuthenticate(url) {
+function checkAuth(url) {
   var redirect_uri = config.redirect_uri + '?code=';
   var redirect_uri = config.redirect_uri + '?code=';
   if (url.startsWith(redirect_uri)) {
   if (url.startsWith(redirect_uri)) {
     onedrive.authState.set('authorizing');
     onedrive.authState.set('authorizing');
@@ -52,7 +52,8 @@ function authorized(params) {
       grant_type: 'authorization_code',
       grant_type: 'authorization_code',
     }, params)),
     }, params)),
     responseType: 'json',
     responseType: 'json',
-  }).then(function (data) {
+  })
+  .then(function (data) {
     if (data.access_token) {
     if (data.access_token) {
       onedrive.config.set({
       onedrive.config.set({
         uid: data.user_id,
         uid: data.user_id,
@@ -64,6 +65,13 @@ function authorized(params) {
     }
     }
   });
   });
 }
 }
+function revoke() {
+  onedrive.config.set({
+    uid: null,
+    token: null,
+    refresh_token: null,
+  });
+}
 function normalize(item) {
 function normalize(item) {
   return {
   return {
     size: item.size,
     size: item.size,
@@ -135,9 +143,9 @@ var OneDrive = base.BaseService.extend({
     var _this = this;
     var _this = this;
     return _this.request({
     return _this.request({
       url: '/drive/special/approot/children',
       url: '/drive/special/approot/children',
-    }).then(function (text) {
-      return JSON.parse(text);
-    }).then(function (data) {
+      responseType: 'json',
+    })
+    .then(function (data) {
       return data.value.filter(function (item) {
       return data.value.filter(function (item) {
         return item.file && base.utils.isScriptFile(item.name);
         return item.file && base.utils.isScriptFile(item.name);
       }).map(normalize);
       }).map(normalize);
@@ -146,9 +154,9 @@ var OneDrive = base.BaseService.extend({
   get: function (path) {
   get: function (path) {
     return this.request({
     return this.request({
       url: '/drive/special/approot:/' + encodeURIComponent(path),
       url: '/drive/special/approot:/' + encodeURIComponent(path),
-    }).then(function (text) {
-      return JSON.parse(text);
-    }).then(function (data) {
+      responseType: 'json',
+    })
+    .then(function (data) {
       var url = data['@content.downloadUrl'];
       var url = data['@content.downloadUrl'];
       return new Promise(function (resolve, reject) {
       return new Promise(function (resolve, reject) {
         var xhr = new XMLHttpRequest;
         var xhr = new XMLHttpRequest;
@@ -174,9 +182,9 @@ var OneDrive = base.BaseService.extend({
         'Content-Type': 'application/octet-stream',
         'Content-Type': 'application/octet-stream',
       },
       },
       body: data,
       body: data,
-    }).then(function (text) {
-      return JSON.parse(text);
-    }).then(normalize);
+      responseType: 'json',
+    })
+    .then(normalize);
   },
   },
   remove: function (path) {
   remove: function (path) {
     // return 204
     // return 204
@@ -185,7 +193,11 @@ var OneDrive = base.BaseService.extend({
       url: '/drive/special/approot:/' + encodeURIComponent(path),
       url: '/drive/special/approot:/' + encodeURIComponent(path),
     }).catch(_.noop);
     }).catch(_.noop);
   },
   },
-  authenticate: authenticate,
-  checkAuthenticate: checkAuthenticate,
+  authorize: authorize,
+  checkAuth: checkAuth,
+  revoke: function () {
+    revoke();
+    return this.prepare();
+  },
 });
 });
 var onedrive = base.register(OneDrive);
 var onedrive = base.register(OneDrive);

+ 2 - 1
src/options/views/tab-settings/vm-sync/index.html

@@ -7,7 +7,8 @@
     <select :value="syncConfig.current" @change="onSyncChange">
     <select :value="syncConfig.current" @change="onSyncChange">
       <option v-for="service in syncServices" v-text="service.displayName" :value="service.name"></option>
       <option v-for="service in syncServices" v-text="service.displayName" :value="service.name"></option>
     </select>
     </select>
-    <button v-text="labelAuthorize" :disabled="!canAuthorize" v-if="service.name"></button>
+    <button v-text="labelAuthorize" v-if="service.name"
+    :disabled="!canAuthorize" @click="onAuthorize"></button>
     <button :disabled="!canSync" v-if="service.name">
     <button :disabled="!canSync" v-if="service.name">
       <svg class="icon"><use xlink:href="#refresh" /></svg>
       <svg class="icon"><use xlink:href="#refresh" /></svg>
     </button>
     </button>

+ 10 - 0
src/options/views/tab-settings/vm-sync/index.js

@@ -104,5 +104,15 @@ module.exports = {
       var value = e.target.value;
       var value = e.target.value;
       _.options.set(SYNC_CURRENT, value);
       _.options.set(SYNC_CURRENT, value);
     },
     },
+    onAuthorize: function () {
+      var service = this.service;
+      if (~['authorized'].indexOf(service.authState)) {
+        // revoke
+        _.sendMessage({cmd: 'SyncRevoke', data: service.name});
+      } else if (~['unauthorized', 'error'].indexOf(service.authState)) {
+        // authorize
+        _.sendMessage({cmd: 'SyncAuthorize', data: service.name});
+      }
+    },
   },
   },
 };
 };