way better admin login flow
This commit is contained in:
		
							parent
							
								
									2da7b6914a
								
							
						
					
					
						commit
						b30e8095f9
					
				
					 4 changed files with 74 additions and 62 deletions
				
			
		|  | @ -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"]) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -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)); | ||||||
|  |  | ||||||
|  | @ -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> | ||||||
|  |  | ||||||
|  | @ -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 }; | ||||||
|   } |   } | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue