licensing-cotton/internal/handlers/renew.go
2025-01-16 15:41:42 +08:00

108 lines
3.4 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package handlers
import (
"database/sql"
"encoding/json"
"fmt"
"licensing-cotton/internal/config"
"net/http"
"time"
"licensing-cotton/internal/database"
"licensing-cotton/internal/models"
)
// HandleRenewLicense 让设备只续 1 小时;需满足某些逻辑才能续
func HandleRenewLicense(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
http.Error(w, `{"error":"Only POST allowed","code":405}`, http.StatusMethodNotAllowed)
return
}
var req struct {
DeviceID string `json:"device_id"`
Expiration string `json:"expiration"`
}
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
http.Error(w, `{"error":"解析请求失败","code":400}`, http.StatusBadRequest)
return
}
if config.AutoRenewAllDevices {
// 计算新的到期时间
newExpiration := time.Now().Add(1 * time.Hour)
// 更新数据库 expiration
_, errUpdate := database.DB.Exec(`UPDATE devices SET expiration=? WHERE device_id=?`, newExpiration, req.DeviceID)
if errUpdate != nil {
http.Error(w, fmt.Sprintf(`{"error":"更新Expiration失败:%s","code":500}`, errUpdate.Error()), http.StatusInternalServerError)
return
}
lic, signErr := SignLicense(req.DeviceID, newExpiration)
if signErr != nil {
http.Error(w, fmt.Sprintf(`{"error":"签名失败: %v","code":500}`, signErr.Error()), http.StatusInternalServerError)
return
}
// 返回成功续期的 License
resp := struct {
License License `json:"license"`
Message string `json:"message"`
}{
License: lic,
Message: "License renewed automatically (AutoRenewAllDevices).",
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(resp)
return
}
// **查询设备**
var dev models.Device
err := database.DB.QueryRow(`SELECT id, device_id, expiration FROM devices WHERE device_id=?`, req.DeviceID).
Scan(&dev.ID, &dev.DeviceID, &dev.Expiration)
if err == sql.ErrNoRows {
if err := CreateRequest(req.DeviceID); err != nil {
http.Error(w, fmt.Sprintf(`{"error":"续期申请失败: %s","code":409}`, err.Error()), http.StatusConflict)
return
}
http.Error(w, `{"error":"设备不存在,已提交申请,等待管理员审批","code":404}`, http.StatusAccepted)
return
} else if err != nil {
http.Error(w, fmt.Sprintf(`{"error":"数据库查询错误: %s","code":500}`, err.Error()), http.StatusInternalServerError)
return
}
newExpiration := time.Now().Add(1 * time.Hour)
if dev.Expiration.Before(time.Now()) {
if err := CreateRequest(req.DeviceID); err != nil {
http.Error(w, fmt.Sprintf(`{"error":"续期申请失败: %s","code":409}`, err.Error()), http.StatusConflict)
return
}
http.Error(w, `{"error":"设备过期,已提交续期申请,等待管理员审批","code":404}`, http.StatusAccepted)
return
}
if dev.Expiration.Before(newExpiration) {
// 如果时间不够1小时了就续期到可以运行的极限
newExpiration = dev.Expiration
}
// **创建新 License 并签名**
lic, signErr := SignLicense(dev.DeviceID, newExpiration)
if signErr != nil {
http.Error(w, fmt.Sprintf(`{"error":"%v","code":500}`, signErr.Error()), http.StatusInternalServerError)
return
}
// **返回成功续期的 License**
resp := struct {
License License `json:"license"`
Message string `json:"message"`
}{
License: lic,
Message: "License renewed successfully.",
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(resp)
}