package admin import ( "Embalming_Girl_Server/db" "crypto/rand" "encoding/hex" "encoding/json" "net/http" ) const AdminPassword = "Qwer123456789!" var adminSession string func genSession() string { b := make([]byte, 32) rand.Read(b) return hex.EncodeToString(b) } func isAuth(r *http.Request) bool { c, err := r.Cookie("admin_session") return err == nil && c.Value != "" && c.Value == adminSession } func authWrap(h http.HandlerFunc) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { if !isAuth(r) { w.WriteHeader(401) json.NewEncoder(w).Encode(map[string]interface{}{"error": "unauthorized"}) return } h(w, r) } } func Register(mux *http.ServeMux, getStats func() map[string]interface{}) { mux.HandleFunc("/admin", func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/html; charset=utf-8") w.Write([]byte(adminHTML)) }) mux.HandleFunc("/api/admin/login", func(w http.ResponseWriter, r *http.Request) { var req struct { Password string `json:"password"` } json.NewDecoder(r.Body).Decode(&req) w.Header().Set("Content-Type", "application/json") if req.Password != AdminPassword { json.NewEncoder(w).Encode(map[string]interface{}{"ok": false}) return } adminSession = genSession() http.SetCookie(w, &http.Cookie{ Name: "admin_session", Value: adminSession, Path: "/", MaxAge: 86400, HttpOnly: true, }) json.NewEncoder(w).Encode(map[string]interface{}{"ok": true}) }) mux.HandleFunc("/api/admin/logout", func(w http.ResponseWriter, r *http.Request) { adminSession = "" http.SetCookie(w, &http.Cookie{Name: "admin_session", Value: "", Path: "/", MaxAge: -1}) w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(map[string]interface{}{"ok": true}) }) mux.HandleFunc("/api/admin/check_session", func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(map[string]interface{}{"ok": isAuth(r)}) }) mux.HandleFunc("/api/admin/stats", authWrap(func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(getStats()) })) mux.HandleFunc("/api/admin/users", authWrap(func(w http.ResponseWriter, r *http.Request) { rows, err := db.DB.Query("SELECT id,username,nickname,bio,avatar,created_at,last_login FROM users ORDER BY id DESC") if err != nil { json.NewEncoder(w).Encode([]int{}) return } defer rows.Close() var users []map[string]interface{} for rows.Next() { var id int64 var username, nickname, bio, avatar string var created, login interface{} rows.Scan(&id, &username, &nickname, &bio, &avatar, &created, &login) users = append(users, map[string]interface{}{ "id": id, "username": username, "nickname": nickname, "bio": bio, "avatar": avatar, "created_at": created, "last_login": login, }) } w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(users) })) mux.HandleFunc("/api/admin/delete_user", authWrap(func(w http.ResponseWriter, r *http.Request) { var req struct { ID int64 `json:"id"` } json.NewDecoder(r.Body).Decode(&req) db.DB.Exec("DELETE FROM sessions WHERE user_id=?", req.ID) db.DB.Exec("DELETE FROM users WHERE id=?", req.ID) w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(map[string]interface{}{"ok": true}) })) } const adminHTML = `Embalming Girl - Admin

Embalming Girl

Server Admin Panel

仪表盘

服务器运行状态总览

在线用户

连接ID用户名昵称版本状态

用户管理

管理已注册的用户账号

用户列表

ID用户名昵称头像注册时间操作

更新管理

管理客户端 OTA 更新

当前已发布版本

发布新版本

`