integrate login page wih api and keycloak
This commit is contained in:
@@ -0,0 +1,89 @@
|
||||
// composables/useAuth.ts
|
||||
import { computed, ref } from 'vue';
|
||||
import type { SessionData as UserSession, LogoutResponse } from '~/types/auth';
|
||||
|
||||
|
||||
const sessionData = ref<UserSession | null>(null);
|
||||
const isLoggedIn = ref(false);
|
||||
const isLoading = ref(false);
|
||||
|
||||
const clearLocalAuthStorage = () => {
|
||||
if (!process.client) return;
|
||||
|
||||
localStorage.removeItem('accessToken');
|
||||
localStorage.removeItem('refreshToken');
|
||||
localStorage.removeItem('user-preferences');
|
||||
localStorage.removeItem('app-state');
|
||||
sessionStorage.clear();
|
||||
};
|
||||
|
||||
export const useAuth = () => {
|
||||
const fetchUserSession = async () => {
|
||||
isLoading.value = true;
|
||||
|
||||
try {
|
||||
const response = await $fetch<UserSession>('/api/auth/sessionUser', {
|
||||
method: 'GET',
|
||||
});
|
||||
|
||||
sessionData.value = response;
|
||||
isLoggedIn.value = !!response;
|
||||
} catch {
|
||||
sessionData.value = null;
|
||||
isLoggedIn.value = false;
|
||||
} finally {
|
||||
isLoading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
const logout = async (): Promise<void> => {
|
||||
try {
|
||||
await $fetch<LogoutResponse>('/api/auth/logout', {
|
||||
method: 'POST',
|
||||
});
|
||||
} finally {
|
||||
clearLocalAuthStorage();
|
||||
sessionData.value = null;
|
||||
isLoggedIn.value = false;
|
||||
await navigateTo('/auth/login?logout=success');
|
||||
}
|
||||
};
|
||||
|
||||
const fullLogout = async (): Promise<void> => {
|
||||
try {
|
||||
const response = await $fetch<LogoutResponse>('/api/auth/logout', {
|
||||
method: 'POST',
|
||||
});
|
||||
|
||||
clearLocalAuthStorage();
|
||||
sessionData.value = null;
|
||||
isLoggedIn.value = false;
|
||||
|
||||
if (process.client && response?.success && response?.logoutUrl) {
|
||||
window.location.href = response.logoutUrl;
|
||||
return;
|
||||
}
|
||||
|
||||
await navigateTo('/auth/login?logout=full');
|
||||
} catch {
|
||||
clearLocalAuthStorage();
|
||||
sessionData.value = null;
|
||||
isLoggedIn.value = false;
|
||||
await navigateTo('/auth/login?logout=full');
|
||||
}
|
||||
};
|
||||
|
||||
const user = computed(() => sessionData.value?.user ?? null);
|
||||
const userRoles = computed(() => sessionData.value?.user?.role ?? []);
|
||||
|
||||
return {
|
||||
isLoggedIn,
|
||||
isLoading,
|
||||
sessionData,
|
||||
user,
|
||||
userRoles,
|
||||
fetchUserSession,
|
||||
logout,
|
||||
fullLogout,
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,49 @@
|
||||
import { ref } from 'vue';
|
||||
import api from '~/utils/api';
|
||||
import type { AuthInfoResponse } from '~/types/auth';
|
||||
|
||||
const authInfo = ref<AuthInfoResponse | null>(null);
|
||||
const isLoading = ref(false);
|
||||
const errorMessage = ref<string | null>(null);
|
||||
|
||||
export const useAuthInfo = () => {
|
||||
const fetchAuthInfo = async (accessToken: string) => {
|
||||
if (!accessToken || !accessToken.trim()) {
|
||||
throw new Error('accessToken is required');
|
||||
}
|
||||
|
||||
isLoading.value = true;
|
||||
errorMessage.value = null;
|
||||
|
||||
try {
|
||||
const response = await api.get<AuthInfoResponse>('/api/v1/auth/info', {
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: `Bearer ${accessToken}`,
|
||||
},
|
||||
});
|
||||
|
||||
authInfo.value = response.data;
|
||||
return response.data;
|
||||
} catch (error) {
|
||||
authInfo.value = null;
|
||||
errorMessage.value = error instanceof Error ? error.message : 'Failed to fetch auth info';
|
||||
throw error;
|
||||
} finally {
|
||||
isLoading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
const clearAuthInfo = () => {
|
||||
authInfo.value = null;
|
||||
errorMessage.value = null;
|
||||
};
|
||||
|
||||
return {
|
||||
authInfo,
|
||||
isLoading,
|
||||
errorMessage,
|
||||
fetchAuthInfo,
|
||||
clearAuthInfo,
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user