- Add verifyCaptcha method to phone login logic
- Add verifyCaptcha method to phone registration logic
- Support both local and Turnstile captcha verification
- Check EnableUserLoginCaptcha for phone login
- Check EnableUserRegisterCaptcha for phone registration
- Validate captcha before processing phone authentication
- Add verifyCaptcha method to user login logic
- Add verifyCaptcha method to user registration logic
- Add verifyCaptcha method to password reset logic
- Support both local and Turnstile captcha verification
- Check respective configuration flags before verification
- Validate captcha code and ID for local captcha
- Validate Turnstile token for Turnstile mode
- Add handler for /v1/auth/captcha/generate endpoint
- Implement captcha generation logic based on configuration
- Support local image captcha generation with Redis storage
- Return Turnstile site key for Turnstile mode
- Check EnableUserLoginCaptcha configuration
- Add CaptchaType field to verify config
- Add EnableUserLoginCaptcha field
- Add EnableUserRegisterCaptcha field
- Add EnableAdminLoginCaptcha field
- Add EnableUserResetPasswordCaptcha field
- Expose captcha configuration to frontend
- Add CaptchaId and CaptchaCode to UserLoginRequest
- Add CaptchaId and CaptchaCode to UserRegisterRequest
- Add CaptchaId and CaptchaCode to ResetPasswordRequest
- Add CaptchaId and CaptchaCode to TelephoneLoginRequest
- Add CaptchaId and CaptchaCode to TelephoneUserRegisterRequest
- Add CaptchaId and CaptchaCode to TelephoneResetPasswordRequest
- Add GenerateCaptchaResponse type
- Add AdminLoginRequest and AdminResetPasswordRequest types
- Add CaptchaId and CaptchaCode fields to login/register/reset requests
- Add /v1/auth/captcha/generate endpoint for user captcha generation
- Add /v1/auth/admin/login endpoint for admin authentication
- Add /v1/auth/admin/reset-password endpoint for admin password reset
- Add /v1/auth/admin/captcha/generate endpoint for admin captcha generation
- Update GlobalConfigResponse with new verify configuration fields
- Add GenerateCaptchaResponse type for captcha generation
- Add CaptchaType field for selecting captcha implementation
- Add EnableUserLoginCaptcha for user login verification
- Add EnableUserRegisterCaptcha for user registration verification
- Add EnableAdminLoginCaptcha for admin login verification
- Add EnableUserResetPasswordCaptcha for password reset verification
- Remove deprecated EnableLoginVerify, EnableRegisterVerify, EnableResetPasswordVerify fields
- Support rollback with down migration
- Add captcha service interface with Generate and Verify methods
- Implement local image captcha using base64Captcha library
- Implement Cloudflare Turnstile verification wrapper
- Support Redis-based captcha storage with 5-minute expiration
- Add factory method for creating captcha service instances
- Node group CRUD operations with traffic-based filtering
- Three grouping modes: average distribution, subscription-based, and traffic-based
- Automatic and manual group recalculation with history tracking
- Group assignment preview before applying changes
- User subscription group locking to prevent automatic reassignment
- Subscribe-to-group mapping configuration
- Group calculation history and detailed reports
- System configuration for group management (enabled/mode/auto_create)
Database:
- Add node_group table for group definitions
- Add group_history and group_history_detail tables for tracking
- Add node_group_ids (JSON) to nodes and subscribe tables
- Add node_group_id and group_locked fields to user_subscribe table
- Add migration files for schema changes
When administrators update subscription plan configurations (traffic limits,
nodes, speed limits, etc.), existing subscribers were not seeing the updated
settings immediately. This was caused by stale cache entries that were not
being invalidated.
The issue occurred because:
- User subscription queries cache the entire result including preloaded plan details
- Plan update/delete operations only cleared the plan's own cache keys
- User subscription cache keys (cache:user:subscribe:user:{userId}) remained stale
This fix ensures that when a subscription plan is updated or deleted, all
associated user subscription caches are properly invalidated by:
- Querying all active users subscribed to the plan
- Building cache keys for each affected user
- Clearing both plan and user subscription caches atomically
Users will now immediately see updated plan configurations without waiting
for cache expiration.
Remove IF NOT EXISTS clause from CREATE INDEX statement to ensure
compatibility with older MySQL versions. Migration framework ensures
each migration runs only once, making the clause unnecessary.
Change ALTER TABLE ADD INDEX IF NOT EXISTS to CREATE INDEX IF NOT EXISTS
to comply with MySQL syntax requirements. The IF NOT EXISTS clause is
only supported with CREATE INDEX statement, not with ALTER TABLE ADD INDEX.
- Check if release exists before creating
- Delete old assets if they exist
- Use --clobber flag to overwrite existing assets
- Prevent 'already exists' errors on tag force-push
This commit addresses critical issues in the redemption code activation flow
to ensure data consistency, prevent duplicate redemptions, and improve user
experience.
Key improvements:
1. Transaction Safety (P0)
- Wrap subscription creation, used count update, and record insertion in
a single database transaction
- Ensure atomicity: all operations succeed or all rollback
- Prevent orphaned records and data inconsistencies
2. Idempotency Protection (P0)
- Add redemption record check before processing to prevent duplicate
operations on queue task retries
- Maintain idempotency at multiple layers: interface, order, and record
3. Distributed Lock (P1)
- Implement Redis-based distributed lock (10s timeout) to prevent
concurrent duplicate redemptions
- Lock key format: redemption_lock:{user_id}:{code}
4. IsNew Field Correction (P2)
- Fix IsNew field to correctly determine first-time purchases using
IsUserEligibleForNewOrder method
- Ensure accurate statistics and future commission calculations
5. Quota Pre-check (P2)
- Add quota validation at interface layer for immediate user feedback
- Prevent "processing" status followed by eventual failure
6. Extended Cache TTL (P2)
- Increase Redis cache expiration from 30 minutes to 2 hours
- Ensure queue tasks can retrieve redemption data even with delays
7. Error Handling (P2)
- Clean up Order records when Redis cache or queue enqueue fails
- Prevent orphaned Order records in the database
8. Cache Clearing Optimization
- Add user subscription cache clearing after activation
- Ensure both node-side and user-side display latest subscription info
Technical details:
- Modified: internal/logic/public/redemption/redeemCodeLogic.go
- Modified: queue/logic/order/activateOrderLogic.go
- Modified: internal/model/redemption/default.go (transaction support)
Testing:
- All changes compiled successfully
- Comprehensive flow verification completed
- Ready for production deployment
BREAKING CHANGE: None
This commit fixes the inconsistent calculation logic between order preview
and actual order creation, which caused balance payment failures when using
coupons.
Changes:
- Standardized fee calculation order in both preCreateOrderLogic and purchaseLogic
- Moved gift amount deduction after fee calculation to ensure correct total
- Removed premature gift amount deduction before transaction in purchaseLogic
- Gift amount is now only deducted within the database transaction
The calculation order is now unified:
1. Apply coupon discount
2. Calculate handling fee based on post-coupon amount
3. Deduct gift amount from total (including fee)
This ensures the preview amount matches the actual payment amount.
When new users register with trial subscription enabled, the subscription
link fails to connect in Clash clients. This is caused by missing cache
invalidation after transaction commit.
Changes:
- Add cache clearing after successful trial subscription creation
- Clear user subscription cache, subscription details cache, and server cache
- Modify activeTrial functions to return subscription object for cache clearing
- Apply fix to all registration methods: email, phone, device, and OAuth
This ensures subscription links work immediately after registration without
requiring manual subscription reset.
- Fix task error handling: return actual errors instead of nil to enable retry
- Add idempotency check: skip processing for already finished orders
- Extend temp order cache: increase from 15 minutes to 24 hours
- Configure retry policy: add MaxRetry(5) for all payment callbacks (Epay, Alipay, Stripe)
This fixes the critical issue where paid orders were being lost due to:
1. Failed tasks being marked as successful and deleted from queue
2. Temporary order info expiring before queue processing
3. No retry mechanism for transient failures
Changes:
- queue/logic/order/activateOrderLogic.go: Fix error returns and add idempotency
- internal/logic/public/portal/purchaseLogic.go: Extend cache to 24 hours
- internal/logic/notify/*NotifyLogic.go: Add retry configuration
- Add quota check in preCreateOrderLogic for order preview
- Move quota check inside transaction in purchaseLogic to prevent race condition
- Add quota check in activateOrderLogic as final safeguard when creating subscription
- Add quota check in redeemCodeLogic when redeeming codes for new subscriptions
- Add optional short_code parameter to DeviceLoginRequest
- Add ShortCode field to Device model
- Save short_code to database during device registration
- Add database migration for user_device.short_code column
- Fix duplicate variable declaration in routes.go