way better admin login flow

This commit is contained in:
Jörn-Michael Miehe 2023-09-11 23:36:36 +00:00
parent 2da7b6914a
commit b30e8095f9
4 changed files with 74 additions and 62 deletions

View file

@ -7,7 +7,7 @@ from ..core.calendar_config import CalendarConfig, get_calendar_config
from ..core.config import Config, get_config from ..core.config import Config, get_config
from ..core.depends import shuffle_solution from ..core.depends import shuffle_solution
from ..core.settings import SETTINGS from ..core.settings import SETTINGS
from ._security import user_is_admin from ._security import require_admin, user_is_admin
router = APIRouter(prefix="/admin", tags=["admin"]) router = APIRouter(prefix="/admin", tags=["admin"])

View file

@ -1,10 +1,14 @@
<template> <template>
<LoginModal ref="login_modal" @submit="on_login" /> <LoginModal
v-if="modal_visible"
@submit="on_submit"
@cancel="modal_visible = false"
/>
<BulmaButton <BulmaButton
class="button is-light" class="button is-light"
@click.left="$refs.login_modal.set_active(true)" @click.left="on_click"
icon="fa-solid fa-toggle-off" :icon="'fa-solid fa-toggle-' + (modelValue ? 'on' : 'off')"
text="Admin" text="Admin"
/> />
</template> </template>
@ -28,12 +32,23 @@ import LoginModal from "./LoginModal.vue";
export default class extends Vue { export default class extends Vue {
// true, iff Benutzer Admin ist // true, iff Benutzer Admin ist
public modelValue!: boolean; public modelValue!: boolean;
public modal_visible = false;
declare $refs: { public on_click() {
login_modal: LoginModal; if (this.modelValue) {
}; // logout
this.$advent22.clear_api_auth();
this.$emit("update:modelValue", false);
} else {
// show login modal
this.modal_visible = true;
}
}
public on_submit(username: string, password: string) {
this.modal_visible = false;
this.$advent22.set_api_auth(username, password);
public on_login() {
this.$advent22 this.$advent22
.api_get<boolean>("admin/is_admin") .api_get<boolean>("admin/is_admin")
.then((is_admin) => this.$emit("update:modelValue", is_admin)); .then((is_admin) => this.$emit("update:modelValue", is_admin));

View file

@ -1,15 +1,14 @@
<template> <template>
<div v-show="active" class="modal is-active"> <div class="modal is-active">
<div class="modal-background" /> <div class="modal-background" />
<div class="modal-card"> <div class="modal-card">
<form @submit.prevent="submit">
<header class="modal-card-head"> <header class="modal-card-head">
<p class="modal-card-title">Login</p> <p class="modal-card-title">Login</p>
<button <button
class="delete" class="delete"
aria-label="close" aria-label="close"
@click.left="set_active(false)" @click.left="$emit('cancel')"
/> />
</header> </header>
@ -33,18 +32,17 @@
</div> </div>
</div> </div>
</section> </section>
</form>
<footer class="modal-card-foot is-flex is-justify-content-space-around"> <footer class="modal-card-foot is-flex is-justify-content-space-around">
<BulmaButton <BulmaButton
class="button is-success" class="button is-success"
@click.left="submit" @click.left="$emit('submit', username, password)"
icon="fa-solid fa-unlock" icon="fa-solid fa-unlock"
text="Login" text="Login"
/> />
<BulmaButton <BulmaButton
class="button is-danger" class="button is-danger"
@click.left="set_active(false)" @click.left="$emit('cancel')"
icon="fa-solid fa-circle-xmark" icon="fa-solid fa-circle-xmark"
text="Abbrechen" text="Abbrechen"
/> />
@ -62,10 +60,12 @@ import BulmaButton from "./bulma/Button.vue";
components: { components: {
BulmaButton, BulmaButton,
}, },
emits: ["submit"], props: {
visible: Boolean,
},
emits: ["cancel", "submit"],
}) })
export default class extends Vue { export default class extends Vue {
public active = false;
public username = ""; public username = "";
public password = ""; public password = "";
@ -73,31 +73,24 @@ export default class extends Vue {
username_input: HTMLInputElement | null | undefined; username_input: HTMLInputElement | null | undefined;
}; };
public created() { private on_keydown(e: KeyboardEvent) {
window.addEventListener("keydown", (e) => { if (e.key == "Escape") this.$emit("cancel");
if (e.key == "Escape") this.set_active(false); else if (e.key == "Enter")
}); this.$emit("submit", this.username, this.password);
} }
public set_active(state: boolean) { public mounted(): void {
this.active = state; window.addEventListener("keydown", this.on_keydown);
if (this.active) {
this.username = "";
this.password = "";
this.$nextTick(() => { this.$nextTick(() => {
if (this.$refs.username_input instanceof HTMLInputElement) { if (this.$refs.username_input instanceof HTMLInputElement) {
this.$refs.username_input?.focus(); this.$refs.username_input.focus();
} }
}); });
} }
}
public submit() { public beforeUnmount(): void {
this.$advent22.set_api_auth(this.username, this.password); window.removeEventListener("keydown", this.on_keydown);
this.$emit("submit");
this.set_active(false);
} }
} }
</script> </script>

View file

@ -38,6 +38,10 @@ export class Advent22 {
return `${this.api_baseurl}/${endpoint}`; return `${this.api_baseurl}/${endpoint}`;
} }
public clear_api_auth() {
this.api_auth = { username: "", password: "" };
}
public set_api_auth(username: string, password: string) { public set_api_auth(username: string, password: string) {
this.api_auth = { username: username, password: password }; this.api_auth = { username: username, password: password };
} }