mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-01-13 01:02:46 +00:00
224 lines
5.9 KiB
Go
224 lines
5.9 KiB
Go
// Package controller provides HTTP handlers for client HWID management.
|
|
package controller
|
|
|
|
import (
|
|
"net/http"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"github.com/mhsanaei/3x-ui/v2/web/service"
|
|
)
|
|
|
|
// ClientHWIDController handles HTTP requests for client HWID management.
|
|
type ClientHWIDController struct {
|
|
clientHWIDService *service.ClientHWIDService
|
|
clientService *service.ClientService
|
|
}
|
|
|
|
// NewClientHWIDController creates a new ClientHWIDController.
|
|
func NewClientHWIDController(g *gin.RouterGroup) *ClientHWIDController {
|
|
a := &ClientHWIDController{
|
|
clientHWIDService: &service.ClientHWIDService{},
|
|
clientService: &service.ClientService{},
|
|
}
|
|
a.initRouter(g)
|
|
return a
|
|
}
|
|
|
|
// initRouter sets up routes for client HWID management.
|
|
func (a *ClientHWIDController) initRouter(g *gin.RouterGroup) {
|
|
g = g.Group("/hwid")
|
|
{
|
|
g.GET("/list/:clientId", a.getHWIDs)
|
|
g.POST("/add", a.addHWID)
|
|
g.POST("/del/:id", a.removeHWID) // Changed to /del/:id to match API style
|
|
g.POST("/deactivate/:id", a.deactivateHWID)
|
|
g.POST("/check", a.checkHWID)
|
|
g.POST("/register", a.registerHWID)
|
|
}
|
|
}
|
|
|
|
// getHWIDs retrieves all HWIDs for a specific client.
|
|
func (a *ClientHWIDController) getHWIDs(c *gin.Context) {
|
|
clientIdStr := c.Param("clientId")
|
|
clientId, err := strconv.Atoi(clientIdStr)
|
|
if err != nil {
|
|
jsonMsg(c, "Invalid client ID", nil)
|
|
return
|
|
}
|
|
|
|
hwids, err := a.clientHWIDService.GetHWIDsForClient(clientId)
|
|
if err != nil {
|
|
jsonMsg(c, "Failed to get HWIDs", err)
|
|
return
|
|
}
|
|
|
|
jsonObj(c, hwids, nil)
|
|
}
|
|
|
|
// addHWID adds a new HWID for a client (manual addition by admin).
|
|
func (a *ClientHWIDController) addHWID(c *gin.Context) {
|
|
var req struct {
|
|
ClientId int `json:"clientId" form:"clientId" binding:"required"`
|
|
HWID string `json:"hwid" form:"hwid" binding:"required"`
|
|
DeviceOS string `json:"deviceOs" form:"deviceOs"`
|
|
DeviceModel string `json:"deviceModel" form:"deviceModel"`
|
|
OSVersion string `json:"osVersion" form:"osVersion"`
|
|
IPAddress string `json:"ipAddress" form:"ipAddress"`
|
|
UserAgent string `json:"userAgent" form:"userAgent"`
|
|
}
|
|
|
|
if err := c.ShouldBind(&req); err != nil {
|
|
jsonMsg(c, "Invalid request", err)
|
|
return
|
|
}
|
|
|
|
hwid, err := a.clientHWIDService.AddHWIDForClient(req.ClientId, req.HWID, req.DeviceOS, req.DeviceModel, req.OSVersion, req.IPAddress, req.UserAgent)
|
|
if err != nil {
|
|
jsonMsg(c, "Failed to add HWID", err)
|
|
return
|
|
}
|
|
|
|
jsonObj(c, hwid, nil)
|
|
}
|
|
|
|
// removeHWID removes a HWID from a client.
|
|
func (a *ClientHWIDController) removeHWID(c *gin.Context) {
|
|
idStr := c.Param("id")
|
|
id, err := strconv.Atoi(idStr)
|
|
if err != nil {
|
|
jsonMsg(c, "Invalid HWID ID", nil)
|
|
return
|
|
}
|
|
|
|
err = a.clientHWIDService.RemoveHWID(id)
|
|
if err != nil {
|
|
jsonMsg(c, "Failed to remove HWID", err)
|
|
return
|
|
}
|
|
|
|
jsonMsg(c, "HWID removed successfully", nil)
|
|
}
|
|
|
|
// deactivateHWID deactivates a HWID (marks as inactive).
|
|
func (a *ClientHWIDController) deactivateHWID(c *gin.Context) {
|
|
idStr := c.Param("id")
|
|
id, err := strconv.Atoi(idStr)
|
|
if err != nil {
|
|
jsonMsg(c, "Invalid HWID ID", nil)
|
|
return
|
|
}
|
|
|
|
err = a.clientHWIDService.DeactivateHWID(id)
|
|
if err != nil {
|
|
jsonMsg(c, "Failed to deactivate HWID", err)
|
|
return
|
|
}
|
|
|
|
jsonMsg(c, "HWID deactivated successfully", nil)
|
|
}
|
|
|
|
// checkHWID checks if a HWID is allowed for a client.
|
|
func (a *ClientHWIDController) checkHWID(c *gin.Context) {
|
|
var req struct {
|
|
ClientId int `json:"clientId" form:"clientId" binding:"required"`
|
|
HWID string `json:"hwid" form:"hwid" binding:"required"`
|
|
}
|
|
|
|
if err := c.ShouldBind(&req); err != nil {
|
|
jsonMsg(c, "Invalid request", err)
|
|
return
|
|
}
|
|
|
|
allowed, err := a.clientHWIDService.CheckHWIDAllowed(req.ClientId, req.HWID)
|
|
if err != nil {
|
|
jsonMsg(c, "Failed to check HWID", err)
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"success": true,
|
|
"obj": gin.H{
|
|
"allowed": allowed,
|
|
},
|
|
})
|
|
}
|
|
|
|
// registerHWID registers a HWID for a client (called by client applications).
|
|
// This endpoint reads HWID and device metadata from HTTP headers:
|
|
// - x-hwid (required): Hardware ID
|
|
// - x-device-os (optional): Device operating system
|
|
// - x-device-model (optional): Device model
|
|
// - x-ver-os (optional): OS version
|
|
// - user-agent (optional): User agent string
|
|
func (a *ClientHWIDController) registerHWID(c *gin.Context) {
|
|
var req struct {
|
|
Email string `json:"email" form:"email" binding:"required"`
|
|
}
|
|
|
|
if err := c.ShouldBind(&req); err != nil {
|
|
jsonMsg(c, "Invalid request", err)
|
|
return
|
|
}
|
|
|
|
// Read HWID from headers (primary method)
|
|
hwid := c.GetHeader("x-hwid")
|
|
if hwid == "" {
|
|
// Try alternative header name (case-insensitive)
|
|
hwid = c.GetHeader("X-HWID")
|
|
}
|
|
if hwid == "" {
|
|
jsonMsg(c, "HWID is required (x-hwid header missing)", nil)
|
|
return
|
|
}
|
|
|
|
// Read device metadata from headers
|
|
deviceOS := c.GetHeader("x-device-os")
|
|
if deviceOS == "" {
|
|
deviceOS = c.GetHeader("X-Device-OS")
|
|
}
|
|
deviceModel := c.GetHeader("x-device-model")
|
|
if deviceModel == "" {
|
|
deviceModel = c.GetHeader("X-Device-Model")
|
|
}
|
|
osVersion := c.GetHeader("x-ver-os")
|
|
if osVersion == "" {
|
|
osVersion = c.GetHeader("X-Ver-OS")
|
|
}
|
|
userAgent := c.GetHeader("User-Agent")
|
|
ipAddress := c.ClientIP()
|
|
|
|
// Get client by email
|
|
client, err := a.clientService.GetClientByEmail(1, req.Email) // TODO: Get userId from session
|
|
if err != nil {
|
|
jsonMsg(c, "Client not found", err)
|
|
return
|
|
}
|
|
|
|
// Register HWID using RegisterHWIDFromHeaders
|
|
hwidRecord, err := a.clientHWIDService.RegisterHWIDFromHeaders(client.Id, hwid, deviceOS, deviceModel, osVersion, ipAddress, userAgent)
|
|
if err != nil {
|
|
// Check if error is HWID limit exceeded
|
|
if strings.Contains(err.Error(), "HWID limit exceeded") {
|
|
c.JSON(http.StatusForbidden, gin.H{
|
|
"success": false,
|
|
"msg": err.Error(),
|
|
})
|
|
return
|
|
}
|
|
jsonMsg(c, "Failed to register HWID", err)
|
|
return
|
|
}
|
|
|
|
if hwidRecord == nil {
|
|
// HWID tracking disabled (hwidMode = "off")
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"success": true,
|
|
"msg": "HWID tracking is disabled",
|
|
})
|
|
return
|
|
}
|
|
|
|
jsonObj(c, hwidRecord, nil)
|
|
}
|