authentication
This commit is contained in:
20
package-lock.json
generated
20
package-lock.json
generated
@@ -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",
|
||||
|
||||
@@ -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"
|
||||
},
|
||||
|
||||
21
src/layout/AppProfileMenu.vue
Normal file
21
src/layout/AppProfileMenu.vue
Normal 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>
|
||||
@@ -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>
|
||||
|
||||
33
src/main.js
33
src/main.js
@@ -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);
|
||||
|
||||
|
||||
@@ -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')
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user