mirror of
https://github.com/janishutz/libreevent.git
synced 2025-11-25 13:24:24 +00:00
restruct + 2fa + auth
This commit is contained in:
@@ -36,6 +36,7 @@ app.use( cookieParser() );
|
|||||||
app.use( express.static( '../webapp/dist' ) );
|
app.use( express.static( '../webapp/dist' ) );
|
||||||
|
|
||||||
require( './admin/routes.js' )( app, settings ); // admin route
|
require( './admin/routes.js' )( app, settings ); // admin route
|
||||||
|
require( './backend/userRoutes.js' )( app, settings ); // user route
|
||||||
|
|
||||||
app.use( ( request, response ) => {
|
app.use( ( request, response ) => {
|
||||||
response.sendFile( path.join( __dirname + '/../webapp/dist/index.html' ) );
|
response.sendFile( path.join( __dirname + '/../webapp/dist/index.html' ) );
|
||||||
|
|||||||
25
src/server/backend/credentials/pwdmanager.js
Normal file
25
src/server/backend/credentials/pwdmanager.js
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* libreevent - pwdmanager.js
|
||||||
|
*
|
||||||
|
* Created by Janis Hutz 07/11/2023, Licensed under the GPL V3 License
|
||||||
|
* https://janishutz.com, development@janishutz.com
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
These functions are required to verify user login and to create new users
|
||||||
|
and to hash new passwords (if user changes password.)
|
||||||
|
*/
|
||||||
|
|
||||||
|
// import and init
|
||||||
|
const bcrypt = require( 'bcrypt' );
|
||||||
|
const db = require( '../db/db.js' );
|
||||||
|
|
||||||
|
module.exports.checkpassword = function checkpassword ( username, password ) {
|
||||||
|
return new Promise( resolve => {
|
||||||
|
db.getData( 'user', username ).then( data => {
|
||||||
|
resolve( bcrypt.compareSync( password, data ) );
|
||||||
|
} );
|
||||||
|
} );
|
||||||
|
};
|
||||||
@@ -11,7 +11,6 @@ const path = require( 'path' );
|
|||||||
const fs = require( 'fs' );
|
const fs = require( 'fs' );
|
||||||
|
|
||||||
module.exports.getData = function getData ( db, searchQuery ) {
|
module.exports.getData = function getData ( db, searchQuery ) {
|
||||||
console.log( db + searchQuery );
|
|
||||||
return new Promise( resolve => {
|
return new Promise( resolve => {
|
||||||
resolve( '$2b$05$ElMYWoMjk7567lXkIkee.e.6cxCrWU4gkfuNLB8gmGYLQQPm7gT3O' );
|
resolve( '$2b$05$ElMYWoMjk7567lXkIkee.e.6cxCrWU4gkfuNLB8gmGYLQQPm7gT3O' );
|
||||||
} );
|
} );
|
||||||
|
|||||||
@@ -1 +1,14 @@
|
|||||||
class
|
/*
|
||||||
|
* libreevent - jsondb.js
|
||||||
|
*
|
||||||
|
* Created by Janis Hutz 07/11/2023, Licensed under the GPL V3 License
|
||||||
|
* https://janishutz.com, development@janishutz.com
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
class JSONDB {
|
||||||
|
constructor () {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
/*
|
|
||||||
* libreevent - routes.js
|
|
||||||
*
|
|
||||||
* Created by Janis Hutz 07/11/2023, Licensed under the GPL V3 License
|
|
||||||
* https://janishutz.com, development@janishutz.com
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
const db = require( './db/db.js' );
|
|
||||||
|
|
||||||
module.exports = ( app, settings ) => {
|
|
||||||
app.post( '/api/reserveTicket', ( request, response ) ) {
|
|
||||||
db.getData( 'test', request.body );
|
|
||||||
response.send( 'ok' );
|
|
||||||
};
|
|
||||||
};
|
|
||||||
38
src/server/backend/userRoutes.js
Normal file
38
src/server/backend/userRoutes.js
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* libreevent - routes.js
|
||||||
|
*
|
||||||
|
* Created by Janis Hutz 07/11/2023, Licensed under the GPL V3 License
|
||||||
|
* https://janishutz.com, development@janishutz.com
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
const db = require( './db/db.js' );
|
||||||
|
const pwdmanager = require( './credentials/pwdmanager.js' );
|
||||||
|
|
||||||
|
module.exports = ( app, settings ) => {
|
||||||
|
app.post( '/api/reserveTicket', ( request, response ) => {
|
||||||
|
db.getData( 'test', request.body );
|
||||||
|
response.send( 'ok' );
|
||||||
|
} );
|
||||||
|
|
||||||
|
app.post( '/user/login', ( request, response ) => {
|
||||||
|
if ( request.body.mail && request.body.password ) {
|
||||||
|
pwdmanager.checkpassword( request.body.mail, request.body.password ).then( data => {
|
||||||
|
if ( data ) {
|
||||||
|
if ( settings.twoFA ) {
|
||||||
|
// TODO: Support both methods of 2fa
|
||||||
|
response.send( '2fa' );
|
||||||
|
} else {
|
||||||
|
request.session.loggedInUser = true;
|
||||||
|
response.send( 'ok' );
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
response.send( 'pwErr' );
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
} else {
|
||||||
|
response.send( 'missingCredentials' );
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
};
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
{
|
{
|
||||||
"init":true
|
"init":true,
|
||||||
|
"twoFA": true
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div id="notifications" @click="handleNotifications();">
|
<div id="notifications" @click="handleNotifications();">
|
||||||
<div class="message-box" :class="location">
|
<div class="message-box" :class="[ location, size ]">
|
||||||
<div class="message-container" :class="messageType">
|
<div class="message-container" :class="messageType">
|
||||||
<span class="material-symbols-outlined types hide" v-if="messageType == 'hide'">question_mark</span>
|
<span class="material-symbols-outlined types hide" v-if="messageType == 'hide'">question_mark</span>
|
||||||
<span class="material-symbols-outlined types" v-else-if="messageType == 'ok'" style="background-color: green;">done</span>
|
<span class="material-symbols-outlined types" v-else-if="messageType == 'ok'" style="background-color: green;">done</span>
|
||||||
@@ -21,7 +21,12 @@
|
|||||||
location: {
|
location: {
|
||||||
type: String,
|
type: String,
|
||||||
'default': 'topleft',
|
'default': 'topleft',
|
||||||
|
},
|
||||||
|
size: {
|
||||||
|
type: String,
|
||||||
|
'default': 'default',
|
||||||
}
|
}
|
||||||
|
// Size options: small, default (default option), big, bigger, huge
|
||||||
},
|
},
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
@@ -119,9 +124,32 @@
|
|||||||
position: fixed;
|
position: fixed;
|
||||||
z-index: 10;
|
z-index: 10;
|
||||||
color: white;
|
color: white;
|
||||||
|
transition: all 0.5s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.default {
|
||||||
height: 10vh;
|
height: 10vh;
|
||||||
width: 15vw;
|
width: 15vw;
|
||||||
transition: all 0.5s;
|
}
|
||||||
|
|
||||||
|
.small {
|
||||||
|
height: 7vh;
|
||||||
|
width: 11vw;
|
||||||
|
}
|
||||||
|
|
||||||
|
.big {
|
||||||
|
height: 12vh;
|
||||||
|
width: 17vw;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bigger {
|
||||||
|
height: 15vh;
|
||||||
|
width: 20vw;
|
||||||
|
}
|
||||||
|
|
||||||
|
.huge {
|
||||||
|
height: 20vh;
|
||||||
|
width: 25vw;
|
||||||
}
|
}
|
||||||
|
|
||||||
.topleft {
|
.topleft {
|
||||||
|
|||||||
@@ -55,6 +55,10 @@ router.beforeEach( ( to, from ) => {
|
|||||||
return { name: 'purchase' };
|
return { name: 'purchase' };
|
||||||
} else if ( to.name.substring( 0, 5 ) === 'setup' && !backendStore.getVisitedSetupPages[ to.name.substring( 5 ).toLowerCase() ] && to.name.substring( 5 ).toLowerCase() !== 'start' && to.name.substring( 5 ).toLowerCase() !== 'root' ) {
|
} else if ( to.name.substring( 0, 5 ) === 'setup' && !backendStore.getVisitedSetupPages[ to.name.substring( 5 ).toLowerCase() ] && to.name.substring( 5 ).toLowerCase() !== 'start' && to.name.substring( 5 ).toLowerCase() !== 'root' ) {
|
||||||
return { name: 'setupStart' };
|
return { name: 'setupStart' };
|
||||||
|
} else if ( to.name === '2fa' && !userStore.getUserTwoFACompliant ) {
|
||||||
|
return { name: 'login' };
|
||||||
|
} else if ( to.name === 'Admin2fa' && !userStore.getAdminTwoFACompliant ) {
|
||||||
|
return { name: 'adminLogin' };
|
||||||
}
|
}
|
||||||
} );
|
} );
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ export default [
|
|||||||
{
|
{
|
||||||
path: '/tickets',
|
path: '/tickets',
|
||||||
name: 'tickets',
|
name: 'tickets',
|
||||||
component: () => import( '../views/OrderView.vue' ),
|
component: () => import( '../views/purchasing/OrderView.vue' ),
|
||||||
meta: {
|
meta: {
|
||||||
title: 'Order ticket - libreevent'
|
title: 'Order ticket - libreevent'
|
||||||
}
|
}
|
||||||
@@ -35,7 +35,7 @@ export default [
|
|||||||
{
|
{
|
||||||
path: '/login',
|
path: '/login',
|
||||||
name: 'login',
|
name: 'login',
|
||||||
component: () => import( '../views/LoginView.vue' ),
|
component: () => import( '../views/user/LoginView.vue' ),
|
||||||
meta: {
|
meta: {
|
||||||
title: 'Login - libreevent'
|
title: 'Login - libreevent'
|
||||||
}
|
}
|
||||||
@@ -43,7 +43,7 @@ export default [
|
|||||||
{
|
{
|
||||||
path: '/admin/login',
|
path: '/admin/login',
|
||||||
name: 'adminLogin',
|
name: 'adminLogin',
|
||||||
component: () => import( '../views/AdminLoginView.vue' ),
|
component: () => import( '../views/admin/AdminLoginView.vue' ),
|
||||||
meta: {
|
meta: {
|
||||||
title: 'Login :: Admin - libreevent'
|
title: 'Login :: Admin - libreevent'
|
||||||
}
|
}
|
||||||
@@ -51,7 +51,7 @@ export default [
|
|||||||
{
|
{
|
||||||
path: '/signup',
|
path: '/signup',
|
||||||
name: 'signup',
|
name: 'signup',
|
||||||
component: () => import( '../views/SignupView.vue' ),
|
component: () => import( '../views/user/SignupView.vue' ),
|
||||||
meta: {
|
meta: {
|
||||||
title: 'Signup - libreevent'
|
title: 'Signup - libreevent'
|
||||||
}
|
}
|
||||||
@@ -59,15 +59,23 @@ export default [
|
|||||||
{
|
{
|
||||||
path: '/account',
|
path: '/account',
|
||||||
name: 'account',
|
name: 'account',
|
||||||
component: () => import( '../views/AccountView.vue' ),
|
component: () => import( '../views/user/AccountView.vue' ),
|
||||||
meta: {
|
meta: {
|
||||||
title: 'Account - libreevent'
|
title: 'Account - libreevent'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: '/twoFactors',
|
||||||
|
name: '2fa',
|
||||||
|
component: () => import( '../views/user/TwoFA.vue' ),
|
||||||
|
meta: {
|
||||||
|
title: 'Two Factor Authentication - libreevent'
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: '/tickets/details',
|
path: '/tickets/details',
|
||||||
name: 'ticketDetails',
|
name: 'ticketDetails',
|
||||||
component: () => import( '../views/TicketsDetailsView.vue' ),
|
component: () => import( '../views/purchasing/TicketsDetailsView.vue' ),
|
||||||
meta: {
|
meta: {
|
||||||
title: 'Details - libreevent',
|
title: 'Details - libreevent',
|
||||||
transition: 'scale'
|
transition: 'scale'
|
||||||
@@ -76,7 +84,7 @@ export default [
|
|||||||
{
|
{
|
||||||
path: '/tickets/order',
|
path: '/tickets/order',
|
||||||
name: 'ticketOrder',
|
name: 'ticketOrder',
|
||||||
component: () => import( '../views/TicketsOrderingView.vue' ),
|
component: () => import( '../views/purchasing/TicketsOrderingView.vue' ),
|
||||||
meta: {
|
meta: {
|
||||||
title: 'Order ticket - libreevent',
|
title: 'Order ticket - libreevent',
|
||||||
transition: 'scale'
|
transition: 'scale'
|
||||||
@@ -85,7 +93,7 @@ export default [
|
|||||||
{
|
{
|
||||||
path: '/cart',
|
path: '/cart',
|
||||||
name: 'cart',
|
name: 'cart',
|
||||||
component: () => import( '../views/CartView.vue' ),
|
component: () => import( '../views/purchasing/CartView.vue' ),
|
||||||
meta: {
|
meta: {
|
||||||
title: 'Cart - libreevent',
|
title: 'Cart - libreevent',
|
||||||
transition: 'scale'
|
transition: 'scale'
|
||||||
@@ -94,7 +102,7 @@ export default [
|
|||||||
{
|
{
|
||||||
path: '/purchase',
|
path: '/purchase',
|
||||||
name: 'purchase',
|
name: 'purchase',
|
||||||
component: () => import( '@/views/PurchaseView.vue' ),
|
component: () => import( '@/views/purchasing/PurchaseView.vue' ),
|
||||||
meta: {
|
meta: {
|
||||||
title: 'Purchase - libreevent',
|
title: 'Purchase - libreevent',
|
||||||
transition: 'scale'
|
transition: 'scale'
|
||||||
@@ -103,21 +111,12 @@ export default [
|
|||||||
{
|
{
|
||||||
path: '/pay',
|
path: '/pay',
|
||||||
name: 'pay',
|
name: 'pay',
|
||||||
component: () => import( '@/views/PaymentView.vue' ),
|
component: () => import( '@/views/purchasing/PaymentView.vue' ),
|
||||||
meta: {
|
meta: {
|
||||||
title: 'Pay - libreevent',
|
title: 'Pay - libreevent',
|
||||||
transition: 'scale',
|
transition: 'scale',
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
|
||||||
path: '/:pathMatch(.*)*',
|
|
||||||
name: 'NotFound',
|
|
||||||
component: () => import( '@/views/404.vue' ),
|
|
||||||
meta: {
|
|
||||||
title: '404 - Page not found :: libreevent',
|
|
||||||
transition: 'scale',
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
path: '/admin/seatplan',
|
path: '/admin/seatplan',
|
||||||
name: 'adminSeatplanEditor',
|
name: 'adminSeatplanEditor',
|
||||||
@@ -136,4 +135,13 @@ export default [
|
|||||||
adminAuthRequired: true,
|
adminAuthRequired: true,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: '/:pathMatch(.*)*',
|
||||||
|
name: 'NotFound',
|
||||||
|
component: () => import( '@/views/404.vue' ),
|
||||||
|
meta: {
|
||||||
|
title: '404 - Page not found :: libreevent',
|
||||||
|
transition: 'scale',
|
||||||
|
}
|
||||||
|
},
|
||||||
]
|
]
|
||||||
@@ -10,7 +10,7 @@
|
|||||||
export default {
|
export default {
|
||||||
path: '/setup',
|
path: '/setup',
|
||||||
name: 'setup',
|
name: 'setup',
|
||||||
component: () => import( '../views/SetupView.vue' ),
|
component: () => import( '../views/setup/SetupView.vue' ),
|
||||||
meta: {
|
meta: {
|
||||||
title: 'Login :: Admin - libreevent',
|
title: 'Login :: Admin - libreevent',
|
||||||
setupAuthRequired: true,
|
setupAuthRequired: true,
|
||||||
|
|||||||
@@ -10,10 +10,12 @@
|
|||||||
import { defineStore } from "pinia";
|
import { defineStore } from "pinia";
|
||||||
|
|
||||||
export const useUserStore = defineStore ( 'user', {
|
export const useUserStore = defineStore ( 'user', {
|
||||||
state: () => ( { 'isUserAuth': true, 'isAdminAuth': true, 'userData': {} } ),
|
state: () => ( { 'isUserAuth': false, 'isAdminAuth': false, 'userData': {}, 'isTwoFACompliantUser': false, 'isTwoFACompliantAdmin': false } ),
|
||||||
getters: {
|
getters: {
|
||||||
getUserAuthenticated: ( state ) => state.isUserAuth,
|
getUserAuthenticated: ( state ) => state.isUserAuth,
|
||||||
getAdminAuthenticated: ( state ) => state.isAdminAuth,
|
getAdminAuthenticated: ( state ) => state.isAdminAuth,
|
||||||
|
getUserTwoFACompliant: ( state ) => state.isTwoFACompliantUser,
|
||||||
|
getAdminTwoFACompliant: ( state ) => state.isTwoFACompliantAdmin,
|
||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
setUserAuth ( auth ) {
|
setUserAuth ( auth ) {
|
||||||
@@ -21,6 +23,12 @@ export const useUserStore = defineStore ( 'user', {
|
|||||||
},
|
},
|
||||||
setAdminAuth ( auth ) {
|
setAdminAuth ( auth ) {
|
||||||
this.isAdminAuth = auth;
|
this.isAdminAuth = auth;
|
||||||
|
},
|
||||||
|
setUser2fa ( auth ) {
|
||||||
|
this.isTwoFACompliantUser = auth;
|
||||||
|
},
|
||||||
|
setAdmin2fa ( auth ) {
|
||||||
|
this.isTwoFACompliantAdmin = auth;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} );
|
} );
|
||||||
@@ -1,84 +0,0 @@
|
|||||||
<!--
|
|
||||||
* libreevent - LoginView.vue
|
|
||||||
*
|
|
||||||
* Created by Janis Hutz 05/14/2023, Licensed under the GPL V3 License
|
|
||||||
* https://janishutz.com, development@janishutz.com
|
|
||||||
*
|
|
||||||
*
|
|
||||||
-->
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<div class="login">
|
|
||||||
<div class="login-app">
|
|
||||||
<h1>Log in</h1>
|
|
||||||
<form>
|
|
||||||
<label for="mail">Email</label><br>
|
|
||||||
<input type="email" v-model="formData[ 'mail' ]" name="mail" id="mail" required><br><br>
|
|
||||||
<label for="password">Password</label><br>
|
|
||||||
<input type="password" v-model="formData[ 'password' ]" name="password" id="password" required>
|
|
||||||
</form>
|
|
||||||
<button @click="login();" class="button">Log in</button>
|
|
||||||
<router-link to="/signup" class="button">Sign up instead</router-link>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import { useUserStore } from '@/stores/userStore';
|
|
||||||
import { mapStores } from 'pinia';
|
|
||||||
|
|
||||||
export default {
|
|
||||||
data () {
|
|
||||||
return {
|
|
||||||
formData: {}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
...mapStores( useUserStore )
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
login () {
|
|
||||||
this.userStore.setUserAuth( true );
|
|
||||||
this.$router.push( sessionStorage.getItem( 'redirect' ) ? sessionStorage.getItem( 'redirect' ) : '/account' );
|
|
||||||
sessionStorage.removeItem( 'redirect' );
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
|
|
||||||
/* TODO: Update colour to image */
|
|
||||||
.login {
|
|
||||||
background-color: green;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
flex-grow: 1;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
flex: 0 1 auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.login-app {
|
|
||||||
background-color: var( --background-color );
|
|
||||||
min-height: fit-content;
|
|
||||||
min-height: fit-content;
|
|
||||||
padding: 5% 20%;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
border-radius: 50px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.button {
|
|
||||||
padding: 5px 10px;
|
|
||||||
margin-top: 2%;
|
|
||||||
}
|
|
||||||
|
|
||||||
nav {
|
|
||||||
display: initial;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
122
src/webapp/src/views/user/LoginView.vue
Normal file
122
src/webapp/src/views/user/LoginView.vue
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
<!--
|
||||||
|
* libreevent - LoginView.vue
|
||||||
|
*
|
||||||
|
* Created by Janis Hutz 05/14/2023, Licensed under the GPL V3 License
|
||||||
|
* https://janishutz.com, development@janishutz.com
|
||||||
|
*
|
||||||
|
*
|
||||||
|
-->
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="login">
|
||||||
|
<div class="login-app">
|
||||||
|
<h1>Log in</h1>
|
||||||
|
<form>
|
||||||
|
<label for="mail">Email</label><br>
|
||||||
|
<input type="email" v-model="formData[ 'mail' ]" name="mail" id="mail" required><br><br>
|
||||||
|
<label for="password">Password</label><br>
|
||||||
|
<input type="password" v-model="formData[ 'password' ]" name="password" id="password" required>
|
||||||
|
</form>
|
||||||
|
<button @click="login();" class="button">Log in</button>
|
||||||
|
<router-link to="/signup" class="button">Sign up instead</router-link>
|
||||||
|
</div>
|
||||||
|
<notifications ref="notification" location="topright" size="bigger"></notifications>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { useUserStore } from '@/stores/userStore';
|
||||||
|
import { mapStores } from 'pinia';
|
||||||
|
import notifications from '@/components/notifications/notifications.vue';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
formData: {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
notifications,
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
...mapStores( useUserStore )
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
login () {
|
||||||
|
if ( this.formData.mail ) {
|
||||||
|
if ( this.formData.password ) {
|
||||||
|
let fetchOptions = {
|
||||||
|
method: 'post',
|
||||||
|
body: JSON.stringify( this.formData ),
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'charset': 'utf-8'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
fetch( localStorage.getItem( 'url' ) + '/user/login', fetchOptions ).then( res => {
|
||||||
|
res.text().then( text => {
|
||||||
|
console.log( text );
|
||||||
|
if ( text === 'ok' ) {
|
||||||
|
this.userStore.setUserAuth( true );
|
||||||
|
this.$router.push( sessionStorage.getItem( 'redirect' ) ? sessionStorage.getItem( 'redirect' ) : '/account' );
|
||||||
|
sessionStorage.removeItem( 'redirect' );
|
||||||
|
} else if ( text === '2fa' ) {
|
||||||
|
this.userStore.setUser2fa( true );
|
||||||
|
this.$router.push( '/twoFactors' );
|
||||||
|
} else {
|
||||||
|
this.$refs.notification.createNotification( 'The credentials you provided do not match our records.', 5, 'error', 'normal' );
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
} );
|
||||||
|
} else {
|
||||||
|
this.$refs.notification.createNotification( 'A password is required to log in', 5, 'error', 'normal' );
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.$refs.notification.createNotification( 'An email address is required to log in', 5, 'error', 'normal' );
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
/* TODO: Update colour to image */
|
||||||
|
.login {
|
||||||
|
background-color: green;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
flex-grow: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
flex: 0 1 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-app {
|
||||||
|
background-color: var( --background-color );
|
||||||
|
min-height: fit-content;
|
||||||
|
min-height: fit-content;
|
||||||
|
padding: 5% 20%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
border-radius: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button {
|
||||||
|
padding: 5px 10px;
|
||||||
|
margin-top: 2%;
|
||||||
|
}
|
||||||
|
|
||||||
|
nav {
|
||||||
|
display: initial;
|
||||||
|
}
|
||||||
|
|
||||||
|
#missing-email, #missing-password, #credentials-wrong {
|
||||||
|
display: none;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
6
src/webapp/src/views/user/TwoFA.vue
Normal file
6
src/webapp/src/views/user/TwoFA.vue
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<template>
|
||||||
|
<div id="2fa">
|
||||||
|
<h1>Two Factor Authentication</h1>
|
||||||
|
<p>We have sent you an email containing a link for Authentication.</p>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
Reference in New Issue
Block a user