35099de2c5
- Fix: Share-Dialog oeffnet sich jetzt auch bei bereits geteilten Dateien - Neu: Dateien/Ordner direkt mit anderen Benutzern teilen (Lesen/Schreiben/Admin) - Neu: Benutzersuche im Share-Dialog, bestehende Freigaben anzeigen/entfernen - Neu: Admin kann Benutzer ueber die Weboberflaeche anlegen - Neu: Admin kann Benutzer bearbeiten (Rolle, Quota, aktiv/inaktiv) und loeschen - Neu: Schieberegler fuer oeffentliche Registrierung in den Admin-Einstellungen - Neu: Register-Link auf Login-Seite nur sichtbar wenn Registrierung erlaubt - Neu: Register-Seite leitet um wenn Registrierung deaktiviert - Neu: AppSettings-Model fuer persistente App-Konfiguration - Neu: /api/users/search Endpunkt fuer Benutzersuche in Share-Dialogen Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
156 lines
3.3 KiB
Vue
156 lines
3.3 KiB
Vue
<template>
|
|
<div class="auth-container">
|
|
<div class="auth-card">
|
|
<div class="auth-header">
|
|
<i class="pi pi-cloud" style="font-size: 2.5rem; color: var(--p-primary-color)"></i>
|
|
<h1>Mini-Cloud</h1>
|
|
<p>Anmelden</p>
|
|
</div>
|
|
|
|
<form @submit.prevent="handleLogin" class="auth-form">
|
|
<div class="field">
|
|
<label for="username">Benutzername</label>
|
|
<InputText
|
|
id="username"
|
|
v-model="username"
|
|
placeholder="Benutzername"
|
|
:invalid="!!error"
|
|
autofocus
|
|
fluid
|
|
/>
|
|
</div>
|
|
|
|
<div class="field">
|
|
<label for="password">Passwort</label>
|
|
<Password
|
|
id="password"
|
|
v-model="password"
|
|
placeholder="Passwort"
|
|
:feedback="false"
|
|
:invalid="!!error"
|
|
toggle-mask
|
|
fluid
|
|
/>
|
|
</div>
|
|
|
|
<Message v-if="error" severity="error" :closable="false">{{ error }}</Message>
|
|
|
|
<Button
|
|
type="submit"
|
|
label="Anmelden"
|
|
:loading="loading"
|
|
fluid
|
|
/>
|
|
</form>
|
|
|
|
<div v-if="registrationAllowed" class="auth-footer">
|
|
<router-link to="/register">Noch kein Konto? Registrieren</router-link>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { ref, onMounted } from 'vue'
|
|
import { useRouter } from 'vue-router'
|
|
import { useAuthStore } from '../stores/auth'
|
|
import axios from 'axios'
|
|
import InputText from 'primevue/inputtext'
|
|
import Password from 'primevue/password'
|
|
import Button from 'primevue/button'
|
|
import Message from 'primevue/message'
|
|
|
|
const router = useRouter()
|
|
const auth = useAuthStore()
|
|
|
|
const username = ref('')
|
|
const password = ref('')
|
|
const error = ref('')
|
|
const loading = ref(false)
|
|
const registrationAllowed = ref(false)
|
|
|
|
onMounted(async () => {
|
|
try {
|
|
const res = await axios.get('/api/auth/registration-status')
|
|
registrationAllowed.value = res.data.allowed
|
|
} catch { registrationAllowed.value = false }
|
|
})
|
|
|
|
async function handleLogin() {
|
|
error.value = ''
|
|
loading.value = true
|
|
try {
|
|
await auth.login(username.value, password.value)
|
|
router.push('/')
|
|
} catch (err) {
|
|
error.value = err.response?.data?.error || 'Anmeldung fehlgeschlagen'
|
|
} finally {
|
|
loading.value = false
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style scoped>
|
|
.auth-container {
|
|
min-height: 100vh;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
background: var(--p-surface-50);
|
|
}
|
|
|
|
.auth-card {
|
|
background: var(--p-surface-0);
|
|
border-radius: 12px;
|
|
padding: 2.5rem;
|
|
width: 100%;
|
|
max-width: 400px;
|
|
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
|
|
}
|
|
|
|
.auth-header {
|
|
text-align: center;
|
|
margin-bottom: 2rem;
|
|
}
|
|
|
|
.auth-header h1 {
|
|
margin: 0.5rem 0 0.25rem;
|
|
font-size: 1.5rem;
|
|
}
|
|
|
|
.auth-header p {
|
|
color: var(--p-text-muted-color);
|
|
margin: 0;
|
|
}
|
|
|
|
.auth-form .field {
|
|
margin-bottom: 1rem;
|
|
}
|
|
|
|
.auth-form .field label {
|
|
display: block;
|
|
margin-bottom: 0.5rem;
|
|
font-weight: 500;
|
|
font-size: 0.875rem;
|
|
}
|
|
|
|
.auth-form button {
|
|
margin-top: 0.5rem;
|
|
}
|
|
|
|
.auth-footer {
|
|
text-align: center;
|
|
margin-top: 1.5rem;
|
|
font-size: 0.875rem;
|
|
}
|
|
|
|
.auth-footer a {
|
|
color: var(--p-primary-color);
|
|
text-decoration: none;
|
|
}
|
|
|
|
.auth-footer a:hover {
|
|
text-decoration: underline;
|
|
}
|
|
</style>
|