diff --git a/assets/js/api.js b/assets/js/api.js index 9ba3b5b46..45859733f 100644 --- a/assets/js/api.js +++ b/assets/js/api.js @@ -1,4 +1,5 @@ import axios from "axios"; +import { openLoginModal } from "./auth"; const { protocol, hostname, port, pathname } = window.location; @@ -15,13 +16,19 @@ const api = axios.create({ api.interceptors.response.use( (response) => response, (error) => { + // handle unauthorized errors + if (error.response?.status === 401) { + openLoginModal(); + return Promise.reject(error); + } + const message = [`${error.message}.`]; if (error.response?.data?.error) { message.push(`${error.response.data.error}.`); } if (error.config) { const method = error.config.method.toUpperCase(); - const url = error.config.baseURL + error.config.url; + const url = error.request.responseURL; message.push(`${method} ${url}`); } window.app.raise({ message }); diff --git a/assets/js/auth.js b/assets/js/auth.js new file mode 100644 index 000000000..ba85b006d --- /dev/null +++ b/assets/js/auth.js @@ -0,0 +1,58 @@ +import { reactive, watch } from "vue"; +import api from "./api"; +import Modal from "bootstrap/js/dist/modal"; + +const auth = reactive({ + configured: true, + loggedIn: false, +}); + +export async function updateAuthStatus() { + try { + const res = await api.get("/auth/status", { + validateStatus: (code) => [200, 501].includes(code), + }); + if (res.status === 501) { + auth.configured = false; + } + if (res.status === 200) { + auth.configured = true; + auth.loggedIn = res.data === true; + } + } catch (e) { + console.log("unable to fetch auth status", e); + } +} + +export async function logout() { + try { + await api.post("/auth/logout"); + await updateAuthStatus(); + } catch (e) { + console.log("unable to logout", e); + } +} + +export function isLoggedIn() { + return auth.loggedIn; +} + +export function isConfigured() { + return auth.configured; +} + +export function openLoginModal() { + const modal = Modal.getOrCreateInstance(document.getElementById("loginModal")); + modal.show(); +} + +// show/hide password modal based on auth status +watch( + () => auth.configured, + (configured) => { + const modal = Modal.getOrCreateInstance(document.getElementById("passwordModal")); + configured ? modal.hide() : modal.show(); + } +); + +export default auth; diff --git a/assets/js/components/Config/GeneralConfig.vue b/assets/js/components/Config/GeneralConfig.vue index cf9ef3bb6..ee4eba811 100644 --- a/assets/js/components/Config/GeneralConfig.vue +++ b/assets/js/components/Config/GeneralConfig.vue @@ -27,11 +27,17 @@ -
+
Password
******* - edit + + edit
diff --git a/assets/js/components/GenericModal.vue b/assets/js/components/GenericModal.vue index fbd3a0d5c..8e4c0ba0c 100644 --- a/assets/js/components/GenericModal.vue +++ b/assets/js/components/GenericModal.vue @@ -4,10 +4,12 @@ :id="id" ref="modal" class="modal fade text-dark" - data-bs-backdrop="true" + :class="sizeClass" tabindex="-1" role="dialog" aria-hidden="true" + :data-bs-backdrop="uncloseable ? 'static' : 'true'" + :data-bs-keyboard="uncloseable ? 'false' : 'true'" :data-testid="dataTestid" >