elearning/frontend_management/stores/auth.ts

151 lines
5.4 KiB
TypeScript

import { defineStore } from 'pinia';
import { authService } from '~/services/auth.service';
import { userService } from '~/services/user.service';
interface User {
id: string;
email: string;
firstName: string;
lastName: string;
role: 'INSTRUCTOR' | 'ADMIN' | 'STUDENT';
avatarUrl?: string | null;
}
export const useAuthStore = defineStore('auth', {
state: () => ({
user: null as User | null,
token: null as string | null,
isAuthenticated: false
}),
getters: {
isInstructor: (state) => state.user?.role === 'INSTRUCTOR',
isAdmin: (state) => state.user?.role === 'ADMIN',
isStudent: (state) => state.user?.role === 'STUDENT'
},
actions: {
async login(email: string, password: string) {
try {
const response = await authService.login(email, password);
this.token = response.token;
this.user = response.user as User;
this.isAuthenticated = true;
// Save to cookies
const tokenCookie = useCookie('token', {
maxAge: 60 * 60 * 24, // 24 hours
sameSite: 'strict'
});
const refreshTokenCookie = useCookie('refreshToken', {
maxAge: 60 * 60 * 24 * 7, // 7 days
sameSite: 'strict'
});
const userCookie = useCookie('user', {
maxAge: 60 * 60 * 24, // 24 hours
sameSite: 'strict'
});
tokenCookie.value = this.token;
refreshTokenCookie.value = response.refreshToken;
userCookie.value = JSON.stringify(this.user);
return response;
} catch (error: any) {
throw error;
}
},
logout() {
this.user = null;
this.token = null;
this.isAuthenticated = false;
// Clear cookies
const tokenCookie = useCookie('token');
const refreshTokenCookie = useCookie('refreshToken');
const userCookie = useCookie('user');
tokenCookie.value = null;
refreshTokenCookie.value = null;
userCookie.value = null;
},
async checkAuth() {
const tokenCookie = useCookie('token');
const userCookie = useCookie('user');
const refreshTokenCookie = useCookie('refreshToken');
// Case 1: Have token and user - restore auth state
if (tokenCookie.value && userCookie.value) {
this.token = tokenCookie.value;
try {
this.user = typeof userCookie.value === 'string'
? JSON.parse(userCookie.value)
: userCookie.value;
this.isAuthenticated = true;
return;
} catch (e) {
// Invalid user data
this.logout();
}
}
// Case 2: No token but have refresh token - try to refresh
if (!tokenCookie.value && refreshTokenCookie.value && userCookie.value) {
// Get cookie refs with options BEFORE await to maintain Nuxt context
const tokenCookieWithOptions = useCookie('token', {
maxAge: 60 * 60 * 24, // 24 hours
sameSite: 'strict'
});
const refreshTokenCookieWithOptions = useCookie('refreshToken', {
maxAge: 60 * 60 * 24 * 7, // 7 days
sameSite: 'strict'
});
const currentRefreshToken = refreshTokenCookie.value;
try {
console.log('Token missing, attempting refresh...');
const newTokens = await authService.refreshToken(currentRefreshToken);
// Update cookies with new tokens
tokenCookieWithOptions.value = newTokens.token;
refreshTokenCookieWithOptions.value = newTokens.refreshToken;
this.token = newTokens.token;
this.user = typeof userCookie.value === 'string'
? JSON.parse(userCookie.value)
: userCookie.value;
this.isAuthenticated = true;
console.log('Token refreshed successfully');
} catch (e) {
console.error('Token refresh failed');
this.logout();
}
}
},
async fetchUserProfile() {
try {
const response = await userService.getProfile();
// Update local user state
this.user = {
id: response.id.toString(),
email: response.email,
firstName: response.profile.first_name,
lastName: response.profile.last_name,
role: response.role.code as 'INSTRUCTOR' | 'ADMIN' | 'STUDENT',
avatarUrl: response.profile.avatar_url
};
// Update user cookie to keep it in sync
const userCookie = useCookie('user');
userCookie.value = JSON.stringify(this.user);
} catch (error) {
console.error('Failed to fetch user profile:', error);
}
}
}
});