Massive refactor!
This commit is contained in:
25
internal/licensecheck/checker.go
Normal file
25
internal/licensecheck/checker.go
Normal file
@@ -0,0 +1,25 @@
|
||||
package internal
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
type LicenseChecker struct {
|
||||
LicenseAPIURL string
|
||||
APIKey string
|
||||
PollInterval time.Duration
|
||||
|
||||
mu sync.RWMutex
|
||||
lastGood time.Time
|
||||
valid bool
|
||||
}
|
||||
|
||||
func (lc *LicenseChecker) setValid(ok bool) {
|
||||
lc.mu.Lock()
|
||||
defer lc.mu.Unlock()
|
||||
lc.valid = ok
|
||||
if ok {
|
||||
lc.lastGood = time.Now()
|
||||
}
|
||||
}
|
||||
76
internal/licensecheck/validate.go
Normal file
76
internal/licensecheck/validate.go
Normal file
@@ -0,0 +1,76 @@
|
||||
package internal
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
func (lc *LicenseChecker) Validate() error {
|
||||
url := fmt.Sprintf("%s/license/lookup?key=%s&format=json", lc.LicenseAPIURL, lc.APIKey)
|
||||
resp, err := http.Get(url)
|
||||
if err != nil {
|
||||
lc.setValid(false)
|
||||
|
||||
return fmt.Errorf("license lookup failed: %w", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != 200 {
|
||||
lc.setValid(false)
|
||||
|
||||
return fmt.Errorf("license lookup error: %s", resp.Status)
|
||||
}
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
lc.setValid(false)
|
||||
|
||||
return fmt.Errorf("reading response failed: %w", err)
|
||||
}
|
||||
|
||||
var data struct {
|
||||
Revoked bool `json:"revoked"`
|
||||
ExpiresAt time.Time `json:"expires_at"`
|
||||
}
|
||||
if err := json.Unmarshal(body, &data); err != nil {
|
||||
lc.setValid(false)
|
||||
|
||||
return fmt.Errorf("unmarshal error: %w", err)
|
||||
}
|
||||
|
||||
if data.Revoked || time.Now().After(data.ExpiresAt) {
|
||||
lc.setValid(false)
|
||||
|
||||
return fmt.Errorf("license expired or revoked")
|
||||
}
|
||||
|
||||
lc.mu.Lock()
|
||||
lc.valid = true
|
||||
lc.lastGood = time.Now()
|
||||
lc.mu.Unlock()
|
||||
|
||||
log.Printf("✅ License validated. Expires: %s", data.ExpiresAt)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (lc *LicenseChecker) StartBackgroundCheck() {
|
||||
go func() {
|
||||
for {
|
||||
time.Sleep(lc.PollInterval)
|
||||
err := lc.Validate()
|
||||
if err != nil {
|
||||
log.Printf("⚠️ License check failed: %v", err)
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
func (lc *LicenseChecker) IsValid() bool {
|
||||
lc.mu.RLock()
|
||||
defer lc.mu.RUnlock()
|
||||
return lc.valid
|
||||
}
|
||||
Reference in New Issue
Block a user