Change: refactor sync logic, disallow implicit auth

This commit is contained in:
eight04 2021-02-09 16:50:18 +08:00
parent cd0645f606
commit 0c0240e26d
2 changed files with 29 additions and 42 deletions

View File

@ -64,18 +64,18 @@ const syncMan = (() => {
}, },
async login(name = prefs.get('sync.enabled')) { async login(name = prefs.get('sync.enabled')) {
// FIXME: it doesn't really make sense to wait pref after getting the pref value
if (ready.then) await ready; if (ready.then) await ready;
await tokenMan.revokeToken(name);
try { try {
await tokenMan.getToken(name, true); await tokenMan.getToken(name, true);
status.login = true;
} catch (err) { } catch (err) {
if (/Authorization page could not be loaded/i.test(err.message)) { status.login = false;
// FIXME: Chrome always fails at the first login so we try again
await tokenMan.getToken(name);
}
throw err; throw err;
} finally {
emitStatusChange();
} }
status.login = true;
emitStatusChange();
}, },
async put(...args) { async put(...args) {
@ -91,26 +91,24 @@ const syncMan = (() => {
if (currentDrive) return; if (currentDrive) return;
currentDrive = getDrive(name); currentDrive = getDrive(name);
ctrl.use(currentDrive); ctrl.use(currentDrive);
status.state = STATES.connecting; status.state = STATES.connecting;
status.currentDriveName = currentDrive.name; status.currentDriveName = currentDrive.name;
status.login = true;
emitStatusChange(); emitStatusChange();
try {
if (!fromPref) { if (!fromPref) {
await syncMan.login(name).catch(handle401Error); try {
} await syncMan.login(name);
await syncMan.syncNow(); } catch (err) {
status.errorMessage = null;
lastError = null;
} catch (err) {
status.errorMessage = err.message;
lastError = err;
// FIXME: should we move this logic to options.js?
if (!fromPref) {
console.error(err); console.error(err);
status.errorMessage = err.message;
lastError = err;
emitStatusChange();
return syncMan.stop(); return syncMan.stop();
} }
} }
await syncMan.syncNow(name);
prefs.set('sync.enabled', name); prefs.set('sync.enabled', name);
status.state = STATES.connected; status.state = STATES.connected;
schedule(SYNC_INTERVAL); schedule(SYNC_INTERVAL);
@ -124,7 +122,7 @@ const syncMan = (() => {
status.state = STATES.disconnecting; status.state = STATES.disconnecting;
emitStatusChange(); emitStatusChange();
try { try {
await ctrl.stop(); await ctrl.uninit();
await tokenMan.revokeToken(currentDrive.name); await tokenMan.revokeToken(currentDrive.name);
await chromeLocal.remove(STORAGE_KEY + currentDrive.name); await chromeLocal.remove(STORAGE_KEY + currentDrive.name);
} catch (e) {} } catch (e) {}
@ -138,14 +136,19 @@ const syncMan = (() => {
async syncNow() { async syncNow() {
if (ready.then) await ready; if (ready.then) await ready;
if (!currentDrive) throw new Error('cannot sync when disconnected'); if (!currentDrive || !status.login) throw new Error('cannot sync when disconnected');
try { try {
await (ctrl.isInit() ? ctrl.syncNow() : ctrl.start()).catch(handle401Error); await ctrl.init();
await ctrl.syncNow();
status.errorMessage = null; status.errorMessage = null;
lastError = null; lastError = null;
} catch (err) { } catch (err) {
status.errorMessage = err.message; status.errorMessage = err.message;
lastError = err; lastError = err;
if (isGrantError(err)) {
status.login = false;
}
} }
emitStatusChange(); emitStatusChange();
}, },
@ -192,21 +195,6 @@ const syncMan = (() => {
}); });
} }
async function handle401Error(err) {
let authError = false;
if (err.code === 401) {
await tokenMan.revokeToken(currentDrive.name).catch(console.error);
authError = true;
} else if (/User interaction required|Requires user interaction/i.test(err.message)) {
authError = true;
}
if (authError) {
status.login = false;
emitStatusChange();
}
return Promise.reject(err);
}
function emitStatusChange() { function emitStatusChange() {
msg.broadcastExtension({method: 'syncStatusUpdate', status}); msg.broadcastExtension({method: 'syncStatusUpdate', status});

View File

@ -75,13 +75,12 @@ const tokenMan = (() => {
return obj[k.TOKEN]; return obj[k.TOKEN];
} }
if (obj[k.REFRESH]) { if (obj[k.REFRESH]) {
try { return refreshToken(name, k, obj);
return await refreshToken(name, k, obj);
} catch (err) {
if (err.code !== 401) throw err;
}
} }
} }
if (!interactive) {
throw new Error(`Invalid token: ${name}`);
}
return authUser(name, k, interactive); return authUser(name, k, interactive);
}, },