mirror of
https://github.com/skyle1995/NetworkAuth.git
synced 2026-05-25 02:24:05 +08:00
389 lines
9.8 KiB
Go
389 lines
9.8 KiB
Go
package admin
|
||
|
||
import (
|
||
"crypto/rand"
|
||
"encoding/hex"
|
||
"encoding/json"
|
||
"net/http"
|
||
"networkDev/database"
|
||
"networkDev/models"
|
||
"networkDev/utils"
|
||
"strconv"
|
||
"strings"
|
||
|
||
"github.com/google/uuid"
|
||
"github.com/sirupsen/logrus"
|
||
)
|
||
|
||
// AppsFragmentHandler 应用列表页面片段处理器
|
||
func AppsFragmentHandler(w http.ResponseWriter, r *http.Request) {
|
||
utils.RenderTemplate(w, "apps.html", map[string]interface{}{
|
||
"Title": "应用管理",
|
||
})
|
||
}
|
||
|
||
// AppsListHandler 应用列表API处理器
|
||
func AppsListHandler(w http.ResponseWriter, r *http.Request) {
|
||
if r.Method != http.MethodGet {
|
||
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
||
return
|
||
}
|
||
|
||
// 获取分页参数
|
||
page, _ := strconv.Atoi(r.URL.Query().Get("page"))
|
||
if page <= 0 {
|
||
page = 1
|
||
}
|
||
limit, _ := strconv.Atoi(r.URL.Query().Get("limit"))
|
||
if limit <= 0 {
|
||
limit = 10
|
||
}
|
||
|
||
// 获取搜索参数
|
||
search := strings.TrimSpace(r.URL.Query().Get("search"))
|
||
|
||
// 构建查询
|
||
db, err := database.GetDB()
|
||
if err != nil {
|
||
logrus.WithError(err).Error("Failed to get database connection")
|
||
http.Error(w, "Internal server error", http.StatusInternalServerError)
|
||
return
|
||
}
|
||
|
||
var apps []models.App
|
||
var total int64
|
||
|
||
query := db.Model(&models.App{})
|
||
|
||
// 如果有搜索条件
|
||
if search != "" {
|
||
query = query.Where("name LIKE ? OR uuid LIKE ?", "%"+search+"%", "%"+search+"%")
|
||
}
|
||
|
||
// 获取总数
|
||
if err := query.Count(&total).Error; err != nil {
|
||
logrus.WithError(err).Error("Failed to count apps")
|
||
http.Error(w, "Internal server error", http.StatusInternalServerError)
|
||
return
|
||
}
|
||
|
||
// 分页查询
|
||
offset := (page - 1) * limit
|
||
if err := query.Order("created_at DESC").Offset(offset).Limit(limit).Find(&apps).Error; err != nil {
|
||
logrus.WithError(err).Error("Failed to query apps")
|
||
http.Error(w, "Internal server error", http.StatusInternalServerError)
|
||
return
|
||
}
|
||
|
||
// 返回结果
|
||
response := map[string]interface{}{
|
||
"code": 0,
|
||
"msg": "success",
|
||
"count": total,
|
||
"data": apps,
|
||
}
|
||
|
||
w.Header().Set("Content-Type", "application/json")
|
||
json.NewEncoder(w).Encode(response)
|
||
}
|
||
|
||
// AppCreateHandler 创建应用API处理器
|
||
func AppCreateHandler(w http.ResponseWriter, r *http.Request) {
|
||
if r.Method != http.MethodPost {
|
||
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
||
return
|
||
}
|
||
|
||
var req struct {
|
||
Name string `json:"name"`
|
||
Version string `json:"version"`
|
||
Status int `json:"status"`
|
||
DownloadType int `json:"download_type"`
|
||
ForceUpdate int `json:"force_update"`
|
||
DownloadURL string `json:"download_url"`
|
||
}
|
||
|
||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||
logrus.WithError(err).Error("Failed to decode JSON request")
|
||
http.Error(w, "Invalid JSON", http.StatusBadRequest)
|
||
return
|
||
}
|
||
|
||
// 验证必填字段
|
||
if strings.TrimSpace(req.Name) == "" {
|
||
logrus.Error("App name is empty")
|
||
http.Error(w, "应用名称不能为空", http.StatusBadRequest)
|
||
return
|
||
}
|
||
|
||
// 设置默认值
|
||
if req.Version == "" {
|
||
req.Version = "1.0.0"
|
||
}
|
||
|
||
logrus.WithFields(logrus.Fields{
|
||
"name": req.Name,
|
||
"version": req.Version,
|
||
"status": req.Status,
|
||
"download_type": req.DownloadType,
|
||
"download_url": req.DownloadURL,
|
||
"force_update": req.ForceUpdate,
|
||
}).Info("Received app create request")
|
||
|
||
// 创建应用
|
||
app := models.App{
|
||
Name: strings.TrimSpace(req.Name),
|
||
Version: req.Version,
|
||
Status: req.Status,
|
||
DownloadType: req.DownloadType,
|
||
DownloadURL: strings.TrimSpace(req.DownloadURL),
|
||
ForceUpdate: req.ForceUpdate,
|
||
}
|
||
|
||
// 确保UUID和Secret被设置(虽然BeforeCreate钩子应该处理这些,但为了保险起见)
|
||
if app.UUID == "" {
|
||
app.UUID = uuid.New().String()
|
||
}
|
||
if app.Secret == "" {
|
||
// 生成32位大写16进制随机字符
|
||
bytes := make([]byte, 16) // 16字节 = 32位16进制字符
|
||
rand.Read(bytes)
|
||
app.Secret = strings.ToUpper(hex.EncodeToString(bytes))
|
||
}
|
||
|
||
db, err := database.GetDB()
|
||
if err != nil {
|
||
logrus.WithError(err).Error("Failed to get database connection")
|
||
http.Error(w, "数据库连接失败", http.StatusInternalServerError)
|
||
return
|
||
}
|
||
|
||
if err := db.Create(&app).Error; err != nil {
|
||
logrus.WithError(err).Error("Failed to create app")
|
||
http.Error(w, "创建应用失败", http.StatusInternalServerError)
|
||
return
|
||
}
|
||
|
||
response := map[string]interface{}{
|
||
"code": 0,
|
||
"msg": "创建成功",
|
||
"data": app,
|
||
}
|
||
|
||
w.Header().Set("Content-Type", "application/json")
|
||
json.NewEncoder(w).Encode(response)
|
||
}
|
||
|
||
// AppUpdateHandler 更新应用API处理器
|
||
func AppUpdateHandler(w http.ResponseWriter, r *http.Request) {
|
||
if r.Method != http.MethodPost {
|
||
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
||
return
|
||
}
|
||
|
||
var req struct {
|
||
ID uint `json:"id"`
|
||
Name string `json:"name"`
|
||
Version string `json:"version"`
|
||
Status int `json:"status"`
|
||
DownloadType int `json:"download_type"`
|
||
DownloadURL string `json:"download_url"`
|
||
ForceUpdate int `json:"force_update"`
|
||
}
|
||
|
||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||
http.Error(w, "Invalid JSON", http.StatusBadRequest)
|
||
return
|
||
}
|
||
|
||
// 验证必填字段
|
||
if req.ID == 0 {
|
||
http.Error(w, "应用ID不能为空", http.StatusBadRequest)
|
||
return
|
||
}
|
||
if strings.TrimSpace(req.Name) == "" {
|
||
http.Error(w, "应用名称不能为空", http.StatusBadRequest)
|
||
return
|
||
}
|
||
|
||
db, err := database.GetDB()
|
||
if err != nil {
|
||
logrus.WithError(err).Error("Failed to get database connection")
|
||
http.Error(w, "数据库连接失败", http.StatusInternalServerError)
|
||
return
|
||
}
|
||
|
||
// 查找应用
|
||
var app models.App
|
||
if err := db.First(&app, req.ID).Error; err != nil {
|
||
http.Error(w, "应用不存在", http.StatusNotFound)
|
||
return
|
||
}
|
||
|
||
// 更新字段
|
||
app.Name = strings.TrimSpace(req.Name)
|
||
app.Version = req.Version
|
||
app.Status = req.Status
|
||
app.DownloadType = req.DownloadType
|
||
app.DownloadURL = strings.TrimSpace(req.DownloadURL)
|
||
app.ForceUpdate = req.ForceUpdate
|
||
|
||
if err := db.Save(&app).Error; err != nil {
|
||
logrus.WithError(err).Error("Failed to update app")
|
||
http.Error(w, "更新应用失败", http.StatusInternalServerError)
|
||
return
|
||
}
|
||
|
||
response := map[string]interface{}{
|
||
"code": 0,
|
||
"msg": "更新成功",
|
||
"data": app,
|
||
}
|
||
|
||
w.Header().Set("Content-Type", "application/json")
|
||
json.NewEncoder(w).Encode(response)
|
||
}
|
||
|
||
// AppDeleteHandler 删除应用API处理器
|
||
func AppDeleteHandler(w http.ResponseWriter, r *http.Request) {
|
||
if r.Method != http.MethodPost {
|
||
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
||
return
|
||
}
|
||
|
||
var req struct {
|
||
ID uint `json:"id"`
|
||
}
|
||
|
||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||
http.Error(w, "Invalid JSON", http.StatusBadRequest)
|
||
return
|
||
}
|
||
|
||
if req.ID == 0 {
|
||
http.Error(w, "应用ID不能为空", http.StatusBadRequest)
|
||
return
|
||
}
|
||
|
||
db, err := database.GetDB()
|
||
if err != nil {
|
||
logrus.WithError(err).Error("Failed to get database connection")
|
||
http.Error(w, "数据库连接失败", http.StatusInternalServerError)
|
||
return
|
||
}
|
||
|
||
// 删除应用
|
||
if err := db.Delete(&models.App{}, req.ID).Error; err != nil {
|
||
logrus.WithError(err).Error("Failed to delete app")
|
||
http.Error(w, "删除应用失败", http.StatusInternalServerError)
|
||
return
|
||
}
|
||
|
||
response := map[string]interface{}{
|
||
"code": 0,
|
||
"msg": "删除成功",
|
||
}
|
||
|
||
w.Header().Set("Content-Type", "application/json")
|
||
json.NewEncoder(w).Encode(response)
|
||
}
|
||
|
||
// AppsBatchDeleteHandler 批量删除应用API处理器
|
||
func AppsBatchDeleteHandler(w http.ResponseWriter, r *http.Request) {
|
||
if r.Method != http.MethodPost {
|
||
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
||
return
|
||
}
|
||
|
||
var req struct {
|
||
IDs []uint `json:"ids"`
|
||
}
|
||
|
||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||
http.Error(w, "Invalid JSON", http.StatusBadRequest)
|
||
return
|
||
}
|
||
|
||
if len(req.IDs) == 0 {
|
||
http.Error(w, "请选择要删除的应用", http.StatusBadRequest)
|
||
return
|
||
}
|
||
|
||
db, err := database.GetDB()
|
||
if err != nil {
|
||
logrus.WithError(err).Error("Failed to get database connection")
|
||
http.Error(w, "数据库连接失败", http.StatusInternalServerError)
|
||
return
|
||
}
|
||
|
||
// 批量删除
|
||
if err := db.Delete(&models.App{}, req.IDs).Error; err != nil {
|
||
logrus.WithError(err).Error("Failed to batch delete apps")
|
||
http.Error(w, "批量删除失败", http.StatusInternalServerError)
|
||
return
|
||
}
|
||
|
||
response := map[string]interface{}{
|
||
"code": 0,
|
||
"msg": "批量删除成功",
|
||
}
|
||
|
||
w.Header().Set("Content-Type", "application/json")
|
||
json.NewEncoder(w).Encode(response)
|
||
}
|
||
|
||
// AppsBatchUpdateStatusHandler 批量更新应用状态API处理器
|
||
func AppsBatchUpdateStatusHandler(w http.ResponseWriter, r *http.Request) {
|
||
if r.Method != http.MethodPost {
|
||
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
||
return
|
||
}
|
||
|
||
var req struct {
|
||
IDs []uint `json:"ids"`
|
||
Status int `json:"status"`
|
||
}
|
||
|
||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||
http.Error(w, "Invalid JSON", http.StatusBadRequest)
|
||
return
|
||
}
|
||
|
||
if len(req.IDs) == 0 {
|
||
http.Error(w, "请选择要更新的应用", http.StatusBadRequest)
|
||
return
|
||
}
|
||
|
||
if req.Status != 0 && req.Status != 1 {
|
||
http.Error(w, "状态值无效", http.StatusBadRequest)
|
||
return
|
||
}
|
||
|
||
db, err := database.GetDB()
|
||
if err != nil {
|
||
logrus.WithError(err).Error("Failed to get database connection")
|
||
http.Error(w, "数据库连接失败", http.StatusInternalServerError)
|
||
return
|
||
}
|
||
|
||
// 批量更新状态
|
||
if err := db.Model(&models.App{}).Where("id IN ?", req.IDs).Update("status", req.Status).Error; err != nil {
|
||
logrus.WithError(err).Error("Failed to batch update app status")
|
||
http.Error(w, "批量更新状态失败", http.StatusInternalServerError)
|
||
return
|
||
}
|
||
|
||
statusText := "禁用"
|
||
if req.Status == 1 {
|
||
statusText = "启用"
|
||
}
|
||
|
||
response := map[string]interface{}{
|
||
"code": 0,
|
||
"msg": "批量" + statusText + "成功",
|
||
}
|
||
|
||
w.Header().Set("Content-Type", "application/json")
|
||
json.NewEncoder(w).Encode(response)
|
||
}
|