Redirect to previous url after login

This commit is contained in:
Simone Gotti 2019-09-26 10:03:44 +02:00
parent 1a582b5cff
commit 4af98fb75b
6 changed files with 332 additions and 275 deletions

View File

@ -149,14 +149,6 @@ export default {
}; };
}, },
watch: { watch: {
user: function(user) {
if (user) {
this.$router.push({
name: "user",
params: { username: this.user.username }
});
}
},
$route: function() { $route: function() {
this.userDropdownActive = false; this.userDropdownActive = false;
this.createDropdownActive = false; this.createDropdownActive = false;

View File

@ -1,26 +1,24 @@
import '@/css/tailwind.scss' import "@/css/tailwind.scss";
import { getUser } from "@/util/auth";
import "@mdi/font/css/materialdesignicons.css"; import "@mdi/font/css/materialdesignicons.css";
import Vue from "vue"; import Vue from "vue";
import Vue2Filters from "vue2-filters"; import Vue2Filters from "vue2-filters";
import App from "./App.vue"; import App from "./App.vue";
import router from "./router"; import router from "./router";
import store from "./store"; import store from "./store";
import { getUser } from "@/util/auth";
Vue.use(Vue2Filters); Vue.use(Vue2Filters);
// TODO(sgotti) use vuex for login/logout // TODO(sgotti) use vuex for login/logout
new Vue({ new Vue({
router, router,
store, store,
created: function () { created: function() {
let user = getUser() let user = getUser();
if (user) { if (user) {
store.dispatch('setUser', user) store.dispatch("setUser", user);
} }
store.dispatch("setRegisterUser", null) store.dispatch("setRegisterUser", null);
}, },
render: h => h(App) render: h => h(App)
}).$mount("#app"); }).$mount("#app");

View File

@ -2,6 +2,7 @@ import store from "@/store";
const ID_TOKEN_KEY = 'id_token'; const ID_TOKEN_KEY = 'id_token';
const USER_KEY = 'user'; const USER_KEY = 'user';
const LOGIN_REDIRECT_KEY = 'login_redirect';
let API_URL = window.CONFIG.API_URL; let API_URL = window.CONFIG.API_URL;
let API_BASE_PATH = window.CONFIG.API_BASE_PATH; let API_BASE_PATH = window.CONFIG.API_BASE_PATH;
@ -125,3 +126,15 @@ export function isLoggedIn() {
const idToken = getIdToken(); const idToken = getIdToken();
return !!idToken; return !!idToken;
} }
export function getLoginRedirect() {
return sessionStorage.getItem(LOGIN_REDIRECT_KEY);
}
export function setLoginRedirect(url) {
sessionStorage.setItem(LOGIN_REDIRECT_KEY, url);
}
export function unsetLoginRedirect() {
return sessionStorage.removeItem(LOGIN_REDIRECT_KEY);
}

View File

@ -2,361 +2,388 @@ import router from "@/router";
import { apiurl, fetch as authfetch, loginapi, registerapi } from "@/util/auth"; import { apiurl, fetch as authfetch, loginapi, registerapi } from "@/util/auth";
export async function fetch(url, init, signal) { export async function fetch(url, init, signal) {
try { try {
let res = await authfetch(url, init, signal) let res = await authfetch(url, init, signal);
if (!res.ok) { if (!res.ok) {
if (res.status === 401) { if (res.status === 401) {
router.push({ name: "login" }) router.push({
// if we return a response containing an error what happens is name: "login",
// that router.push mounts the login view before the calling query: { redirect: router.currentRoute.fullPath }
// component processed the response and the calling component });
// may set the "unauthorized" error as a global error hiding the // if we return a response containing an error what happens is
// login view. // that router.push mounts the login view before the calling
// So return an empty response so the caller won't set a global // component processed the response and the calling component
// error (but in the console will appear other errors since also // may set the "unauthorized" error as a global error hiding the
// data is null) // 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 // TODO(sgotti) find a way to make this cleaner. The solution
// could be to find a way to firstly let the component handle // could be to find a way to firstly let the component handle
// the error and the do the router push... // the error and the do the router push...
return 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 {
if (res.status == 204) { if (res.status == 204) {
return { data: null, error: null } return { data: null, error: null };
} }
return { data: await res.json(), error: null } return { data: await res.json(), error: null };
}
} catch (e) {
if (e.name == 'AbortError') {
return { data: null, error: null, aborted: true, }
}
return { data: null, error: "api call failed: " + e.message }
} }
} catch (e) {
if (e.name == "AbortError") {
return { data: null, error: null, aborted: true };
}
return { data: null, error: "api call failed: " + e.message };
}
} }
export async function login(username, password, remotesourcename) { export async function login(username, password, remotesourcename) {
let init = { let init = {
method: "POST", method: "POST",
body: JSON.stringify({ body: JSON.stringify({
remote_source_name: remotesourcename, remote_source_name: remotesourcename,
login_name: username, login_name: username,
password: password password: password
}) })
} };
try { try {
let res = await loginapi(init) let res = await loginapi(init);
if (!res.ok) { if (!res.ok) {
let data = await res.json() let data = await res.json();
return { data: null, error: data.message } return { data: null, error: data.message };
} else { } else {
return { data: await res.json(), error: null } return { data: await res.json(), error: null };
}
} catch (e) {
return { data: null, error: "api call failed: " + e.message }
} }
} catch (e) {
return { data: null, error: "api call failed: " + e.message };
}
} }
export async function register(username, remotesourcename, remoteloginname, remotepassword) { export async function register(
let init = { username,
method: "POST", remotesourcename,
body: JSON.stringify({ remoteloginname,
username: username, remotepassword
remote_source_name: remotesourcename, ) {
remote_source_login_name: remoteloginname, let init = {
remote_source_login_password: remotepassword method: "POST",
}) body: JSON.stringify({
} username: username,
remote_source_name: remotesourcename,
remote_source_login_name: remoteloginname,
remote_source_login_password: remotepassword
})
};
try { try {
let res = await registerapi(init) let res = await registerapi(init);
if (!res.ok) { if (!res.ok) {
let data = await res.json() let data = await res.json();
return { data: null, error: data.message } return { data: null, error: data.message };
} else { } else {
return { data: await res.json(), error: null } return { data: await res.json(), error: null };
}
} catch (e) {
return { data: null, error: "api call failed: " + e.message }
} }
} catch (e) {
return { data: null, error: "api call failed: " + e.message };
}
} }
export async function fetchCurrentUser(signal) { export async function fetchCurrentUser(signal) {
let path = "/user" let path = "/user";
return await fetch(apiurl(path), null, signal); return await fetch(apiurl(path), null, signal);
} }
export async function fetchOrgMembers(orgref, signal) { export async function fetchOrgMembers(orgref, signal) {
let path = "/orgs/" + orgref + "/members" let path = "/orgs/" + orgref + "/members";
return await fetch(apiurl(path), null, signal); return await fetch(apiurl(path), null, signal);
} }
export async function fetchRuns(group, startRunID, lastrun, signal) { export async function fetchRuns(group, startRunID, lastrun, signal) {
let u = apiurl("/runs"); let u = apiurl("/runs");
if (group) { if (group) {
u.searchParams.append("group", group) u.searchParams.append("group", group);
} }
if (lastrun) { if (lastrun) {
u.searchParams.append("lastrun", true) u.searchParams.append("lastrun", true);
} }
if (startRunID) { if (startRunID) {
u.searchParams.append("start", startRunID) u.searchParams.append("start", startRunID);
} }
return await fetch(u, null, signal) return await fetch(u, null, signal);
} }
export async function fetchRun(runid, signal) { export async function fetchRun(runid, signal) {
return await fetch(apiurl("/runs/" + runid), null, signal); return await fetch(apiurl("/runs/" + runid), null, signal);
} }
export async function fetchTask(runid, taskid, signal) { export async function fetchTask(runid, taskid, signal) {
return await fetch(apiurl("/runs/" + runid + "/tasks/" + taskid), signal) return await fetch(apiurl("/runs/" + runid + "/tasks/" + taskid), signal);
} }
export async function fetchUser(username, signal) { export async function fetchUser(username, signal) {
let path = "/users/" + username let path = "/users/" + username;
return await fetch(apiurl(path), null, signal); return await fetch(apiurl(path), null, signal);
} }
export async function fetchProjectGroup(projectgroupref, signal) { export async function fetchProjectGroup(projectgroupref, signal) {
let path = "/projectgroups/" + encodeURIComponent(projectgroupref) let path = "/projectgroups/" + encodeURIComponent(projectgroupref);
return await fetch(apiurl(path), null, signal); return await fetch(apiurl(path), null, signal);
} }
export async function fetchProjectGroupSubgroups(projectgroupref, signal) { export async function fetchProjectGroupSubgroups(projectgroupref, signal) {
let path = "/projectgroups/" + encodeURIComponent(projectgroupref) let path = "/projectgroups/" + encodeURIComponent(projectgroupref);
path += "/subgroups"; path += "/subgroups";
return await fetch(apiurl(path), null, signal); return await fetch(apiurl(path), null, signal);
} }
export async function fetchProjectGroupProjects(projectgroupref, signal) { export async function fetchProjectGroupProjects(projectgroupref, signal) {
let path = "/projectgroups/" + encodeURIComponent(projectgroupref) let path = "/projectgroups/" + encodeURIComponent(projectgroupref);
path += "/projects"; path += "/projects";
return await fetch(apiurl(path), null, signal); return await fetch(apiurl(path), null, signal);
} }
export async function fetchProject(ref, signal) { export async function fetchProject(ref, signal) {
let path = "/projects/" + encodeURIComponent(ref) let path = "/projects/" + encodeURIComponent(ref);
return await fetch(apiurl(path), null, signal); return await fetch(apiurl(path), null, signal);
} }
export async function fetchSecrets(ownertype, ref, all, signal) { export async function fetchSecrets(ownertype, ref, all, signal) {
let path let path;
if (ownertype == "project") { if (ownertype == "project") {
path = "/projects/" path = "/projects/";
} else if (ownertype == "projectgroup") { } else if (ownertype == "projectgroup") {
path = "/projectgroups/" path = "/projectgroups/";
} }
path += encodeURIComponent(ref); path += encodeURIComponent(ref);
path += "/secrets"; path += "/secrets";
if (all) { if (all) {
path += "?tree&removeoverridden"; path += "?tree&removeoverridden";
} }
return await fetch(apiurl(path), null, signal); return await fetch(apiurl(path), null, signal);
} }
export async function fetchVariables(ownertype, ref, all, signal) { export async function fetchVariables(ownertype, ref, all, signal) {
let path let path;
if (ownertype == "project") { if (ownertype == "project") {
path = "/projects/" path = "/projects/";
} else if (ownertype == "projectgroup") { } else if (ownertype == "projectgroup") {
path = "/projectgroups/" path = "/projectgroups/";
} }
path += encodeURIComponent(ref); path += encodeURIComponent(ref);
path += "/variables"; path += "/variables";
if (all) { if (all) {
path += "?tree&removeoverridden"; path += "?tree&removeoverridden";
} }
return await fetch(apiurl(path), null, signal); return await fetch(apiurl(path), null, signal);
} }
export async function createOrganization(orgname, visibility, signal) { export async function createOrganization(orgname, visibility, signal) {
let path = "/orgs" let path = "/orgs";
let init = { let init = {
method: "POST", method: "POST",
body: JSON.stringify({ body: JSON.stringify({
name: orgname, name: orgname,
visibility: visibility, visibility: visibility
}) })
} };
return await fetch(apiurl(path), init, signal) return await fetch(apiurl(path), init, signal);
} }
export async function createUserToken(username, tokenname, signal) { export async function createUserToken(username, tokenname, signal) {
let path = "/users/" + username + "/tokens" let path = "/users/" + username + "/tokens";
let init = { let init = {
method: "POST", method: "POST",
body: JSON.stringify({ body: JSON.stringify({
token_name: tokenname, token_name: tokenname
}) })
} };
return await fetch(apiurl(path), init, signal) return await fetch(apiurl(path), init, signal);
} }
export async function deleteUserToken(username, tokenname, signal) { export async function deleteUserToken(username, tokenname, signal) {
let path = "/users/" + username + "/tokens/" + tokenname let path = "/users/" + username + "/tokens/" + tokenname;
let init = { let init = {
method: "DELETE", method: "DELETE"
} };
return await fetch(apiurl(path), init, signal) return await fetch(apiurl(path), init, signal);
} }
export async function createUserLinkedAccount(username, remotesourcename, loginname, password, signal) { export async function createUserLinkedAccount(
let path = "/users/" + username + "/linkedaccounts" username,
let init = { remotesourcename,
method: "POST", loginname,
body: JSON.stringify({ password,
remote_source_name: remotesourcename, signal
remote_source_login_name: loginname, ) {
remote_source_login_password: password, let path = "/users/" + username + "/linkedaccounts";
}) let init = {
} method: "POST",
return await fetch(apiurl(path), init, signal) body: JSON.stringify({
remote_source_name: remotesourcename,
remote_source_login_name: loginname,
remote_source_login_password: password
})
};
return await fetch(apiurl(path), init, signal);
} }
export async function deleteLinkedAccount(username, laid, signal) { export async function deleteLinkedAccount(username, laid, signal) {
let path = "/users/" + username + "/linkedaccounts/" + laid let path = "/users/" + username + "/linkedaccounts/" + laid;
let init = { let init = {
method: "DELETE", method: "DELETE"
} };
return await fetch(apiurl(path), init, signal) return await fetch(apiurl(path), init, signal);
} }
export async function restartRun(runid, fromStart, signal) { export async function restartRun(runid, fromStart, signal) {
let path = "/runs/" + runid + "/actions" let path = "/runs/" + runid + "/actions";
let init = { let init = {
method: "PUT", method: "PUT",
body: JSON.stringify({ body: JSON.stringify({
action_type: "restart", action_type: "restart",
from_start: fromStart from_start: fromStart
}) })
} };
return await fetch(apiurl(path), init, signal) return await fetch(apiurl(path), init, signal);
} }
export async function cancelRun(runid, signal) { export async function cancelRun(runid, signal) {
let path = "/runs/" + runid + "/actions" let path = "/runs/" + runid + "/actions";
let init = { let init = {
method: "PUT", method: "PUT",
body: JSON.stringify({ body: JSON.stringify({
action_type: "cancel" action_type: "cancel"
}) })
} };
return await fetch(apiurl(path), init, signal) return await fetch(apiurl(path), init, signal);
} }
export async function stopRun(runid, signal) { export async function stopRun(runid, signal) {
let path = "/runs/" + runid + "/actions" let path = "/runs/" + runid + "/actions";
let init = { let init = {
method: "PUT", method: "PUT",
body: JSON.stringify({ body: JSON.stringify({
action_type: "stop" action_type: "stop"
}) })
} };
return await fetch(apiurl(path), init, signal) return await fetch(apiurl(path), init, signal);
} }
export async function approveTask(runid, taskid, signal) { export async function approveTask(runid, taskid, signal) {
let path = "/runs/" + runid + "/tasks/" + taskid + "/actions" let path = "/runs/" + runid + "/tasks/" + taskid + "/actions";
let init = { let init = {
method: "PUT", method: "PUT",
body: JSON.stringify({ body: JSON.stringify({
action_type: "approve" action_type: "approve"
}) })
} };
return await fetch(apiurl(path), init, signal) return await fetch(apiurl(path), init, signal);
} }
export async function fetchRemoteSources(signal) { export async function fetchRemoteSources(signal) {
let path = "/remotesources" let path = "/remotesources";
return await fetch(apiurl(path), null, signal); return await fetch(apiurl(path), null, signal);
} }
export async function userRemoteRepos(remotesourceid, signal) { export async function userRemoteRepos(remotesourceid, signal) {
let path = "/user/remoterepos/" + remotesourceid let path = "/user/remoterepos/" + remotesourceid;
return await fetch(apiurl(path, null, signal)); return await fetch(apiurl(path, null, signal));
} }
export async function createProjectGroup(parentref, name, visibility, signal) { export async function createProjectGroup(parentref, name, visibility, signal) {
let path = "/projectgroups" let path = "/projectgroups";
let init = { let init = {
method: "POST", method: "POST",
body: JSON.stringify({ body: JSON.stringify({
name: name, name: name,
parent_ref: parentref, parent_ref: parentref,
visibility: visibility visibility: visibility
}) })
} };
return await fetch(apiurl(path), init, signal) return await fetch(apiurl(path), init, signal);
} }
export async function updateProjectGroup(projectgroupref, name, visibility, signal) { export async function updateProjectGroup(
let path = "/projectgroups/" + encodeURIComponent(projectgroupref) projectgroupref,
let init = { name,
method: "PUT", visibility,
body: JSON.stringify({ signal
name: name, ) {
visibility: visibility, let path = "/projectgroups/" + encodeURIComponent(projectgroupref);
}) let init = {
} method: "PUT",
return await fetch(apiurl(path), init, signal) body: JSON.stringify({
name: name,
visibility: visibility
})
};
return await fetch(apiurl(path), init, signal);
} }
export async function createProject(parentref, name, visibility, remotesourcename, remoterepopath, signal) { export async function createProject(
let path = "/projects" parentref,
let init = { name,
method: "POST", visibility,
body: JSON.stringify({ remotesourcename,
name: name, remoterepopath,
parent_ref: parentref, signal
visibility: visibility, ) {
remote_source_name: remotesourcename, let path = "/projects";
repo_path: remoterepopath, let init = {
}) method: "POST",
} body: JSON.stringify({
return await fetch(apiurl(path), init, signal) name: name,
parent_ref: parentref,
visibility: visibility,
remote_source_name: remotesourcename,
repo_path: remoterepopath
})
};
return await fetch(apiurl(path), init, signal);
} }
export async function updateProject(projectref, name, visibility, signal) { export async function updateProject(projectref, name, visibility, signal) {
let path = "/projects/" + encodeURIComponent(projectref) let path = "/projects/" + encodeURIComponent(projectref);
let init = { let init = {
method: "PUT", method: "PUT",
body: JSON.stringify({ body: JSON.stringify({
name: name, name: name,
visibility: visibility, visibility: visibility
}) })
} };
return await fetch(apiurl(path), init, signal) return await fetch(apiurl(path), init, signal);
} }
export async function deleteProject(projectref, signal) { export async function deleteProject(projectref, signal) {
let path = "/projects/" + encodeURIComponent(projectref) let path = "/projects/" + encodeURIComponent(projectref);
let init = { let init = {
method: "DELETE", method: "DELETE"
} };
return await fetch(apiurl(path), init, signal) return await fetch(apiurl(path), init, signal);
} }
export async function projectUpdateRepoLinkedAccount(projectref, signal) { export async function projectUpdateRepoLinkedAccount(projectref, signal) {
let path = "/projects/" + encodeURIComponent(projectref) + "/updaterepolinkedaccount" let path =
let init = { "/projects/" + encodeURIComponent(projectref) + "/updaterepolinkedaccount";
method: "PUT", let init = {
} method: "PUT"
return await fetch(apiurl(path), init, signal) };
return await fetch(apiurl(path), init, signal);
} }
export async function deleteProjectGroup(projectgroupref, signal) { export async function deleteProjectGroup(projectgroupref, signal) {
let path = "/projectgroups/" + encodeURIComponent(projectgroupref) let path = "/projectgroups/" + encodeURIComponent(projectgroupref);
let init = { let init = {
method: "DELETE", method: "DELETE"
} };
return await fetch(apiurl(path), init, signal) return await fetch(apiurl(path), init, signal);
} }

View File

@ -38,7 +38,12 @@
<script> <script>
import { fetchRemoteSources, login } from "@/util/data"; import { fetchRemoteSources, login } from "@/util/data";
import { setLoggedUser, doLogout } from "@/util/auth"; import {
setLoggedUser,
unsetLoginRedirect,
setLoginRedirect,
doLogout
} from "@/util/auth";
import LoginForm from "@/components/loginform"; import LoginForm from "@/components/loginform";
@ -63,6 +68,9 @@ export default {
this.remotesources = data; this.remotesources = data;
}, },
async doLogin(username, password, remotesourcename) { async doLogin(username, password, remotesourcename) {
unsetLoginRedirect();
let redirect = this.$route.query["redirect"];
this.error = null; this.error = null;
let { data, error } = await login(username, password, remotesourcename); let { data, error } = await login(username, password, remotesourcename);
@ -72,11 +80,19 @@ export default {
return; return;
} }
if (data.oauth2_redirect) { if (data.oauth2_redirect) {
if (redirect) {
setLoginRedirect(redirect);
}
window.location = data.oauth2_redirect; window.location = data.oauth2_redirect;
return; return;
} }
setLoggedUser(data.token, data.user); setLoggedUser(data.token, data.user);
this.$router.push({ name: "home" }); if (redirect) {
unsetLoginRedirect();
this.$router.push(redirect);
} else {
this.$router.push({ name: "home" });
}
} }
}, },
mounted: function() { mounted: function() {

View File

@ -13,7 +13,12 @@
<script> <script>
import { fetch } from "@/util/data"; import { fetch } from "@/util/data";
import { oauth2callbackurl, setLoggedUser } from "@/util/auth"; import {
oauth2callbackurl,
setLoggedUser,
unsetLoginRedirect,
getLoginRedirect
} from "@/util/auth";
export default { export default {
components: {}, components: {},
@ -41,7 +46,13 @@ export default {
if (data.request_type === "loginuser") { if (data.request_type === "loginuser") {
setLoggedUser(data.response.token, data.response.user); setLoggedUser(data.response.token, data.response.user);
this.$router.push("/"); let redirect = getLoginRedirect(redirect);
if (redirect) {
unsetLoginRedirect();
this.$router.push(redirect);
} else {
this.$router.push({ name: "home" });
}
} else if (data.request_type === "authorize") { } else if (data.request_type === "authorize") {
this.$store.dispatch("setRegisterUser", data.response); this.$store.dispatch("setRegisterUser", data.response);
this.$router.push("/register"); this.$router.push("/register");