feat: Implement user authentication, admin user management, and role-based access control.
This commit is contained in:
parent
8a2ca592bc
commit
38648581ec
19 changed files with 1762 additions and 514 deletions
|
|
@ -41,14 +41,72 @@ export interface LoginResponse {
|
|||
user: {
|
||||
id: string;
|
||||
email: string;
|
||||
fullName: string;
|
||||
firstName: string;
|
||||
lastName: string;
|
||||
role: string;
|
||||
};
|
||||
}
|
||||
|
||||
// Mock data for development
|
||||
const MOCK_USERS = [
|
||||
{
|
||||
email: 'admin@elearning.local',
|
||||
password: 'password',
|
||||
user: {
|
||||
id: '1',
|
||||
email: 'admin@elearning.local',
|
||||
firstName: 'ผู้ดูแล',
|
||||
lastName: 'ระบบ',
|
||||
role: 'ADMIN'
|
||||
}
|
||||
},
|
||||
{
|
||||
email: 'instructor@elearning.local',
|
||||
password: 'password',
|
||||
user: {
|
||||
id: '2',
|
||||
email: 'instructor@elearning.local',
|
||||
firstName: 'อาจารย์',
|
||||
lastName: 'ทดสอบ',
|
||||
role: 'INSTRUCTOR'
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
export const authService = {
|
||||
async login(email: string, password: string): Promise<LoginResponse> {
|
||||
const config = useRuntimeConfig();
|
||||
const useMockData = config.public.useMockData as boolean;
|
||||
|
||||
// Use Mock Data
|
||||
if (useMockData) {
|
||||
return this.mockLogin(email, password);
|
||||
}
|
||||
|
||||
// Use Real API
|
||||
return this.apiLogin(email, password);
|
||||
},
|
||||
|
||||
// Mock login for development
|
||||
async mockLogin(email: string, password: string): Promise<LoginResponse> {
|
||||
await new Promise(resolve => setTimeout(resolve, 500)); // Simulate delay
|
||||
|
||||
const mockUser = MOCK_USERS.find(u => u.email === email);
|
||||
|
||||
if (!mockUser || mockUser.password !== password) {
|
||||
throw new Error('อีเมลหรือรหัสผ่านไม่ถูกต้อง');
|
||||
}
|
||||
|
||||
return {
|
||||
token: 'mock-jwt-token',
|
||||
refreshToken: 'mock-refresh-token',
|
||||
user: mockUser.user
|
||||
};
|
||||
},
|
||||
|
||||
// Real API login
|
||||
async apiLogin(email: string, password: string): Promise<LoginResponse> {
|
||||
const config = useRuntimeConfig();
|
||||
|
||||
try {
|
||||
const response = await $fetch<ApiLoginResponse>('/api/auth/login', {
|
||||
|
|
@ -60,6 +118,11 @@ export const authService = {
|
|||
}
|
||||
});
|
||||
|
||||
// Check if user role is STUDENT - block login
|
||||
if (response.user.role.code === 'STUDENT') {
|
||||
throw new Error('ไม่สามารถเข้าสู่ระบบได้ ระบบนี้สำหรับผู้สอนและผู้ดูแลระบบเท่านั้น');
|
||||
}
|
||||
|
||||
// Transform API response to frontend format
|
||||
return {
|
||||
token: response.token,
|
||||
|
|
@ -67,26 +130,68 @@ export const authService = {
|
|||
user: {
|
||||
id: response.user.id.toString(),
|
||||
email: response.user.email,
|
||||
fullName: `${response.user.profile.first_name} ${response.user.profile.last_name}`,
|
||||
role: response.user.role.code // Use role.code (ADMIN, INSTRUCTOR, etc.)
|
||||
firstName: response.user.profile.first_name,
|
||||
lastName: response.user.profile.last_name,
|
||||
role: response.user.role.code
|
||||
}
|
||||
};
|
||||
} catch (error: any) {
|
||||
// Re-throw custom errors (like STUDENT role block)
|
||||
if (error.message && !error.response) {
|
||||
throw error;
|
||||
}
|
||||
// Handle API errors
|
||||
if (error.response?.status === 401) {
|
||||
throw new Error('Invalid credentials');
|
||||
throw new Error('อีเมลหรือรหัสผ่านไม่ถูกต้อง');
|
||||
}
|
||||
throw new Error('Login failed');
|
||||
throw new Error('เกิดข้อผิดพลาดในการเข้าสู่ระบบ');
|
||||
}
|
||||
},
|
||||
|
||||
async logout(): Promise<void> {
|
||||
// TODO: Call logout API if available
|
||||
// For now, just clear local storage
|
||||
if (process.client) {
|
||||
localStorage.removeItem('token');
|
||||
localStorage.removeItem('refreshToken');
|
||||
localStorage.removeItem('user');
|
||||
// Clear cookies
|
||||
const tokenCookie = useCookie('token');
|
||||
const refreshTokenCookie = useCookie('refreshToken');
|
||||
const userCookie = useCookie('user');
|
||||
|
||||
tokenCookie.value = null;
|
||||
refreshTokenCookie.value = null;
|
||||
userCookie.value = null;
|
||||
},
|
||||
|
||||
async forgotPassword(email: string): Promise<void> {
|
||||
const config = useRuntimeConfig();
|
||||
const useMockData = config.public.useMockData as boolean;
|
||||
|
||||
if (useMockData) {
|
||||
// Mock: simulate sending email
|
||||
await new Promise(resolve => setTimeout(resolve, 1000));
|
||||
return;
|
||||
}
|
||||
|
||||
// Real API
|
||||
await $fetch('/api/auth/reset-request', {
|
||||
method: 'POST',
|
||||
baseURL: config.public.apiBaseUrl as string,
|
||||
body: { email }
|
||||
});
|
||||
},
|
||||
|
||||
async resetPassword(token: string, password: string): Promise<void> {
|
||||
const config = useRuntimeConfig();
|
||||
const useMockData = config.public.useMockData as boolean;
|
||||
|
||||
if (useMockData) {
|
||||
// Mock: simulate reset password
|
||||
await new Promise(resolve => setTimeout(resolve, 1000));
|
||||
return;
|
||||
}
|
||||
|
||||
// Real API
|
||||
await $fetch('/api/auth/reset-password', {
|
||||
method: 'POST',
|
||||
baseURL: config.public.apiBaseUrl as string,
|
||||
body: { token, password }
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue