This commit is contained in:
hailin 2025-06-13 21:38:13 +08:00
parent fcb6c480eb
commit e0286c29b8
2 changed files with 70 additions and 69 deletions

View File

@ -1,78 +1,80 @@
package license package license
import ( import (
"encoding/base64" "encoding/base64"
"encoding/json" "encoding/json"
"github.com/gofiber/fiber/v2" "license-server/storage"
"license-server/storage" "time"
"time"
"github.com/gofiber/fiber/v2"
) )
func GenerateLicenseHandler(db storage.Database) fiber.Handler { func GenerateLicenseHandler(db storage.Database) fiber.Handler {
return func(c *fiber.Ctx) error { return func(c *fiber.Ctx) error {
var req LicenseRequest var req LicenseRequest
if err := c.BodyParser(&req); err != nil { if err := c.BodyParser(&req); err != nil {
return fiber.ErrBadRequest return fiber.ErrBadRequest
} }
payloadBytes, _ := json.Marshal(req) payloadBytes, _ := json.Marshal(req)
payloadB64 := base64.StdEncoding.EncodeToString(payloadBytes) payloadB64 := base64.StdEncoding.EncodeToString(payloadBytes)
signature, _ := SignPayload(payloadBytes) signature, _ := SignPayload(payloadBytes)
licenseFile := LicenseFile{ licenseFile := LicenseFile{
Payload: payloadB64, Payload: payloadB64,
Signature: signature, Signature: signature,
} }
return c.JSON(licenseFile) return c.JSON(licenseFile)
} }
} }
func ActivateLicenseHandler(db storage.Database) fiber.Handler { func ActivateLicenseHandler(db storage.Database) fiber.Handler {
return func(c *fiber.Ctx) error { return func(c *fiber.Ctx) error {
var lf LicenseFile var lf LicenseFile
if err := c.BodyParser(&lf); err != nil { if err := c.BodyParser(&lf); err != nil {
return fiber.ErrBadRequest return fiber.ErrBadRequest
} }
payloadBytes, _ := base64.StdEncoding.DecodeString(lf.Payload) payloadBytes, _ := base64.StdEncoding.DecodeString(lf.Payload)
var req LicenseRequest var req LicenseRequest
json.Unmarshal(payloadBytes, &req) json.Unmarshal(payloadBytes, &req)
if db.HasActivated(req.MachineID) { if db.HasActivated(req.MachineID) {
return fiber.NewError(403, "This machine is already activated.") return fiber.NewError(403, "This machine is already activated.")
} }
if !VerifySignature(&privateKey.PublicKey, payloadBytes, lf.Signature) { if !VerifySignature(&privateKey.PublicKey, payloadBytes, lf.Signature) {
return fiber.NewError(401, "Invalid license signature") return fiber.NewError(401, "Invalid license signature")
} }
db.SaveActivation(req.MachineID, lf) licenseText := lf.Payload + "." + lf.Signature
return c.SendString("License activated successfully.") db.SaveActivation(req.MachineID, licenseText)
}
return c.SendString("License activated successfully.")
}
} }
func ValidateLicenseHandler(db storage.Database) fiber.Handler { func ValidateLicenseHandler(db storage.Database) fiber.Handler {
return func(c *fiber.Ctx) error { return func(c *fiber.Ctx) error {
var lf LicenseFile var lf LicenseFile
if err := c.BodyParser(&lf); err != nil { if err := c.BodyParser(&lf); err != nil {
return fiber.ErrBadRequest return fiber.ErrBadRequest
} }
payloadBytes, _ := base64.StdEncoding.DecodeString(lf.Payload) payloadBytes, _ := base64.StdEncoding.DecodeString(lf.Payload)
var req LicenseRequest var req LicenseRequest
json.Unmarshal(payloadBytes, &req) json.Unmarshal(payloadBytes, &req)
if !VerifySignature(&privateKey.PublicKey, payloadBytes, lf.Signature) { if !VerifySignature(&privateKey.PublicKey, payloadBytes, lf.Signature) {
return fiber.NewError(401, "Invalid license signature") return fiber.NewError(401, "Invalid license signature")
} }
expiry, _ := time.Parse("2006-01-02", req.Expiry) expiry, _ := time.Parse("2006-01-02", req.Expiry)
if time.Now().After(expiry) { if time.Now().After(expiry) {
return fiber.NewError(403, "License expired") return fiber.NewError(403, "License expired")
} }
return c.JSON(fiber.Map{"valid": true, "features": req.Features}) return c.JSON(fiber.Map{"valid": true, "features": req.Features})
} }
} }

View File

@ -1,35 +1,34 @@
package storage package storage
import ( import (
"database/sql" "database/sql"
_ "github.com/mattn/go-sqlite3"
"license-server/license" _ "github.com/mattn/go-sqlite3"
) )
type Database struct { type Database struct {
db *sql.DB db *sql.DB
} }
func InitDB() Database { func InitDB() Database {
db, _ := sql.Open("sqlite3", "./license.db") db, _ := sql.Open("sqlite3", "./license.db")
db.Exec(`CREATE TABLE IF NOT EXISTS activations ( db.Exec(`CREATE TABLE IF NOT EXISTS activations (
id INTEGER PRIMARY KEY AUTOINCREMENT, id INTEGER PRIMARY KEY AUTOINCREMENT,
machine_id TEXT UNIQUE, machine_id TEXT UNIQUE,
license TEXT, license TEXT,
activated INTEGER activated INTEGER
)`) )`)
return Database{db} return Database{db}
} }
func (d Database) HasActivated(machineID string) bool { func (d Database) HasActivated(machineID string) bool {
row := d.db.QueryRow("SELECT activated FROM activations WHERE machine_id = ?", machineID) row := d.db.QueryRow("SELECT activated FROM activations WHERE machine_id = ?", machineID)
var activated int var activated int
err := row.Scan(&activated) err := row.Scan(&activated)
return err == nil && activated == 1 return err == nil && activated == 1
} }
func (d Database) SaveActivation(machineID string, lf license.LicenseFile) { func (d Database) SaveActivation(machineID string, licenseText string) {
d.db.Exec("INSERT OR REPLACE INTO activations(machine_id, license, activated) VALUES (?, ?, 1)", d.db.Exec("INSERT OR REPLACE INTO activations(machine_id, license, activated) VALUES (?, ?, 1)",
machineID, lf.Payload+"."+lf.Signature) machineID, licenseText)
} }