This commit is contained in:
2025-04-24 16:23:06 +02:00
6 changed files with 1706 additions and 751 deletions

2127
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -8,6 +8,7 @@
"lint": "eslint --fix . --ext .vue,.js,.jsx,.cjs,.mjs --fix --ignore-path .gitignore"
},
"dependencies": {
"@azure/msal-browser": "^4.9.1",
"@heroicons/vue": "^2.2.0",
"@matpool/vue-json-view": "^0.1.8",
"@primevue/themes": "^4.0.0",

View File

@@ -2,67 +2,72 @@ import AppLayout from '@/layout/AppLayout.vue';
import { createRouter, createWebHistory } from 'vue-router';
const router = createRouter({
history: createWebHistory(),
routes: [
{
path: '/',
component: AppLayout,
meta: {
auth: true
},
children: [
history: createWebHistory(),
routes: [
{
path: '/projects',
name: 'projects-list',
component: () => import('@/views/pages/ProjectList.vue')
path: '/',
component: AppLayout,
meta: {
auth: true
},
children: [
{
path: '/projects',
name: 'projects-list',
component: () => import('@/views/pages/ProjectList.vue')
},
{
path: '/',
name: 'dashboard',
component: () => import('@/views/pages/ksDocuments/KsDocuments.vue')
},
{
path: '/ksdocuments',
children: [
{ path: '', name: 'ks-document', component: () => import('@/views/pages/ksDocuments/KsDocuments.vue') },
{ path: 'new', name: 'ks-document-new', component: () => import('@/views/pages/ksDocuments/KsNewDocumentForm.vue') }
]
},
{
path: '/ks_git_repos',
children: [
{ path: '', name: 'ks-git-repos', component: () => import('@/views/pages/ksGitRepo/KsGitRepos.vue') },
//{path: 'new', name: 'ks-git-repo-new', component: () => import('@/views/pages/ksGitRepo/KsNewGitRepoForm.vue')},
//{path: '/clone', name: 'ks-git-clone-repo', component: () => import('@/views/pages/ksGitRepo/KsGitCloneRepoForm.vue')},
{ path: 'ks_code_parser', name: 'ks_code_parser', component: () => import('@/views/pages/ksGitRepo/ksCodeParser/KsGitCodeParser.vue') }
]
},
{
path: '/ks_similarity_search',
children: [{ path: '', name: 'ks_similarity_search', component: () => import('@/views/pages/similaritySearch/KsSimilaritySearch.vue') }]
},
{
path: '/ks_vector_data',
children: [{ path: '', name: 'ks_vector_data', component: () => import('@/views/pages/vectorDBSearch/KsVectorData.vue') }]
},
{
path: '/kstexts',
children: [{ path: '', name: 'ks-texts', component: () => import('@/views/pages/KsTexts.vue') }]
}
]
},
{
path: '/',
name: 'dashboard',
component: () => import('@/views/pages/ksDocuments/KsDocuments.vue')
path: '/auth/login',
name: 'login',
meta: {
auth: false
},
component: () => import('@/views/pages/auth/Login.vue')
},
{
path: '/ksdocuments',
children: [
{path: '', name: 'ks-document', component: () => import('@/views/pages/ksDocuments/KsDocuments.vue')},
{path: 'new', name: 'ks-document-new', component: () => import('@/views/pages/ksDocuments/KsNewDocumentForm.vue')},
]
},
{
path: '/ks_git_repos',
children: [
{path: '', name: 'ks-git-repos', component: () => import('@/views/pages/ksGitRepo/KsGitRepos.vue')},
//{path: 'new', name: 'ks-git-repo-new', component: () => import('@/views/pages/ksGitRepo/KsNewGitRepoForm.vue')},
//{path: '/clone', name: 'ks-git-clone-repo', component: () => import('@/views/pages/ksGitRepo/KsGitCloneRepoForm.vue')},
{path: 'ks_code_parser', name: 'ks_code_parser', component: () => import('@/views/pages/ksGitRepo/ksCodeParser/KsGitCodeParser.vue')}
]
},
{
path: '/ks_similarity_search',
children: [
{path: '', name: 'ks_similarity_search', component: () => import('@/views/pages/similaritySearch/KsSimilaritySearch.vue')},
]
},
{
path: '/ks_vector_data',
children: [
{path: '', name: 'ks_vector_data', component: () => import('@/views/pages/vectorDBSearch/KsVectorData.vue')},
]
},
{
path: '/kstexts',
children: [
{path: '', name: 'ks-texts', component: () => import('@/views/pages/KsTexts.vue')},
]
},
]
},
{
path: '/auth/login',
name: 'login',
component: () => import('@/views/pages/auth/Login.vue')
},
]
path: '/auth/callback',
name: 'test',
meta: {
auth: false
},
component: () => import('@/views/pages/auth/Callback.vue')
}
]
});
export default router;
export default router;

