Initial commit
This commit is contained in:
24
pages/dashboard.vue
Normal file
24
pages/dashboard.vue
Normal file
@@ -0,0 +1,24 @@
|
||||
<template>
|
||||
<v-row>
|
||||
<v-col class="text-center">
|
||||
<blockquote class="blockquote">
|
||||
“First, solve the problem. Then, write the code.”
|
||||
<footer>
|
||||
<small>
|
||||
<em>—John Johnson</em>
|
||||
</small>
|
||||
</footer>
|
||||
</blockquote>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'DashboardPage',
|
||||
layout ({ $auth }) {
|
||||
// Ref: https://firebase.google.com/docs/reference/js/v8/firebase.auth.Auth#currentuser
|
||||
return $auth.currentUser.emailVerified ? 'default' : 'unverified'
|
||||
}
|
||||
}
|
||||
</script>
|
||||
29
pages/index.vue
Normal file
29
pages/index.vue
Normal file
@@ -0,0 +1,29 @@
|
||||
<template>
|
||||
<v-overlay color="transparent">
|
||||
<v-progress-circular color="primary" indeterminate />
|
||||
</v-overlay>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { onAuthStateChanged } from 'firebase/auth'
|
||||
|
||||
export default {
|
||||
name: 'IndexPage',
|
||||
layout: 'empty',
|
||||
created () {
|
||||
// Setting an authentication state observer on the Firebase Auth object.
|
||||
// This observer gets called when Auth finished initializing and
|
||||
// whenever the user's sign-in state changes.
|
||||
onAuthStateChanged(this.$auth, (user) => {
|
||||
this.$store.commit('initFirebase')
|
||||
if (user) {
|
||||
// User is signed in; redirect to main page (dashboard)
|
||||
this.$router.push({ name: 'dashboard' })
|
||||
} else {
|
||||
// User is signed out; redirect to login page
|
||||
this.$router.push({ name: 'login' })
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
234
pages/login.vue
Normal file
234
pages/login.vue
Normal file
@@ -0,0 +1,234 @@
|
||||
<template>
|
||||
<v-container>
|
||||
<v-card v-if="existingUser" max-width="500px" elevation="12" class="mx-auto">
|
||||
<v-card-text>
|
||||
<v-form ref="loginForm" v-model="valid">
|
||||
<v-text-field
|
||||
v-model="email"
|
||||
label="Deine IU E-Mail-Adresse"
|
||||
prepend-icon="mdi-account-circle"
|
||||
@keyup.enter="signIn"
|
||||
/>
|
||||
<v-text-field
|
||||
v-model="password"
|
||||
:type="showPassword ? 'text' : 'password'"
|
||||
label="Passwort"
|
||||
prepend-icon="mdi-lock"
|
||||
:append-icon="showPassword ? 'mdi-eye' : 'mdi-eye-off'"
|
||||
@click:append="showPassword = !showPassword"
|
||||
@keyup.enter="signIn"
|
||||
/>
|
||||
</v-form>
|
||||
<v-btn
|
||||
block
|
||||
depressed
|
||||
color="primary"
|
||||
:loading="loading"
|
||||
:disabled="loading"
|
||||
@click="signIn"
|
||||
>
|
||||
Anmelden
|
||||
</v-btn>
|
||||
</v-card-text>
|
||||
<v-card-text>
|
||||
<v-btn text block color="primary" @click="existingUser = false">Noch kein Konto?</v-btn>
|
||||
<v-btn text block color="primary" @click="showPwResetDialog = true">Passwort vergessen?</v-btn>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
<v-card v-else max-width="500px" elevation="12" class="mx-auto">
|
||||
<v-card-text>
|
||||
<v-form ref="signupForm" v-model="valid">
|
||||
<v-text-field
|
||||
v-model="email"
|
||||
:rules="emailRules"
|
||||
label="Deine IU E-Mail-Adresse"
|
||||
prepend-icon="mdi-account-circle"
|
||||
@keyup.enter="signUp"
|
||||
/>
|
||||
<v-text-field
|
||||
v-model="password"
|
||||
:rules="passwordRules"
|
||||
:type="showPassword ? 'text' : 'password'"
|
||||
label="Passwort"
|
||||
prepend-icon="mdi-lock"
|
||||
:append-icon="showPassword ? 'mdi-eye' : 'mdi-eye-off'"
|
||||
@click:append="showPassword = !showPassword"
|
||||
@keyup.enter="signUp"
|
||||
/>
|
||||
<v-text-field
|
||||
v-model="passwordConfirm"
|
||||
:rules="passwordConfirmRules"
|
||||
:type="showPassword ? 'text' : 'password'"
|
||||
label="Passwort bestätigen"
|
||||
prepend-icon="mdi-lock"
|
||||
:append-icon="showPassword ? 'mdi-eye' : 'mdi-eye-off'"
|
||||
@click:append="showPassword = !showPassword"
|
||||
@keyup.enter="signUp"
|
||||
/>
|
||||
<v-checkbox
|
||||
v-model="checkbox"
|
||||
:rules="[v => !!v || '']"
|
||||
required
|
||||
>
|
||||
<template #label>
|
||||
<div>
|
||||
Ich stimme den Nutzungs- und Datenschutzbestimmungen zu.
|
||||
</div>
|
||||
</template>
|
||||
</v-checkbox>
|
||||
</v-form>
|
||||
<v-btn
|
||||
block
|
||||
depressed
|
||||
color="primary"
|
||||
:loading="loading"
|
||||
:disabled="loading"
|
||||
@click="signUp"
|
||||
>
|
||||
Registrieren
|
||||
</v-btn>
|
||||
<v-btn
|
||||
text
|
||||
block
|
||||
color="primary"
|
||||
class="mt-3"
|
||||
@click="existingUser = true"
|
||||
>
|
||||
Bereits registriert?
|
||||
</v-btn>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
<v-dialog v-model="showPwResetDialog" max-width="500px">
|
||||
<v-card>
|
||||
<v-card-title>
|
||||
<span class="headline">Passwort zurücksetzen</span>
|
||||
</v-card-title>
|
||||
<v-card-text>
|
||||
<v-form ref="form" v-model="valid" @submit.prevent="resetPassword">
|
||||
<v-text-field v-model="email" autofocus label="Email" required></v-text-field>
|
||||
</v-form>
|
||||
</v-card-text>
|
||||
<v-card-actions>
|
||||
<v-spacer></v-spacer>
|
||||
<v-btn color="primary" outlined @click="showPwResetDialog = false">Abbrechen</v-btn>
|
||||
<v-btn color="primary" depressed :loading="loading" :disabled="loading" @click="resetPassword">Link senden</v-btn>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</v-dialog>
|
||||
</v-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
createUserWithEmailAndPassword,
|
||||
sendEmailVerification,
|
||||
signInWithEmailAndPassword,
|
||||
sendPasswordResetEmail
|
||||
} from 'firebase/auth'
|
||||
|
||||
export default {
|
||||
name: 'LoginPage',
|
||||
data () {
|
||||
return {
|
||||
existingUser: true,
|
||||
loading: false,
|
||||
valid: false,
|
||||
showPassword: false,
|
||||
showPwResetDialog: false,
|
||||
defaultErrorReqField: 'Feld darf nicht leer sein',
|
||||
email: '',
|
||||
emailRules: [
|
||||
v => !!v || this.defaultErrorReqField,
|
||||
v => /^\w+([.-]?\w+)*@(iu\.org|iubh-fernstudium\.de)+$/.test(v) || 'Keine gültige IU E-Mail-Adresse'
|
||||
],
|
||||
password: '',
|
||||
passwordRules: [
|
||||
v => !!v || this.defaultErrorReqField,
|
||||
v => /^(?=.*?[a-zA-Z])(?=.*?[0-9]).{8,}$/.test(v) || 'Mindestens 8 Zeichen, 1 Buchstabe und 1 Zahl'
|
||||
],
|
||||
passwordConfirm: '',
|
||||
passwordConfirmRules: [
|
||||
v => !!v || this.defaultErrorReqField,
|
||||
v => v === this.password || 'Passwörter stimmen nicht überein'
|
||||
],
|
||||
checkbox: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
signUp () {
|
||||
this.$refs.signupForm.validate()
|
||||
if (this.valid) {
|
||||
this.loading = true
|
||||
|
||||
createUserWithEmailAndPassword(this.$auth, this.email, this.password)
|
||||
.then((userCredential) => {
|
||||
// TODO: database integration
|
||||
// User signed up successfully.
|
||||
// The authentication state observer will redirect the user to the main page (dashboard),
|
||||
// see pages/index.vue
|
||||
sendEmailVerification(userCredential.user)
|
||||
.then(() => {
|
||||
// Email verification sent!
|
||||
// Nothing to do here...
|
||||
})
|
||||
})
|
||||
.catch((error) => {
|
||||
// Sign up failed; display error message
|
||||
const errorCode = error.code
|
||||
const errorMessage = error.message
|
||||
this.$toast({content: `${errorCode}: ${errorMessage}`, color: 'error'})
|
||||
})
|
||||
.then(() => {
|
||||
this.loading = false
|
||||
})
|
||||
}
|
||||
},
|
||||
signIn () {
|
||||
this.loading = true
|
||||
|
||||
signInWithEmailAndPassword(this.$auth, this.email, this.password)
|
||||
.then((userCredential) => {
|
||||
// User signed in successfully.
|
||||
// The authentication state observer will redirect the user to the main page (dashboard),
|
||||
// see pages/index.vue
|
||||
})
|
||||
.catch((error) => {
|
||||
// Sign in failed; display error message
|
||||
const errorCode = error.code
|
||||
const errorMessage = error.message
|
||||
this.$toast({content: `${errorCode}: ${errorMessage}`, color: 'error'})
|
||||
})
|
||||
.then(() => {
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
resetPassword () {
|
||||
this.$refs.form.validate()
|
||||
if (this.valid) {
|
||||
this.loading = true
|
||||
|
||||
sendPasswordResetEmail(this.$auth, this.email.trim())
|
||||
.then(() => {
|
||||
// Password reset email sent!
|
||||
this.$toast({
|
||||
content:
|
||||
`Wir haben dir einen Link zur Passwortrücksetzung an deine E-Mail-Adresse geschickt!
|
||||
Solltest du keine E-Mail erhalten haben, überprüfe deinen Spam-Ordner.`,
|
||||
color: 'success',
|
||||
timeout: -1
|
||||
})
|
||||
})
|
||||
.catch((error) => {
|
||||
// Failed to send password reset email; display error message
|
||||
const errorCode = error.code
|
||||
const errorMessage = error.message
|
||||
this.$toast({content: `${errorCode}: ${errorMessage}`, color: 'error'})
|
||||
})
|
||||
.then(() => {
|
||||
this.loading = false
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
Reference in New Issue
Block a user