mirror of
https://github.com/truewhile/MeBox.git
synced 2026-10-07 05:46:38 +08:00
fix: honor licensed user limits
This commit is contained in:
@@ -2,6 +2,7 @@ package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"testing"
|
||||
@@ -23,7 +24,7 @@ func newAuthTestServices(t *testing.T) (*repository.Container, *AuthService, *Pr
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := db.AutoMigrate(&model.User{}, &model.UserPermission{}, &model.RefreshToken{}, &model.TelegramBinding{}); err != nil {
|
||||
if err := db.AutoMigrate(&model.User{}, &model.UserPermission{}, &model.RefreshToken{}, &model.TelegramBinding{}, &model.Setting{}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
repos := repository.New(db)
|
||||
@@ -57,6 +58,44 @@ func TestRegisterRejectsMoreThanTwentyUsers(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestRegisterUsesLicensedUserLimit(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
repos, auth, _, _ := newAuthTestServices(t)
|
||||
maxUsers := 25
|
||||
state := LicenseActivationState{Valid: true, LicenseType: "plus", MaxUsers: &maxUsers}
|
||||
raw, _ := json.Marshal(state)
|
||||
if err := repos.Setting.Set(ctx, LicenseSettingActivation, string(raw)); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for i := 0; i < OpenSourceUserLimit; i++ {
|
||||
if err := repos.User.Create(ctx, &model.User{
|
||||
Username: fmt.Sprintf("licensed-%02d", i),
|
||||
PasswordHash: "hash",
|
||||
Role: "user",
|
||||
Tier: "free",
|
||||
}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
if _, _, err := auth.Register(ctx, "extra", "password"); err != nil {
|
||||
t.Fatalf("licensed user limit should allow user 21: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLicensedMaxUsersCanBeUnlimited(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
repos, _, _, _ := newAuthTestServices(t)
|
||||
state := LicenseActivationState{Valid: true, LicenseType: "enterprise", UnlimitedUsers: true}
|
||||
raw, _ := json.Marshal(state)
|
||||
if err := repos.Setting.Set(ctx, LicenseSettingActivation, string(raw)); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if got := LicensedMaxUsers(ctx, repos); got <= 1_000_000 {
|
||||
t.Fatalf("unlimited license should return a very high limit, got %d", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRegisterDefaultsAdultLibrariesHidden(t *testing.T) {
|
||||
_, auth, _, _ := newAuthTestServices(t)
|
||||
user, _, err := auth.Register(context.Background(), "viewer", "password")
|
||||
|
||||
+31
-13
@@ -3,6 +3,7 @@ package service
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"math"
|
||||
"time"
|
||||
|
||||
"github.com/ShukeBta/MediaStationGo/internal/repository"
|
||||
@@ -16,19 +17,28 @@ const (
|
||||
)
|
||||
|
||||
type LicenseActivationState struct {
|
||||
Valid bool `json:"valid"`
|
||||
LicenseType string `json:"license_type,omitempty"`
|
||||
ExpiryDate string `json:"expiry_date,omitempty"`
|
||||
MaxDevices int `json:"max_devices,omitempty"`
|
||||
DaysRemaining *int `json:"days_remaining,omitempty"`
|
||||
NextHeartbeat string `json:"next_heartbeat,omitempty"`
|
||||
DeviceID string `json:"device_id,omitempty"`
|
||||
DeviceName string `json:"device_name,omitempty"`
|
||||
UpdatedAt string `json:"updated_at,omitempty"`
|
||||
Valid bool `json:"valid"`
|
||||
LicenseType string `json:"license_type,omitempty"`
|
||||
ExpiryDate string `json:"expiry_date,omitempty"`
|
||||
MaxDevices int `json:"max_devices,omitempty"`
|
||||
MaxUsers *int `json:"max_users,omitempty"`
|
||||
UnlimitedUsers bool `json:"unlimited_users,omitempty"`
|
||||
DaysRemaining *int `json:"days_remaining,omitempty"`
|
||||
NextHeartbeat string `json:"next_heartbeat,omitempty"`
|
||||
DeviceID string `json:"device_id,omitempty"`
|
||||
DeviceName string `json:"device_name,omitempty"`
|
||||
UpdatedAt string `json:"updated_at,omitempty"`
|
||||
}
|
||||
|
||||
func LicensedMaxUsers(ctx context.Context, repos *repository.Container) int64 {
|
||||
if LicenseActive(ctx, repos) {
|
||||
state, ok := loadLicenseActivationState(ctx, repos)
|
||||
if ok && state.Valid && !licenseExpired(state.ExpiryDate) {
|
||||
if state.UnlimitedUsers {
|
||||
return math.MaxInt64
|
||||
}
|
||||
if state.MaxUsers != nil && *state.MaxUsers > 0 {
|
||||
return int64(*state.MaxUsers)
|
||||
}
|
||||
return LicensedUserLimit
|
||||
}
|
||||
return OpenSourceUserLimit
|
||||
@@ -38,15 +48,23 @@ func LicenseActive(ctx context.Context, repos *repository.Container) bool {
|
||||
if repos == nil || repos.Setting == nil {
|
||||
return false
|
||||
}
|
||||
state, ok := loadLicenseActivationState(ctx, repos)
|
||||
return ok && state.Valid && !licenseExpired(state.ExpiryDate)
|
||||
}
|
||||
|
||||
func loadLicenseActivationState(ctx context.Context, repos *repository.Container) (LicenseActivationState, bool) {
|
||||
if repos == nil || repos.Setting == nil {
|
||||
return LicenseActivationState{}, false
|
||||
}
|
||||
raw, err := repos.Setting.Get(ctx, LicenseSettingActivation)
|
||||
if err != nil || raw == "" {
|
||||
return false
|
||||
return LicenseActivationState{}, false
|
||||
}
|
||||
var state LicenseActivationState
|
||||
if err := json.Unmarshal([]byte(raw), &state); err != nil {
|
||||
return false
|
||||
return LicenseActivationState{}, false
|
||||
}
|
||||
return state.Valid && !licenseExpired(state.ExpiryDate)
|
||||
return state, true
|
||||
}
|
||||
|
||||
func licenseExpired(expiry string) bool {
|
||||
|
||||
Reference in New Issue
Block a user