View File

@@ -0,0 +1,66 @@
<script setup>
import { useAuth } from '@websanova/vue-auth/src/v3.js';
import axios from 'axios';
import { onMounted, ref } from 'vue';
import { useRouter } from 'vue-router';
import { msalInstance } from './MsalConfig'; // wherever you created your MSAL instance
const router = useRouter()
const auth = useAuth();
const message = ref('')
onMounted(async () => {
console.log("Mounted on callback")
await msalInstance.initialize()
console.log("After initialize on callback")
const response = await msalInstance.handleRedirectPromise()
console.log("Response:",response)
if (response) {
message.value ="Logging in to the application..."
localStorage.setItem('msalUser', JSON.stringify(response.account))
axios.post("/msauth/exchange",{}, {
headers: { Authorization: `Bearer ${response.accessToken}` }
}).then(res=>{
if(res.data.token){
auth.token(null,res.data.token,false);
auth.fetch().then(response=>{
console.log("1 user :" , response.data.data);
if (!response.data.data.selectedProject) {
router.push({ name: 'projects-list' });
} else {
router.push({ name: 'ks-document' });
}
}).catch(res=>{
console.log("Error on token exchange:",res)
message.value = "Error authenticating on the application. Did you ask for authorization?"
visible.value = true;
});
}else{
message.value = "Error authenticating on the application. Did you ask for authorization?"
console.error("No token exchange with backend")
}
}).catch(res=>{
console.log(res.data)
message.value = "Error authenticating on the application. Did you ask for authorization?"
});
}
})
</script>
<template>
<div>{{message}}</div>
</template>

View File

