chore: Typescript Auth (#20470)
This commit is contained in:
parent
1e1e7947b1
commit
2cabe49239
9 changed files with 133 additions and 123 deletions
|
|
@ -1,5 +1,5 @@
|
|||
import axios from "axios";
|
||||
import { openLoginModal } from "./components/Auth/auth.js";
|
||||
import { openLoginModal } from "./components/Auth/auth";
|
||||
|
||||
const { protocol, hostname, port, pathname } = window.location;
|
||||
|
||||
|
|
|
|||
|
|
@ -57,14 +57,15 @@
|
|||
</GenericModal>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
<script lang="ts">
|
||||
import GenericModal from "../Helper/GenericModal.vue";
|
||||
import Modal from "bootstrap/js/dist/modal";
|
||||
import api from "../../api.js";
|
||||
import { updateAuthStatus, getAndClearNextUrl, getAndClearNextModal, isLoggedIn } from "./auth.js";
|
||||
import { updateAuthStatus, getAndClearNextUrl, getAndClearNextModal, isLoggedIn } from "./auth";
|
||||
import { docsPrefix } from "../../i18n.js";
|
||||
import { defineComponent } from "vue";
|
||||
|
||||
export default {
|
||||
export default defineComponent({
|
||||
name: "LoginModal",
|
||||
components: { GenericModal },
|
||||
data: () => {
|
||||
|
|
@ -98,11 +99,11 @@ export default {
|
|||
this.iframeHint = false;
|
||||
},
|
||||
focus() {
|
||||
console.log(this.$refs.password);
|
||||
this.$refs.password.focus();
|
||||
console.log(this.$refs["password"]);
|
||||
this.$refs["password"]?.focus();
|
||||
},
|
||||
closeModal() {
|
||||
Modal.getOrCreateInstance(document.getElementById("loginModal")).hide();
|
||||
Modal.getOrCreateInstance(document.getElementById("loginModal") as HTMLElement).hide();
|
||||
},
|
||||
async login() {
|
||||
this.loading = true;
|
||||
|
|
@ -136,13 +137,15 @@ export default {
|
|||
}
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
this.error = err.message;
|
||||
if (err instanceof Error) {
|
||||
this.error = err.message;
|
||||
}
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
});
|
||||
</script>
|
||||
<style scoped>
|
||||
form {
|
||||
|
|
|
|||
|
|
@ -85,13 +85,14 @@
|
|||
</GenericModal>
|
||||
</template>
|
||||
|
||||
<script type="js">
|
||||
<script type="ts">
|
||||
import GenericModal from "../Helper/GenericModal.vue";
|
||||
import FormRow from "../Helper/FormRow.vue";
|
||||
import api from "../../api.js";
|
||||
import { updateAuthStatus, isConfigured } from "./auth.js";
|
||||
import { updateAuthStatus, isConfigured } from "./auth";
|
||||
import { defineComponent } from "vue";
|
||||
|
||||
export default {
|
||||
export default defineComponent({
|
||||
name: "PasswordModal",
|
||||
components: { FormRow, GenericModal },
|
||||
data: () => {
|
||||
|
|
@ -173,5 +174,5 @@ export default {
|
|||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
});
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -1,107 +0,0 @@
|
|||
import { reactive, watch } from "vue";
|
||||
import api from "../../api.js";
|
||||
import store from "../../store.js";
|
||||
import Modal from "bootstrap/js/dist/modal";
|
||||
import { isSystemError } from "../../utils/fatal.js";
|
||||
|
||||
const auth = reactive({
|
||||
configured: true,
|
||||
loggedIn: null, // true / false / null (unknown)
|
||||
nextUrl: null, // url to navigate to after login
|
||||
nextModal: null, // modal instance to show after login
|
||||
});
|
||||
|
||||
export async function updateAuthStatus() {
|
||||
if (store.state.offline || isSystemError(store.state.fatal)) {
|
||||
// system not ready, skip auth check
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const res = await api.get("/auth/status", {
|
||||
validateStatus: (code) => [200, 501, 500].includes(code),
|
||||
});
|
||||
if (res.status === 501) {
|
||||
auth.configured = false;
|
||||
}
|
||||
if (res.status === 200) {
|
||||
auth.configured = true;
|
||||
auth.loggedIn = res.data === true;
|
||||
}
|
||||
if (res.status === 500) {
|
||||
auth.loggedIn = null;
|
||||
console.log("unable to fetch auth status", res);
|
||||
}
|
||||
} catch (e) {
|
||||
console.log("unable to fetch auth status", e);
|
||||
}
|
||||
}
|
||||
|
||||
export async function logout() {
|
||||
try {
|
||||
await api.post("/auth/logout");
|
||||
await updateAuthStatus();
|
||||
auth.nextUrl = null;
|
||||
} catch (e) {
|
||||
console.log("unable to logout", e);
|
||||
}
|
||||
}
|
||||
|
||||
export function isLoggedIn() {
|
||||
return auth.loggedIn === true;
|
||||
}
|
||||
|
||||
export function statusUnknown() {
|
||||
return auth.loggedIn === null;
|
||||
}
|
||||
|
||||
export function isConfigured() {
|
||||
return auth.configured;
|
||||
}
|
||||
|
||||
export function getAndClearNextUrl() {
|
||||
const nextUrl = auth.nextUrl;
|
||||
auth.nextUrl = null;
|
||||
return nextUrl;
|
||||
}
|
||||
|
||||
export function getAndClearNextModal() {
|
||||
const nextModal = auth.nextModal;
|
||||
auth.nextModal = null;
|
||||
return nextModal;
|
||||
}
|
||||
|
||||
export function openLoginModal(nextUrl = null, nextModal = null) {
|
||||
auth.nextUrl = nextUrl;
|
||||
auth.nextModal = nextModal;
|
||||
const modal = Modal.getOrCreateInstance(document.getElementById("loginModal"));
|
||||
modal.show();
|
||||
}
|
||||
|
||||
// show/hide password modal based on auth status
|
||||
watch(
|
||||
() => auth.configured,
|
||||
(configured) => {
|
||||
console.log("configured", configured);
|
||||
const modal = Modal.getOrCreateInstance(document.getElementById("passwordModal"));
|
||||
if (configured) {
|
||||
modal.hide();
|
||||
} else {
|
||||
modal.show();
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
let timeoutId = null;
|
||||
function debounedUpdateAuthStatus() {
|
||||
clearTimeout(timeoutId);
|
||||
timeoutId = setTimeout(() => {
|
||||
updateAuthStatus();
|
||||
}, 500);
|
||||
}
|
||||
|
||||
// update auth status on reconnect or server restart
|
||||
watch(() => store.state.offline, debounedUpdateAuthStatus);
|
||||
watch(() => store.state.startup, debounedUpdateAuthStatus);
|
||||
|
||||
export default auth;
|
||||
109
assets/js/components/Auth/auth.ts
Normal file
109
assets/js/components/Auth/auth.ts
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
import { reactive, watch } from "vue";
|
||||
import api from "../../api.js";
|
||||
import store from "../../store.js";
|
||||
import Modal from "bootstrap/js/dist/modal";
|
||||
import { isSystemError } from "../../utils/fatal.js";
|
||||
|
||||
const auth = reactive({
|
||||
configured: true,
|
||||
loggedIn: null as boolean | null, // true / false / null (unknown)
|
||||
nextUrl: null as string | null, // url to navigate to after login
|
||||
nextModal: null as Modal | null, // modal instance to show after login
|
||||
});
|
||||
|
||||
export async function updateAuthStatus() {
|
||||
if (store.state.offline || isSystemError(store.state.fatal)) {
|
||||
// system not ready, skip auth check
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const res = await api.get("/auth/status", {
|
||||
validateStatus: (code) => [200, 501, 500].includes(code),
|
||||
});
|
||||
if (res.status === 501) {
|
||||
auth.configured = false;
|
||||
}
|
||||
if (res.status === 200) {
|
||||
auth.configured = true;
|
||||
auth.loggedIn = res.data === true;
|
||||
}
|
||||
if (res.status === 500) {
|
||||
auth.loggedIn = null;
|
||||
console.log("unable to fetch auth status", res);
|
||||
}
|
||||
} catch (e) {
|
||||
console.log("unable to fetch auth status", e);
|
||||
}
|
||||
}
|
||||
|
||||
export async function logout() {
|
||||
try {
|
||||
await api.post("/auth/logout");
|
||||
await updateAuthStatus();
|
||||
auth.nextUrl = null;
|
||||
} catch (e) {
|
||||
console.log("unable to logout", e);
|
||||
}
|
||||
}
|
||||
|
||||
export function isLoggedIn() {
|
||||
return auth.loggedIn === true;
|
||||
}
|
||||
|
||||
export function statusUnknown() {
|
||||
return auth.loggedIn === null;
|
||||
}
|
||||
|
||||
export function isConfigured() {
|
||||
return auth.configured;
|
||||
}
|
||||
|
||||
export function getAndClearNextUrl() {
|
||||
const nextUrl = auth.nextUrl;
|
||||
auth.nextUrl = null;
|
||||
return nextUrl;
|
||||
}
|
||||
|
||||
export function getAndClearNextModal() {
|
||||
const nextModal = auth.nextModal;
|
||||
auth.nextModal = null;
|
||||
return nextModal;
|
||||
}
|
||||
|
||||
export function openLoginModal(nextUrl = null, nextModal = null) {
|
||||
auth.nextUrl = nextUrl;
|
||||
auth.nextModal = nextModal;
|
||||
const modal = Modal.getOrCreateInstance(document.getElementById("loginModal") as HTMLElement);
|
||||
modal.show();
|
||||
}
|
||||
|
||||
// show/hide password modal based on auth status
|
||||
watch(
|
||||
() => auth.configured,
|
||||
(configured) => {
|
||||
console.log("configured", configured);
|
||||
const modal = Modal.getOrCreateInstance(
|
||||
document.getElementById("passwordModal") as HTMLElement
|
||||
);
|
||||
if (configured) {
|
||||
modal.hide();
|
||||
} else {
|
||||
modal.show();
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
let timeoutId: number | undefined = undefined;
|
||||
function debounedUpdateAuthStatus() {
|
||||
clearTimeout(timeoutId);
|
||||
timeoutId = setTimeout(() => {
|
||||
updateAuthStatus();
|
||||
}, 500);
|
||||
}
|
||||
|
||||
// update auth status on reconnect or server restart
|
||||
watch(() => store.state.offline, debounedUpdateAuthStatus);
|
||||
watch(() => store.state.startup, debounedUpdateAuthStatus);
|
||||
|
||||
export default auth;
|
||||
|
|
@ -140,7 +140,7 @@
|
|||
import Modal from "bootstrap/js/dist/modal";
|
||||
import { docsPrefix } from "../i18n.js";
|
||||
import { performRestart } from "../restart.js";
|
||||
import { isLoggedIn, openLoginModal } from "./Auth/auth.js";
|
||||
import { isLoggedIn, openLoginModal } from "./Auth/auth";
|
||||
|
||||
export default {
|
||||
name: "HelpModal",
|
||||
|
|
|
|||
|
|
@ -131,7 +131,7 @@ import "@h2d2/shopicons/es/regular/moonstars";
|
|||
import "@h2d2/shopicons/es/regular/menu";
|
||||
import "@h2d2/shopicons/es/regular/newtab";
|
||||
import collector from "../../mixins/collector.js";
|
||||
import { logout, isLoggedIn, openLoginModal } from "../Auth/auth.js";
|
||||
import { logout, isLoggedIn, openLoginModal } from "../Auth/auth";
|
||||
import baseAPI from "./baseapi.js";
|
||||
import { isApp, sendToApp } from "../../utils/native.js";
|
||||
import { isUserConfigError } from "../../utils/fatal.js";
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import {
|
|||
updateAuthStatus,
|
||||
isLoggedIn,
|
||||
isConfigured,
|
||||
} from "./components/Auth/auth.js";
|
||||
} from "./components/Auth/auth";
|
||||
|
||||
function hideAllModals() {
|
||||
[...document.querySelectorAll(".modal.show")].forEach((modal) => {
|
||||
|
|
|
|||
|
|
@ -8,9 +8,13 @@ declare global {
|
|||
|
||||
export interface State {
|
||||
offline: boolean;
|
||||
startup?: boolean;
|
||||
loadpoints: [];
|
||||
forecast?: any;
|
||||
currency?: CURRENCY;
|
||||
fatal?: {
|
||||
error: any;
|
||||
};
|
||||
}
|
||||
|
||||
export enum CURRENCY {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue