auth/data: avoid setting global errors when receiving a 401

If we do a router.push to the login view the previous component will receive
anyway the error and set the global error after the login view is mounted (!!!)
and so the main app will show the global error instead of the login view.

Not sure how to avoid this. As a really ugly workaround just return an empty
response on 401 so the components (since they are currently assumong the
response is always define) will throw an exception and not set the global error.
This commit is contained in:
Simone Gotti 2019-07-05 13:41:43 +02:00
parent fbed07059e
commit 43e860d3c5
4 changed files with 27 additions and 9 deletions

View File

@ -1,4 +1,3 @@
import router from "@/router";
import store from "@/store"; import store from "@/store";
const ID_TOKEN_KEY = 'id_token'; const ID_TOKEN_KEY = 'id_token';
@ -54,8 +53,7 @@ export async function loginapi(init) {
} }
try { try {
let res = await window.fetch(loginurl(), init) return await window.fetch(loginurl(), init)
return res
} catch (e) { } catch (e) {
throw e throw e
} }
@ -67,8 +65,7 @@ export async function registerapi(init) {
} }
try { try {
let res = await window.fetch(registerurl(), init) return await window.fetch(registerurl(), init)
return res
} catch (e) { } catch (e) {
throw e throw e
} }
@ -87,10 +84,7 @@ export async function fetch(url, init) {
} }
try { try {
let res = await window.fetch(url, init) return await window.fetch(url, init)
if (res.status === 401) {
router.push({ name: "login" })
} else { return res }
} catch (e) { } catch (e) {
throw e throw e
} }

View File

@ -1,10 +1,27 @@
import { apiurl, loginapi, registerapi } from "@/util/auth"; import { apiurl, loginapi, registerapi } from "@/util/auth";
import { fetch as authfetch } from "@/util/auth"; import { fetch as authfetch } from "@/util/auth";
import router from "@/router";
export async function fetch(url, init) { export async function fetch(url, init) {
try { try {
let res = await authfetch(url, init) let res = await authfetch(url, init)
if (!res.ok) { if (!res.ok) {
if (res.status === 401) {
router.push({ name: "login" })
// if we return a response containing an error what happens is
// that router.push mounts the login view before the calling
// component processed the response and the calling component
// may set the "unauthorized" error as a global error hiding the
// login view.
// So return an empty response so the caller won't set a global
// error (but in the console will appear other errors since also
// data is null)
// TODO(sgotti) find a way to make this cleaner. The solution
// could be to find a way to firstly let the component handle
// the error and the do the router push...
return
}
let data = await res.json() let data = await res.json()
return { data: null, error: data.message } return { data: null, error: data.message }
} else { } else {
@ -86,6 +103,7 @@ export async function fetchRuns(group, startRunID, lastrun) {
if (startRunID) { if (startRunID) {
u.searchParams.append("start", startRunID) u.searchParams.append("start", startRunID)
} }
return await fetch(u) return await fetch(u)
} }

View File

@ -77,6 +77,9 @@ export default {
this.$router.push({ name: "home" }); this.$router.push({ name: "home" });
} }
}, },
mounted: function() {
this.$store.dispatch("setError", null);
},
created: function() { created: function() {
doLogout(); doLogout();
this.fetchRemoteSources(); this.fetchRemoteSources();

View File

@ -125,6 +125,9 @@ export default {
this.$router.push({ name: "home" }); this.$router.push({ name: "home" });
} }
}, },
mounted: function() {
this.$store.dispatch("setError", null);
},
created: function() { created: function() {
doLogout(); doLogout();
this.fetchRemoteSources(); this.fetchRemoteSources();