Spaces:
Sleeping
Sleeping
| import { txasupabase } from '../../../lib/txasupabase.js'; | |
| export const POST = async ({ request, cookies }) => { | |
| try { | |
| // 1. Kiểm tra quyền Admin bảo mật | |
| const token = cookies.get('auth_token')?.value; | |
| let currentUser = null; | |
| if (token) { | |
| try { | |
| currentUser = JSON.parse(Buffer.from(token, 'base64').toString('utf-8')); | |
| } catch (e) {} | |
| } | |
| if (!currentUser || currentUser.role !== 'admin') { | |
| return new Response(JSON.stringify({ error: 'Bạn không có quyền quản trị!' }), { | |
| status: 403, | |
| headers: { 'Content-Type': 'application/json' } | |
| }); | |
| } | |
| const body = await request.json(); | |
| const { username, usernames, action, role, email, password, province, ward, avatar_url } = body; | |
| if (!action) { | |
| return new Response(JSON.stringify({ error: 'Thiếu thông tin hành động (action)!' }), { | |
| status: 400, | |
| headers: { 'Content-Type': 'application/json' } | |
| }); | |
| } | |
| // --- HÀNH ĐỘNG 1: THÊM MỚI NGƯỜI DÙNG (CREATE) --- | |
| if (action === 'create') { | |
| if (!username || !email || !password) { | |
| return new Response(JSON.stringify({ error: 'Vui lòng cung cấp đầy đủ Tài khoản, Email và Mật khẩu!' }), { | |
| status: 400, | |
| headers: { 'Content-Type': 'application/json' } | |
| }); | |
| } | |
| const cleanUsername = username.trim(); | |
| const cleanEmail = email.trim(); | |
| // Kiểm tra xem tên đăng nhập đã tồn tại chưa | |
| const existingUser = await txasupabase.getUserByUsername(cleanUsername); | |
| if (existingUser) { | |
| return new Response(JSON.stringify({ error: 'Tên tài khoản này đã tồn tại trên hệ thống!' }), { | |
| status: 400, | |
| headers: { 'Content-Type': 'application/json' } | |
| }); | |
| } | |
| // Kiểm tra xem email đã được sử dụng chưa | |
| const { data: existingEmail } = await txasupabase.supabase | |
| .from('users') | |
| .select('username') | |
| .eq('email', cleanEmail) | |
| .maybeSingle(); | |
| if (existingEmail) { | |
| return new Response(JSON.stringify({ error: 'Địa chỉ Email này đã được đăng ký cho tài khoản khác!' }), { | |
| status: 400, | |
| headers: { 'Content-Type': 'application/json' } | |
| }); | |
| } | |
| const defaultAvatar = txasupabase.getGravatarUrl(cleanEmail); | |
| const { data, error } = await txasupabase.supabase | |
| .from('users') | |
| .insert({ | |
| username: cleanUsername, | |
| email: cleanEmail, | |
| password: password, | |
| province: province || '', | |
| ward: ward || '', | |
| role: role || 'user', | |
| avatar_url: avatar_url || defaultAvatar, | |
| favorites: [], | |
| history: [], | |
| created_at: new Date().toISOString() | |
| }) | |
| .select() | |
| .single(); | |
| if (error) throw error; | |
| // Ghi log hoạt động | |
| await txasupabase.supabase.from('logs').insert({ | |
| action: 'user_created', | |
| level: 'info', | |
| message: `Admin "${currentUser.username}" đã tạo mới tài khoản "${cleanUsername}" với quyền "${role || 'user'}"`, | |
| details: JSON.stringify({ username: cleanUsername, role: role || 'user', created_by: currentUser.username }) | |
| }); | |
| return new Response(JSON.stringify({ | |
| success: true, | |
| message: `Đã tạo tài khoản "${cleanUsername}" thành công!`, | |
| user: data | |
| }), { | |
| status: 200, | |
| headers: { 'Content-Type': 'application/json' } | |
| }); | |
| } | |
| // --- HÀNH ĐỘNG 2: CHỈNH SỬA THÔNG TIN NGƯỜI DÙNG (UPDATE) --- | |
| if (action === 'update') { | |
| if (!username) { | |
| return new Response(JSON.stringify({ error: 'Thiếu Tên tài khoản cần cập nhật!' }), { | |
| status: 400, | |
| headers: { 'Content-Type': 'application/json' } | |
| }); | |
| } | |
| // Chặn Admin tự hạ quyền của chính mình khi cập nhật | |
| if (username === currentUser.username && role === 'user') { | |
| return new Response(JSON.stringify({ error: 'Bạn không thể tự hạ quyền quản trị của chính mình!' }), { | |
| status: 400, | |
| headers: { 'Content-Type': 'application/json' } | |
| }); | |
| } | |
| // Kiểm tra trùng lặp email nếu email bị thay đổi | |
| if (email) { | |
| const cleanEmail = email.trim(); | |
| const { data: dupEmail } = await txasupabase.supabase | |
| .from('users') | |
| .select('username') | |
| .eq('email', cleanEmail) | |
| .neq('username', username) | |
| .maybeSingle(); | |
| if (dupEmail) { | |
| return new Response(JSON.stringify({ error: 'Địa chỉ Email này đã được sử dụng bởi tài khoản khác!' }), { | |
| status: 400, | |
| headers: { 'Content-Type': 'application/json' } | |
| }); | |
| } | |
| } | |
| const updateData = { | |
| email: email ? email.trim() : undefined, | |
| province: province !== undefined ? province : undefined, | |
| ward: ward !== undefined ? ward : undefined, | |
| role: role !== undefined ? role : undefined, | |
| avatar_url: avatar_url !== undefined ? avatar_url : undefined | |
| }; | |
| // Chỉ cập nhật mật khẩu mới nếu được điền | |
| if (password && password.trim() !== '') { | |
| updateData.password = password; | |
| } | |
| // Loại bỏ các trường undefined để tránh ghi đè null vô lý | |
| Object.keys(updateData).forEach(key => updateData[key] === undefined && delete updateData[key]); | |
| const { data, error } = await txasupabase.supabase | |
| .from('users') | |
| .update(updateData) | |
| .eq('username', username) | |
| .select() | |
| .single(); | |
| if (error) throw error; | |
| // Ghi log hoạt động | |
| await txasupabase.supabase.from('logs').insert({ | |
| action: 'user_updated', | |
| level: 'info', | |
| message: `Admin "${currentUser.username}" đã cập nhật thông tin tài khoản "${username}"`, | |
| details: JSON.stringify({ username, updated_fields: Object.keys(updateData), updated_by: currentUser.username }) | |
| }); | |
| return new Response(JSON.stringify({ | |
| success: true, | |
| message: `Đã cập nhật thông tin tài khoản "${username}" thành công!`, | |
| user: data | |
| }), { | |
| status: 200, | |
| headers: { 'Content-Type': 'application/json' } | |
| }); | |
| } | |
| // --- HÀNH ĐỘNG 3: ĐỔI VAI TRÒ NHANH (CHANGE ROLE) --- | |
| if (action === 'change_role') { | |
| if ((!username && !usernames) || !role) { | |
| return new Response(JSON.stringify({ error: 'Thiếu thông tin người dùng hoặc vai trò!' }), { | |
| status: 400, | |
| headers: { 'Content-Type': 'application/json' } | |
| }); | |
| } | |
| const userList = usernames ? usernames : [username]; | |
| // Ngăn không cho admin tự hạ quyền của chính mình | |
| if (userList.includes(currentUser.username)) { | |
| return new Response(JSON.stringify({ error: 'Bạn không thể tự hạ quyền hoặc thay đổi vai trò của chính mình!' }), { | |
| status: 400, | |
| headers: { 'Content-Type': 'application/json' } | |
| }); | |
| } | |
| const { error } = await txasupabase.supabase | |
| .from('users') | |
| .update({ role: role }) | |
| .in('username', userList); | |
| if (error) throw error; | |
| await txasupabase.supabase.from('logs').insert({ | |
| action: 'user_role_changed_bulk', | |
| level: 'info', | |
| message: `Admin "${currentUser.username}" đã đổi quyền của ${userList.length} tài khoản thành "${role}"`, | |
| details: JSON.stringify({ usernames: userList, new_role: role, changed_by: currentUser.username }) | |
| }); | |
| return new Response(JSON.stringify({ | |
| success: true, | |
| message: `Đã chuyển đổi quyền của ${userList.length} tài khoản thành công!` | |
| }), { | |
| status: 200, | |
| headers: { 'Content-Type': 'application/json' } | |
| }); | |
| } | |
| // --- HÀNH ĐỘNG 4: XÓA TÀI KHOẢN (DELETE & BULK DELETE) --- | |
| if (action === 'delete') { | |
| const userList = usernames ? usernames : [username]; | |
| // Ngăn không cho admin tự xóa chính mình | |
| const cleanUserList = userList.filter(u => u !== currentUser.username); | |
| if (cleanUserList.length === 0) { | |
| return new Response(JSON.stringify({ error: 'Không thể tự xóa tài khoản quản trị của chính bạn!' }), { | |
| status: 400, | |
| headers: { 'Content-Type': 'application/json' } | |
| }); | |
| } | |
| const { error } = await txasupabase.supabase | |
| .from('users') | |
| .delete() | |
| .in('username', cleanUserList); | |
| if (error) throw error; | |
| await txasupabase.supabase.from('logs').insert({ | |
| action: 'user_deleted_bulk', | |
| level: 'warn', | |
| message: `Admin "${currentUser.username}" đã xóa đồng loạt ${cleanUserList.length} tài khoản người dùng`, | |
| details: JSON.stringify({ deleted_usernames: cleanUserList, deleted_by: currentUser.username }) | |
| }); | |
| return new Response(JSON.stringify({ | |
| success: true, | |
| message: `Đã xóa thành công ${cleanUserList.length} tài khoản người dùng!` | |
| }), { | |
| status: 200, | |
| headers: { 'Content-Type': 'application/json' } | |
| }); | |
| } | |
| return new Response(JSON.stringify({ error: 'Hành động không hợp lệ!' }), { | |
| status: 400, | |
| headers: { 'Content-Type': 'application/json' } | |
| }); | |
| } catch (err) { | |
| console.error('Error handling admin user management API:', err); | |
| return new Response(JSON.stringify({ error: err.message || 'Có lỗi xảy ra trên hệ thống!' }), { | |
| status: 500, | |
| headers: { 'Content-Type': 'application/json' } | |
| }); | |
| } | |
| }; | |