@@ -1,7 +1,10 @@
<script setup>
import { useLayout } from '@/layout/composables/layout';
import { useAuth } from '@websanova/vue-auth/src/v3.js';
import { computed, ref } from 'vue';
import axios from 'axios';
import Message from 'primevue/message';
import { onMounted,computed, ref } from 'vue';
import { msalInstance, msalrequest } from './MsalConfig';
import { useRouter } from 'vue-router';
//import logo from '@/assets/Logo_Apollo_Transparent.png';
import logo from '@/assets/apollo.jpg';
@@ -19,7 +22,80 @@ const logoUrl = computed(() => {
return `/layout/images/${isDarkTheme ? 'logo-white' : 'logo-dark'}.svg`;
});
const login = async () => {
const msaccount = ref(null);
onMounted(async () => {
await msalInstance.initialize()
const accounts = msalInstance.getAllAccounts()
console.log("Accounts:",accounts)
if (accounts.length > 0) {
console.log(accounts)
msaccount.value= accounts[0]
}
})
const loginAD = async () => {
var token = await msalInstance.acquireTokenSilent({
scopes: msalrequest.scopes,
account: msaccount.value
})
console.log("Token " ,token)
axios.post("/msauth/exchange",{}, {
headers: { Authorization: `Bearer ${token.accessToken}` }
}).then(res=>{
console.log("Token exhange done :",res.data.token)
if(res.data.token){
auth.token(null, res.data.token,false)
auth.fetch().then(response=>{
console.log("1 user :" , response.data.data);
if (!response.data.data.selectedProject) {
router.push({ name: 'projects-list' });
} else {
router.push({ name: 'ks-document' });
}
console.log("response", response);
}).catch(res=>{
console.log("Error on token exchange:",res)
error.value = "Error authenticating on the application. Did you ask for authorization?"
visible.value = true;
});
}else{
error.value = "Error authenticating on the application. Did you ask for authorization?"
visible.value = true;
console.error("No token exchange with backend")
}
}).catch(res=>{
console.log("Error on token exchange:",res)
error.value = "Error authenticating on the application. Did you ask for authorization?"
visible.value = true;
});
}
const loginMsal = async () => {
await msalInstance.initialize()
msalInstance.loginRedirect(msalrequest)
}
const logoutAD = async () => {
const logoutRequest = {
account: msaccount.value,
mainWindowRedirectUri:window.location.href,
};
await msalInstance.logoutPopup(logoutRequest);
}
const login_old = async () => {
try {
await auth.login({
data:{
@@ -33,7 +109,7 @@ const login = async () => {
if (!response.data.data.selectedProject) {
router.push({ name: 'projects-list' });
} else {
router.push({ name: 'ksdocuments' });
router.push({ name: 'ks-document' });
}
console.log("response", response);
@@ -79,8 +155,8 @@ const login = async () => {
<h1>Welcome to</h1>
<h1>WizardAI - KNOWLEDGE</h1>
</div>
<div>
<!-- Username & Password Section -->
<div class="mb-10 w-full max-w-xl">
<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" />
@@ -95,15 +171,35 @@ const login = async () => {
<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" @click="login" class="w-full p-4 text-xl"></Button>
<Button @click="login_old" label="Sign In with Username and Password" class="w-full p-4 text-xl"></Button>
</div>
<!-- Divider -->
<div class="my-6 w-full max-w-xl flex items-center justify-center">
<hr class="flex-grow border-t border-gray-300 dark:border-gray-700" />
<span class="mx-4 text-gray-500 dark:text-gray-400">Sign in with Microsoft Azure AD</span>
<hr class="flex-grow border-t border-gray-300 dark:border-gray-700" />
</div>
<Message v-if="visible" severity="error" :life="3000" class="mt-2 error-message">{{ error }}</Message>
<!-- Azure AD Section -->
<div class="w-full max-w-xl">
<Button @click="loginMsal" v-if="msaccount == null" label="Sign In with Microsoft AD"
class="w-full text-l mb-4" />
<Button @click="loginAD" v-if="msaccount" :label="'Login ' + msaccount.username"
class="w-full text-l mb-4" />
<Button @click="logoutAD" v-if="msaccount" label="Logout AD" severity="warn"
class="w-full text-l mb-4" />
</div>
<!-- Error Message -->
<Message v-if="visible" severity="error" :life="5000" class="mt-4 error-message">{{ error }}</Message>
</div>
</div>
</div>
</div>
</div>
</template>
<style scoped>

View File

@@ -0,0 +1,32 @@
import { PublicClientApplication } from '@azure/msal-browser';
export const msalInstance = new PublicClientApplication({
auth: {
clientId: '1ddbd871-9544-4a31-97a4-2968ce08e49a', //'d3fee0e3-49e0-4910-b0b4-805bfbd5488a',
authority: 'https://login.microsoftonline.com/e0793d39-0939-496d-b129-198edd916feb/', //'https://login.microsoftonline.com/9dc4721e-4d54-4c40-a681-1dd740292901/', //
redirectUri: 'http://localhost:5173/auth/callback', // or your deployed URL
navigateToLoginRequestUrl: false
},
cache: {
cacheLocation: 'localStorage',
storeAuthStateInCookie: false
}
});
/*
export const msalInstance = new PublicClientApplication({
auth: {
clientId: 'd3fee0e3-49e0-4910-b0b4-805bfbd5488a',
authority: "https://login.microsoftonline.com/9dc4721e-4d54-4c40-a681-1dd740292901",
redirectUri: "http://localhost:5173/auth/callback", // or your deployed URL
navigateToLoginRequestUrl: false,
},
cache: {
cacheLocation: "localStorage",
storeAuthStateInCookie: false,
}
})
*/
export const msalrequest = {
scopes: ['1ddbd871-9544-4a31-97a4-2968ce08e49a/.default'] //['api://d3fee0e3-49e0-4910-b0b4-805bfbd5488a/access_as_user']
};