Spaces:
Sleeping
Sleeping
File size: 9,927 Bytes
4bea261 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 | 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' }
});
}
};
|