authentication

This commit is contained in:
paola.trabucco
2024-08-07 14:53:43 +02:00
parent ae95f2b4cc
commit e20f7521bb
7 changed files with 134 additions and 24 deletions

20
package-lock.json generated
View File

@@ -10,12 +10,14 @@
"dependencies": {
"@heroicons/vue": "^2.1.5",
"@primevue/themes": "^4.0.0",
"@websanova/vue-auth": "^4.2.1",
"axios": "^1.7.2",
"chart.js": "3.3.2",
"json-editor-vue": "^0.15.1",
"primeicons": "^6.0.1",
"primevue": "^4.0.0",
"vue": "^3.4.34",
"vue-authenticate-2": "^2.2.0",
"vue-markdown-render": "^2.2.1",
"vue-router": "^4.4.0"
},
@@ -1097,7 +1099,6 @@
"cpu": [
"x64"
],
"dev": true,
"optional": true,
"os": [
"linux"
@@ -1300,6 +1301,11 @@
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.34.tgz",
"integrity": "sha512-x5LmiRLpRsd9KTjAB8MPKf0CDPMcuItjP0gbNqFCIgL1I8iYp4zglhj9w9FPCdIbHG2M91RVeIbArFfFTz9I3A=="
},
"node_modules/@websanova/vue-auth": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/@websanova/vue-auth/-/vue-auth-4.2.1.tgz",
"integrity": "sha512-gc4WL3WzJMkj3wZmrBAP7U7WBAcVY0/a/YhCzMVR/iA1u/8QJlugq/320CRRbZ0Acz+qbGPhdm07IRE3U053yg=="
},
"node_modules/acorn": {
"version": "8.12.1",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz",
@@ -4276,6 +4282,18 @@
}
}
},
"node_modules/vue-authenticate-2": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/vue-authenticate-2/-/vue-authenticate-2-2.2.0.tgz",
"integrity": "sha512-4jk9Wv/bV6Bfk6LWQp5WESCe6hxkBrCQThFYqkg9F70q6auEDcdwzo2cVYWPFTwQE5UFX8C9MJUC2Wx6OYwdhw==",
"optionalDependencies": {
"@rollup/rollup-linux-x64-gnu": "^4.9.5"
},
"peerDependencies": {
"axios": "^1.6.7",
"vue": "^3.4.21"
}
},
"node_modules/vue-eslint-parser": {
"version": "9.4.3",
"resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-9.4.3.tgz",

View File

@@ -10,12 +10,14 @@
"dependencies": {
"@heroicons/vue": "^2.1.5",
"@primevue/themes": "^4.0.0",
"@websanova/vue-auth": "^4.2.1",
"axios": "^1.7.2",
"chart.js": "3.3.2",
"json-editor-vue": "^0.15.1",
"primeicons": "^6.0.1",
"primevue": "^4.0.0",
"vue": "^3.4.34",
"vue-authenticate-2": "^2.2.0",
"vue-markdown-render": "^2.2.1",
"vue-router": "^4.4.0"
},

View File

@@ -0,0 +1,21 @@
<template>
<div class="config-panel hidden">
<div class="config-panel-content">
<span class="config-panel-label">Welcome </span>
<span v-if="user">
{{ user.name + " " + user.surname }}
</span>
<button @click="auth.logout()" class="p-button p-button-danger p-button-outlined">Logout</button>
</div>
</div>
</template>
<script setup>
import { useAuth } from '@websanova/vue-auth/src/v3.js';
import { computed } from 'vue';
const auth = useAuth();
const user = computed(() => auth.user());
</script>

View File

@@ -1,6 +1,10 @@
<script setup>
import { useLayout } from '@/layout/composables/layout';
import { useAuth } from '@websanova/vue-auth/src/v3.js';
import AppConfigurator from './AppConfigurator.vue';
import AppProfileMenu from './AppProfileMenu.vue';
const auth = useAuth();
const { onMenuToggle, toggleDarkMode, isDarkTheme } = useLayout();
</script>
@@ -60,18 +64,15 @@ const { onMenuToggle, toggleDarkMode, isDarkTheme } = useLayout();
<div class="layout-topbar-menu hidden lg:block">
<div class="layout-topbar-menu-content">
<button type="button" class="layout-topbar-action">
<i class="pi pi-calendar"></i>
<span>Calendar</span>
</button>
<button type="button" class="layout-topbar-action">
<i class="pi pi-inbox"></i>
<span>Messages</span>
</button>
<button type="button" class="layout-topbar-action">
<i class="pi pi-user"></i>
<span>Profile</span>
<button
v-styleclass="{ selector: '@next', enterFromClass: 'hidden', enterActiveClass: 'animate-scalein', leaveToClass: 'hidden', leaveActiveClass: 'animate-fadeout', hideOnOutsideClick: true }"
type="button"
class="layout-topbar-action "
>
<i class="pi pi-user"></i>
</button>
<AppProfileMenu />
</div>
</div>
</div>

View File

@@ -1,17 +1,45 @@
import { createAuth } from '@websanova/vue-auth';
import driverAuthBearer from '@websanova/vue-auth/dist/drivers/auth/bearer.esm.js';
import driverHttpAxios from '@websanova/vue-auth/dist/drivers/http/axios.1.x.esm.js';
import driverRouterVueRouter from '@websanova/vue-auth/dist/drivers/router/vue-router.2.x.esm.js';
import axios from 'axios';
import { createApp } from 'vue';
import App from './App.vue';
import router from './router';
import PrimeVue from 'primevue/config';
import Aura from '@primevue/themes/aura';
import ToastService from 'primevue/toastservice';
import PrimeVue from 'primevue/config';
import ConfirmationService from 'primevue/confirmationservice';
import ToastService from 'primevue/toastservice';
import BlockViewer from '@/components/BlockViewer.vue';
import '@/assets/styles.scss';
import '@/assets/tailwind.css';
var auth = createAuth({
plugins: {
http: axios,
router: router
},
drivers: {
http: driverHttpAxios,
auth: driverAuthBearer,
router: driverRouterVueRouter
},
options:{
notFoundRedirect: '/auth/login',
authRedirect: '/auth/login',
loginData: {url: 'api/auth/login', method: 'POST', redirect: '/'},
logoutData: {redirect: '/auth/login'},
fetchData: {url: 'api/auth/fetch-user', method: 'GET', enabled: true},
refreshData: {url: 'api/auth/refresh-token', method: 'GET', enabled: true}
}
});
axios.defaults.baseURL = import.meta.env.VITE_BACKEND_URL;
const app = createApp(App);
app.use(router);
@@ -25,6 +53,7 @@ app.use(PrimeVue, {
});
app.use(ToastService);
app.use(ConfirmationService);
app.use(auth);
app.component('BlockViewer', BlockViewer);

View File

@@ -8,6 +8,9 @@ const router = createRouter({
{
path: '/',
component: AppLayout,
meta: {
auth: true
},
children: [
{
path: 'scenario',
@@ -25,6 +28,11 @@ const router = createRouter({
]
}
]
},
{
path: '/auth/login',
name: 'login',
component: () => import('@/views/pages/auth/Login.vue')
}
]
});

View File

@@ -1,36 +1,64 @@
<script setup>
import { useLayout } from '@/layout/composables/layout';
import { useAuth } from '@websanova/vue-auth/src/v3.js';
import Message from 'primevue/message';
import { computed, ref } from 'vue';
const auth = useAuth();
const { isDarkTheme } = useLayout();
const email = ref('');
const username = ref('');
const password = ref('');
const checked = ref(false);
const error = ref('');
const visible = ref(false);
const logoUrl = computed(() => {
return `/layout/images/${isDarkTheme ? 'logo-white' : 'logo-dark'}.svg`;
});
const login = async () => {
console.log('Username: ', username.value);
try {
await auth.login({
data:{
"username":username.value,
"password":password.value
},
redirect:'/',
fetchUser: true,
url: '/api/auth/login'
})
} catch (err) {
console.log( 'Error ' + err)
error.value = 'Incorrect username or password. Please try again.';
visible.value = true;
setTimeout(() => {
visible.value = false;
}, 3500);
}
}
</script>
<template>
<div class="bg-surface-50 dark:bg-surface-950 flex items-center justify-center min-h-screen min-w-[100vw] overflow-hidden">
<div class="flex flex-col items-center justify-center">
<img :src="logoUrl" alt="Sakai logo" class="mb-8 w-24 shrink-0" />
<div style="border-radius: 56px; padding: 0.3rem; background: linear-gradient(180deg, var(--primary-color) 10%, rgba(33, 150, 243, 0) 30%)">
<div class="w-full bg-surface-0 dark:bg-surface-900 py-20 px-8 sm:px-20" style="border-radius: 53px">
<div class="text-center mb-8">
<img src="/demo/images/login/avatar.png" alt="Image" height="50" class="mb-4" />
<div class="text-surface-900 dark:text-surface-0 text-3xl font-medium mb-4">Welcome, Isabel!</div>
<span class="text-surface-600 dark:text-surface-200 font-medium">Sign in to continue</span>
<h1>Welcome to HERMIONE</h1>
</div>
<div>
<label for="email1" class="block text-surface-900 dark:text-surface-0 text-xl font-medium mb-2">Email</label>
<InputText id="email1" type="text" placeholder="Email address" class="w-full md:w-[30rem] mb-8" style="padding: 1rem" v-model="email" />
<label for="email1" class="block text-surface-900 dark:text-surface-0 text-xl font-medium mb-2">Username</label>
<InputText id="email1" type="text" placeholder="Username" class="w-full md:w-[30rem] mb-8" style="padding: 1rem" v-model="username" />
<label for="password1" class="block text-surface-900 dark:text-surface-0 font-medium text-xl mb-2">Password</label>
<Password id="password1" v-model="password" placeholder="Password" :toggleMask="true" class="w-full mb-4" inputClass="w-full" :inputStyle="{ padding: '1rem' }"></Password>
<!--
<div class="flex items-center justify-between mb-8 gap-8">
<div class="flex items-center">
<Checkbox v-model="checked" id="rememberme1" binary class="mr-2"></Checkbox>
@@ -38,7 +66,10 @@ const logoUrl = computed(() => {
</div>
<a class="font-medium no-underline ml-2 text-right cursor-pointer" style="color: var(--primary-color)">Forgot password?</a>
</div>
<Button label="Sign In" class="w-full p-4 text-xl"></Button>
-->
<Button @click="login" label="Sign In" class="w-full p-4 text-xl"></Button>
<Message v-if="visible" severity="error" :life="3000" class="mt-2">{{ error }}</Message>
</div>
</div>
</div>