Login still a bit buggy but working...
This commit is contained in:
parent
119aba2b3c
commit
b759d8324c
|
@ -1,52 +1,38 @@
|
||||||
<template>
|
<template>
|
||||||
<button v-if="store.isUserLogged" @click="logout" class="action-button">
|
<button v-if="store.isUserLogged" @click="logout" class="action-button">
|
||||||
Logout
|
Logout {{ store.user.username }}
|
||||||
</button>
|
</button>
|
||||||
<ModalDialog v-else title="Login">
|
<ModalDialog v-if="store.user.isOpenLoginModal" title="Login">
|
||||||
<form @submit="login">
|
<form @submit.prevent="login">
|
||||||
<label for="username">Username:</label
|
<div class="login-container">
|
||||||
><input
|
<label for="username">Username:</label>
|
||||||
id="username"
|
<input
|
||||||
name="username"
|
id="username"
|
||||||
autocomplete="username"
|
name="username"
|
||||||
required
|
autocomplete="username"
|
||||||
v-model="loginForm.username"
|
required
|
||||||
/>
|
v-model="loginForm.username"
|
||||||
<label for="password">Password:</label
|
/>
|
||||||
><input
|
<label for="password">Password:</label>
|
||||||
id="password"
|
<input
|
||||||
name="password"
|
id="password"
|
||||||
type="password"
|
name="password"
|
||||||
autocomplete="current-password"
|
type="password"
|
||||||
required
|
autocomplete="current-password"
|
||||||
v-model="loginForm.password"
|
required
|
||||||
/>
|
v-model="loginForm.password"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
<h3 v-if="loginForm.error.length > 0" class="error-text">
|
<h3 v-if="loginForm.error.length > 0" class="error-text">
|
||||||
{{ loginForm.error }}
|
{{ loginForm.error }}
|
||||||
</h3>
|
</h3>
|
||||||
<input type="submit" />
|
<input type="submit" class="button-login" />
|
||||||
</form>
|
</form>
|
||||||
</ModalDialog>
|
</ModalDialog>
|
||||||
|
|
||||||
<!--
|
|
||||||
|
|
||||||
<a-tooltip title="Login">
|
|
||||||
<template v-if="DocumentStore.isUserLogged">
|
|
||||||
<a-button @click="logout" type="text" class="action-button" :icon="h(UserDeleteOutlined)" />
|
|
||||||
</template>
|
|
||||||
<template v-else>
|
|
||||||
<a-button @click="showModal" type="text" class="action-button" :icon="h(UserOutlined)" />
|
|
||||||
</template>
|
|
||||||
</a-tooltip>
|
|
||||||
<a-modal v-model:open="DocumentStore.user.isOpenLoginModal" :confirm-loading="confirmLoading" okText="Login" @ok="login">
|
|
||||||
<div class="login-container">
|
|
||||||
</div>
|
|
||||||
</a-modal>
|
|
||||||
-->
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref } from 'vue'
|
import { reactive, ref } from 'vue'
|
||||||
import { loginUser, logoutUser } from '@/repositories/User'
|
import { loginUser, logoutUser } from '@/repositories/User'
|
||||||
import type { ISimpleError } from '@/repositories/Client'
|
import type { ISimpleError } from '@/repositories/Client'
|
||||||
import { useDocumentStore } from '@/stores/documents'
|
import { useDocumentStore } from '@/stores/documents'
|
||||||
|
@ -62,7 +48,7 @@ const logout = async () => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const loginForm = ref({
|
const loginForm = reactive({
|
||||||
username: '',
|
username: '',
|
||||||
password: '',
|
password: '',
|
||||||
error: ''
|
error: ''
|
||||||
|
@ -70,16 +56,15 @@ const loginForm = ref({
|
||||||
|
|
||||||
const login = async () => {
|
const login = async () => {
|
||||||
try {
|
try {
|
||||||
loginForm.value.error = ''
|
loginForm.error = ''
|
||||||
confirmLoading.value = true
|
confirmLoading.value = true
|
||||||
const user = await loginUser(loginForm.value.username, loginForm.value.password)
|
const msg = await loginUser(loginForm.username, loginForm.password)
|
||||||
if (user) {
|
console.log('Logged in', msg)
|
||||||
location.reload()
|
store.login(msg.username, !!msg.privileged)
|
||||||
}
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
const httpError = error as ISimpleError
|
const httpError = error as ISimpleError
|
||||||
if (httpError.name) {
|
if (httpError.name) {
|
||||||
loginForm.value.error = httpError.message
|
loginForm.error = httpError.message
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
confirmLoading.value = false
|
confirmLoading.value = false
|
||||||
|
@ -90,11 +75,14 @@ const login = async () => {
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.login-container {
|
.login-container {
|
||||||
display: grid;
|
display: grid;
|
||||||
|
gap: 1rem;
|
||||||
grid-template-columns: 1fr 2fr;
|
grid-template-columns: 1fr 2fr;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
margin: 1rem 0;
|
||||||
}
|
}
|
||||||
.button-login {
|
.button-login {
|
||||||
|
margin-left: auto;
|
||||||
background-color: var(--secondary-color);
|
background-color: var(--secondary-color);
|
||||||
color: var(--secondary-background);
|
color: var(--secondary-background);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,6 @@
|
||||||
/* Base domain for all request */
|
|
||||||
export const baseURL = import.meta.env.VITE_URL_DOCUMENT
|
|
||||||
|
|
||||||
class ClientClass {
|
class ClientClass {
|
||||||
async post(url: string, data?: Record<string, any>): Promise<any> {
|
async post(url: string, data?: Record<string, any>): Promise<any> {
|
||||||
const res = await fetch(`${baseURL}/`, {
|
const res = await fetch(url, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
accept: 'application/json',
|
accept: 'application/json',
|
||||||
|
@ -11,7 +8,12 @@ class ClientClass {
|
||||||
},
|
},
|
||||||
body: data !== undefined ? JSON.stringify(data) : undefined
|
body: data !== undefined ? JSON.stringify(data) : undefined
|
||||||
})
|
})
|
||||||
const msg = await res.json()
|
let msg
|
||||||
|
try {
|
||||||
|
msg = await res.json()
|
||||||
|
} catch (e) {
|
||||||
|
throw new SimpleError(res.status, `HTTP ${res.status} ${res.statusText}`)
|
||||||
|
}
|
||||||
if ('error' in msg) throw new SimpleError(msg.error.code, msg.error.message)
|
if ('error' in msg) throw new SimpleError(msg.error.code, msg.error.message)
|
||||||
return msg
|
return msg
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import type { DocumentStore } from '@/stores/documents'
|
import type { DocumentStore } from '@/stores/documents'
|
||||||
import { useDocumentStore } from '@/stores/documents'
|
import { useDocumentStore } from '@/stores/documents'
|
||||||
|
import createWebSocket from './WS'
|
||||||
|
|
||||||
export type FUID = string
|
export type FUID = string
|
||||||
|
|
||||||
|
@ -63,6 +64,19 @@ export class DocumentHandler {
|
||||||
|
|
||||||
handleWebSocketMessage(event: MessageEvent) {
|
handleWebSocketMessage(event: MessageEvent) {
|
||||||
const msg = JSON.parse(event.data)
|
const msg = JSON.parse(event.data)
|
||||||
|
if ("error" in msg) {
|
||||||
|
if (msg.error.code === 401) {
|
||||||
|
this.store.user.isLoggedIn = false
|
||||||
|
this.store.user.isOpenLoginModal = true
|
||||||
|
} else {
|
||||||
|
this.store.error = msg.error.message
|
||||||
|
}
|
||||||
|
// The server closes the websocket after errors, so we need to reopen it
|
||||||
|
setTimeout(
|
||||||
|
() => { this.store.wsWatch = createWebSocket(url_document_watch_ws, this.handleWebSocketMessage)},
|
||||||
|
1000
|
||||||
|
)
|
||||||
|
}
|
||||||
switch (true) {
|
switch (true) {
|
||||||
case !!msg.root:
|
case !!msg.root:
|
||||||
this.handleRootMessage(msg)
|
this.handleRootMessage(msg)
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { createRouter, createWebHashHistory } from 'vue-router'
|
import { createRouter, createWebHashHistory } from 'vue-router'
|
||||||
import ExplorerView from '../views/ExplorerView.vue'
|
import ExplorerView from '@/views/ExplorerView.vue'
|
||||||
|
|
||||||
const router = createRouter({
|
const router = createRouter({
|
||||||
history: createWebHashHistory(import.meta.env.BASE_URL),
|
history: createWebHashHistory(import.meta.env.BASE_URL),
|
||||||
|
|
|
@ -15,6 +15,8 @@ type DirectoryData = {
|
||||||
[filename: string]: FileData
|
[filename: string]: FileData
|
||||||
}
|
}
|
||||||
type User = {
|
type User = {
|
||||||
|
username: string
|
||||||
|
privileged: boolean
|
||||||
isOpenLoginModal: boolean
|
isOpenLoginModal: boolean
|
||||||
isLoggedIn: boolean
|
isLoggedIn: boolean
|
||||||
}
|
}
|
||||||
|
@ -42,7 +44,7 @@ export const useDocumentStore = defineStore({
|
||||||
wsWatch: undefined,
|
wsWatch: undefined,
|
||||||
wsUpload: undefined,
|
wsUpload: undefined,
|
||||||
error: '' as string,
|
error: '' as string,
|
||||||
user: { isLoggedIn: false, isOpenLoginModal: false } as User
|
user: { username: "", privileged: false, isLoggedIn: false, isOpenLoginModal: false } as User
|
||||||
}),
|
}),
|
||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
|
@ -137,6 +139,12 @@ export const useDocumentStore = defineStore({
|
||||||
for (const d of this.document) {
|
for (const d of this.document) {
|
||||||
if ('mtime' in d) d.modified = formatUnixDate(d.mtime)
|
if ('mtime' in d) d.modified = formatUnixDate(d.mtime)
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
login(username: string, privileged: boolean) {
|
||||||
|
this.user.username = username
|
||||||
|
this.user.privileged = privileged
|
||||||
|
this.user.isLoggedIn = true
|
||||||
|
this.user.isOpenLoginModal = false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
getters: {
|
getters: {
|
||||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1,7 +1,7 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang=en>
|
<html lang=en>
|
||||||
<script type="module" crossorigin src="/assets/index-2034a7a8.js"></script>
|
<script type="module" crossorigin src="/assets/index-eb4428c4.js"></script>
|
||||||
<link rel="stylesheet" href="/assets/index-c3cea0a2.css">
|
<link rel="stylesheet" href="/assets/index-683ba1dc.css">
|
||||||
|
|
||||||
<meta charset=UTF-8>
|
<meta charset=UTF-8>
|
||||||
<title>Cista</title>
|
<title>Cista</title>
|
||||||
|
|
Loading…
Reference in New Issue
Block a user