diff --git a/general/components/Header/AuthLoginModal.vue b/general/components/Header/AuthLoginModal.vue index 0fb89758..ba50869c 100644 --- a/general/components/Header/AuthLoginModal.vue +++ b/general/components/Header/AuthLoginModal.vue @@ -64,6 +64,21 @@ Create an account + @@ -80,6 +95,8 @@ const toastStore = useToastStore(); const authStore = useAuthStore(); const authModalStore = useAuthModalStore(); +const route = useRoute(); + const identifier = ref(''); const password = ref(''); const error = ref(null); @@ -117,8 +134,7 @@ const handleSubmit = async () => { }); if (response.jwt && response.user) { - authStore.setJwt(response.jwt); - authStore.setUserData(response.user); + await authStore.loginAndFetchProfile(response.jwt, response.user); toastStore.addToast('You are logged in.'); hideModal(); } else { @@ -142,5 +158,29 @@ const handleSubmit = async () => { } }; +const connectGithub = () => { + const githubConnectUrl = `${baseURL()}/api/connect/github`; + + authStore.setRedirectLink(route.fullPath); + + window.location.href = githubConnectUrl; +}; + const modalOpen = computed(() => authModalStore.authModal === 'login'); + + diff --git a/general/pages/connect/github.vue b/general/pages/connect/github.vue new file mode 100644 index 00000000..69f9a366 --- /dev/null +++ b/general/pages/connect/github.vue @@ -0,0 +1,135 @@ + + + + + diff --git a/general/stores/auth.ts b/general/stores/auth.ts index 97660a97..51daaf52 100644 --- a/general/stores/auth.ts +++ b/general/stores/auth.ts @@ -1,4 +1,5 @@ import { defineStore } from 'pinia'; +import { useRuntimeConfig } from '#app'; export interface UserData { id: number; @@ -22,6 +23,7 @@ export interface UserData { interface AuthState { jwt: string | null; user: UserData | null; + redirectLink: string | null; } export const useAuthStore = defineStore({ @@ -29,7 +31,8 @@ export const useAuthStore = defineStore({ state: (): AuthState => { return { jwt: null, - user: null + user: null, + redirectLink: null }; }, actions: { @@ -39,9 +42,56 @@ export const useAuthStore = defineStore({ setUserData(user: UserData) { this.user = user; }, + setRedirectLink(link: string) { + this.redirectLink = link; + }, + clearRedirectLink() { + this.redirectLink = null; + }, + async fetchFullProfile() { + if (!this.jwt) { + throw new Error('No JWT token available'); + } + + const runtimeConfig = useRuntimeConfig(); + const baseURL = + typeof window !== 'undefined' + ? window.location.origin + `${runtimeConfig.public.strapiBasePath}` + : `${runtimeConfig.public.strapiBaseUrl}`; + + try { + const response = await $fetch( + `${baseURL}/api/users/me?populate=role`, + { + method: 'GET', + headers: { + Authorization: `Bearer ${this.jwt}` + } + } + ); + + if (response) { + this.setUserData(response); + } else { + throw new Error('Invalid response from server'); + } + } catch (error) { + console.error('Error fetching full profile:', error); + throw error; + } + }, + async loginAndFetchProfile( + jwt: string, + initialUserData: Partial + ) { + this.setJwt(jwt); + this.setUserData({ ...initialUserData } as UserData); + await this.fetchFullProfile(); + }, clear() { this.jwt = null; this.user = null; + this.redirectLink = null; } }, persist: { @@ -49,7 +99,7 @@ export const useAuthStore = defineStore({ const runtimeConfig = useRuntimeConfig(); return `ontoviewer-auth-${runtimeConfig.public.ontologyName}`; }, - storage: process.client ? localStorage : undefined, - paths: ['jwt', 'user'] + storage: import.meta.client ? localStorage : undefined, + paths: ['jwt', 'user', 'redirectLink'] } });