Add IsFree subscription toggle to bypass all tier limitations

- Add IsFree boolean field to UserSubscription model
- When IsFree is true, user sees limitations_enabled=false regardless of global setting
- CheckLimit() bypasses all limit checks for IsFree users
- Add admin endpoint GET /api/admin/subscriptions/user/:user_id
- Add IsFree toggle to admin user detail page under Subscription card
- Add database migration 004_subscription_is_free
- Add integration tests for IsFree functionality
- Add task kanban categorization documentation

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Trey t
2025-12-01 18:05:41 -06:00
parent 0a708c092d
commit 0c86611a10
14 changed files with 750 additions and 3 deletions

View File

@@ -95,12 +95,19 @@ func (s *SubscriptionService) GetSubscriptionStatus(userID uint) (*SubscriptionS
return nil, err
}
// Determine if limitations are enabled for this user
// If user has IsFree flag, always return false (no limitations)
limitationsEnabled := settings.EnableLimitations
if sub.IsFree {
limitationsEnabled = false
}
// Build flattened response (KMM expects subscription fields at top level)
resp := &SubscriptionStatusResponse{
AutoRenew: sub.AutoRenew,
Limits: limitsMap,
Usage: usage,
LimitationsEnabled: settings.EnableLimitations,
LimitationsEnabled: limitationsEnabled,
}
// Format dates if present
@@ -161,7 +168,7 @@ func (s *SubscriptionService) CheckLimit(userID uint, limitType string) error {
return err
}
// If limitations are disabled, allow everything
// If limitations are disabled globally, allow everything
if !settings.EnableLimitations {
return nil
}
@@ -171,6 +178,11 @@ func (s *SubscriptionService) CheckLimit(userID uint, limitType string) error {
return err
}
// IsFree users bypass all limitations
if sub.IsFree {
return nil
}
// Pro users have unlimited access
if sub.IsPro() {
return nil