"frontend/git@web.lueluesay.top:chenxi/sub2api.git" did not exist on "85fc54b2051999fd778f255b8bc37e7729032f50"
- 19 Apr, 2026 1 commit
-
-
erio authored
Add quota exceeded check to IsSchedulable() and refactor shouldClearStickySession to delegate to IsSchedulable(), eliminating duplicated logic and fixing missed overload/rate-limit/expired checks. Frontend displays quota exceeded status independently via quota fields.
-
- 18 Apr, 2026 2 commits
-
-
erio authored
Admin GET /api/v1/admin/payment/providers previously returned every config value — including privateKey / apiV3Key / secretKey etc. — verbatim. Any future XSS on the admin UI would hand attackers the full set of production payment credentials, and the plaintext values sat unnecessarily in browser memory for every operator. Treat those fields as write-only from the admin surface: - decryptAndMaskConfig() strips sensitive keys from the GET response. The authoritative list is an explicit per-provider registry that mirrors the frontend's PROVIDER_CONFIG_FIELDS sensitive flag: alipay → privateKey, publicKey, alipayPublicKey wxpay → privateKey, apiV3Key, publicKey stripe → secretKey, webhookSecret (publishableKey stays plain) easypay → pkey Payment runtime still reads the full config via decryptConfig, so nothing at the gateway changes. - mergeConfig() treats an empty value for a sensitive key as "leave unchanged" — the admin UI omits unchanged secrets so operators can tweak non-sensitive settings without re-entering credentials. - Admin dialog (PaymentProviderDialog.vue): * secret inputs get autocomplete="new-password", data-1p-ignore, data-lpignore and data-bwignore so password managers do not offer to save provider credentials * in edit mode the required-field check skips sensitive fields (empty is the "keep existing" signal) and the placeholder shows "leave empty to keep" instead of the default example value * create mode still requires every non-optional field, including secrets, since there is nothing to preserve - Unit test renamed to TestIsSensitiveProviderConfigField, covers the per-provider registry and specifically asserts that Stripe's publishableKey is NOT treated as a secret. -
erio authored
The native Alipay provider previously tried to embed the payment page URL into a QR code on the client — the URL is not a scannable payload so the QR never worked. Merchants also hit a H5 detection mismatch whenever the backend UA sniffer missed iPadOS 13+ or embedded browsers, and the popup window was too small for Alipay's standard checkout layout (QR + account-login panel on the right), forcing the user to scroll horizontally and vertically. Changes: Backend - alipay.go: drop QR-on-URL path. Use redirect-only flow — alipay.trade.page.pay for PC (returns a gateway URL the browser opens in a new window) and alipay.trade.wap.pay for H5 (returns a URL the browser jumps to). Both flows produce pages on openapi.alipaydev.com / excashier.alipay.com; the client never renders a QR itself. - payment_handler.go: add optional is_mobile bool to CreateOrderRequest so the frontend can declare the device explicitly. Server still falls back to UA sniffing when absent. Frontend - types/payment.ts, PaymentView.vue: declare is_mobile in CreateOrderRequest and pass the computed isMobileDevice() value. - providerConfig.ts: replace the two fixed POPUP_WINDOW_FEATURES constants with getPaymentPopupFeatures(), which prefers 1250×900 (Alipay's checkout footprint), clamps to window.screen.avail* and centers the popup so it never overflows on smaller laptops. - PaymentQRDialog.vue, PaymentStatusPanel.vue, StripePaymentInline.vue, PaymentView.vue: use the new helper at all popup call sites.
-
- 17 Apr, 2026 3 commits
-
-
erio authored
分组倍率和用户专属倍率在保存时没有校验,0 会触发计费层的 `<=0 → 1.0` 防御条款,结果订阅/余额分组按标准价扣费;完全是沉默地绕过了业务规则。 - 保存校验(admin_service):CreateGroup / UpdateGroup / BatchSetGroupRateMultipliers / UpdateUser.SyncUserGroupRates 全部要求 > 0 - 计算层(billing_service):三处 `<=0 → 1.0` 改为 `<0 → 0`;负数按 0 结算, 避免配置异常被静默按 1x 收费 - 前端:分组倍率 / 用户专属倍率输入 min 统一到 0.001 - 删除未使用的 IsFreeSubscription 方法 测试:新增 billing_service_rate_multiplier_test.go 端到端验证;更新原有锁定 旧 `<=0 → 1.0` 行为的测试。
-
erio authored
Chrome's password manager matched the apikey-type account's Base URL + API Key inputs as a login form and autofilled the last saved password by domain, so editing a Gemini account could overwrite its apikey with a Claude key that shared the same Base URL. Add autocomplete="new-password" plus data-*-ignore attributes for 1Password / LastPass / Bitwarden to opt the field out of every major password manager's autofill.
-
shaw authored
-
- 16 Apr, 2026 1 commit
-
-
KnowSky404 authored
-
- 15 Apr, 2026 6 commits
-
-
erio authored
-
erio authored
- Cost cell: change gray "A $xxx" to orange "成本 $xxx" with i18n - Remove standalone account_cost column from column settings (redundant)
-
erio authored
- UserBreakdownItem: add AccountCost field + SQL aggregation - UserBreakdownSubTable: add orange account cost column - Admin usage table: add account_cost column (after cost, default visible) - Column settings: add account_cost toggle option
-
erio authored
-
erio authored
- Add account_cost column to dashboard aggregation tables (migration 107) - DashboardStats: add TotalAccountCost/TodayAccountCost fields - ModelStat/GroupStat: add AccountCost field with SQL aggregation - GetStatsWithFilters: always return TotalAccountCost (remove accountID filter) - Dashboard Token cards: show user(green)/cost(orange)/standard(gray) - Usage stats card: show account cost and standard below main value - Model/Group distribution tables: add orange cost column
-
erio authored
Replace dead EventSource variable with AbortController to enable cancelling fetch streams. Remove close-button disable during connecting status so users can dismiss the dialog at any time.
-
- 14 Apr, 2026 27 commits
-
-
erio authored
- Show base amount (充值金额) as first line - Show fee amount with percentage when fee_rate > 0 - Show pay_amount (实付金额) in bold primary color - Show credited amount (到账金额) when different from pay_amount - Compute baseAmount and feeAmount from backend order data
-
erio authored
Backend: - Validate recharge_fee_rate: 0 ≤ rate ≤ 100, max 2 decimal places Frontend settings: - Add % suffix icon to fee rate input - Enforce max=100, min=0, step=0.01 with 2 decimal precision
-
erio authored
Backend: - Use cfg.RechargeFeeRate in order creation instead of hardcoded 0 - Remove dead getFeeRate stub method - All amounts computed server-side: order_amount, pay_amount, fee_rate Frontend - PaymentView: - Read recharge_fee_rate from checkout-info API (not per-method) - Show fee breakdown only when fee_rate > 0 - Show credited amount only when multiplier ≠ 1 Frontend - Order display (user + admin): - Fix fee_rate * 100 bug (fee_rate is already a percentage) - OrderTable: show pay_amount as primary, fee/credited as sub-lines - AdminOrderDetail: full breakdown (base/fee/paid/credited) - AdminRefundDialog: label "到账金额" for clarity - PaymentResultView: show pay_amount with fee info Types + i18n: - Add recharge_fee_rate to CheckoutInfoResponse - Add fee_rate to CreateOrderResult - Add translations: creditedAmount, fee, baseAmount, includedInPayAmount
-
erio authored
- Add recharge_fee_rate system setting (percentage fee on top of recharge amount) - Full backend chain: config constant, PaymentConfig struct, update validation, read/write persistence, DTO, handler GET/PUT responses - Frontend: settings input with preview, i18n (zh/en), API types - Fix provider card toggle layout: labels above switches to save width - Fix Chinese translation: "EasyPay" → "易支付" in provider description
-
erio authored
- Add balance_recharge_multiplier system setting (e.g. 1.2 = charge 100 get 120) - Separate order_amount (credited balance) from pay_amount (actual payment) - Refund calculates gateway amount proportionally from pay_amount - Frontend shows both amounts in order details, payment status, refund dialog - Admin settings UI for configuring recharge multiplier
-
erio authored
- Fix flaky WebSocket passthrough test: allow StatusNormalClosure after client close instead of requiring NoError (race condition fix) - Fix ratelimit 401 test: use PlatformOpenAI instead of PlatformGemini for OAuth token cache invalidation scenario (more accurate) - Add usageLoadQueue: Anthropic OAuth/setup-token accounts sharing the same proxy exit are serialized with 1-2s jitter to prevent upstream 429 - AccountUsageCell: add module-level usage cache (5min TTL), unmounted safety guard, and integrate enqueueUsageRequest for throttled fetching
-
erio authored
Replace dialog-based payment with inline state flow (select → paying/stripe). - PaymentStatusPanel replaces QR dialog for scan-to-pay - StripePaymentInline replaces Stripe popup - Subscription confirm as inline card instead of modal - Payment button color follows payment method - Renewal modal with URL parameter navigation (?tab=subscription&group=123) - Mobile auto-redirect for H5 payment - AmountInput uses global min/max instead of per-method - Tab auto-hides during payment - Restore CNY (¥) currency for upstream compatibility
-
erio authored
Extract repeated badge template (SVG icon + current/max display) into a reusable CapacityBadge component. Reduces AccountCapacityCell from ~300 lines to ~180 lines with identical behavior.
-
erio authored
Backend: - gateway_handler: pass subject.UserID instead of int64(0) for user-level routing - setting_handler: add missing BalanceLowNotifyRechargeURL to UpdateSettings response - openai_gateway_service: use applyAccountStatsCost for account stats pricing integration - embed_on: add local file override (data/public/) for embedded frontend assets Frontend: - useTableSelection: add batchUpdate method for batch operations - AccountsView: virtual scrolling params, Set-based isSelected, swipe virtualization - ProxiesView: add batchUpdate to selection and swipe-select - BulkEditAccountModal: fix submit handler to prevent event object as argument - SettingsView: move payload construction outside try block - i18n: add general translation keys (saved, deleted, view, validation, allowUserRefund) - api/client: reorder error fields for consistency - stores/payment: clarify pollOrderStatus JSDoc
-
erio authored
Bug fixes: - Detached context for GetAccountConcurrencyBatch (prevent all-zero on request cancel) - Filter soft-deleted users in GetByGroupID - Stripe CSP policy (allow Stripe.js in script-src and frame-src) - WebSearch API key validation on save - RECHARGING status in payment result success check - Windows test fixes (logger Sync deadlock, config path escaping) Feature enhancements: - Webhook multi-instance dispatch (extractOutTradeNo + GetWebhookProvider) - EasyPay mobile H5 payment (device param + PayURL2) - SSE error propagation in WebSearch emulation - AccountStatsCost DTO field for admin usage logs - Plans sort by sort_order instead of created_at - UsageMapHook for streaming response usage data - apicompat Instructions field passthrough - EffectiveLoadFactor for ops concurrency/metrics - Usage billing RETURNING balance for notify system - BulkUpdate mixed channel warning with details - println to slog migration in auth cache - Wire ProviderSet cleanup - CI cache-dependency-path optimization Frontend: - Refund eligibility check per provider (canRequestRefund) - Plan sort_order editing - Dead code cleanup (simulate_claude_max, client_affinity) - GroupsView platform switch guard - channels features_config API type - UsageView account_stats_cost export
-
erio authored
allow_user_refund: - Add allow_user_refund field to PaymentProviderInstance ent schema - Migration 103: ALTER TABLE payment_provider_instances ADD COLUMN - Cascade logic: disabling refund_enabled auto-disables allow_user_refund - User refund validation: check provider instance allows user refund - Admin refund validation: check provider instance allows admin refund - Subscription refund: deduct days on refund, rollback on failure - New endpoint: GET /payment/orders/refund-eligible-providers - Frontend: ToggleSwitch in ProviderCard/Dialog, cascade in SettingsView Wildcard matching: - Change findPricingForModel from "longest prefix wins" to "config order priority (first match wins)", aligning with channel service behavior
-
erio authored
- QuotaLimit changed to *int64 (null=unlimited, >0=limited) - Add reset-usage endpoint (POST /admin/settings/web-search-emulation/reset-usage) - Show quota usage in header always (collapsed and expanded) - Add reset quota button in expanded provider view - Quota input: empty=unlimited with ∞ placeholder, must be >0 if set - Add email verification hint on balance notify card
-
erio authored
The buttons were hidden because v-if only checked provider.api_key, which is always empty for saved providers (backend sanitizes it). Now also checks api_key_configured. Copy button is disabled when no actual key is available (only configured placeholder shown).
-
erio authored
- Skip websearch provider when ProxyID is set but proxy not found (prevent silent direct connection bypass) - Fix sortByStableRandomWeight: pair factors with items so sort.Slice swap keeps weights aligned - Allow empty platform in account_stats_pricing_rules (wildcard matching), only force anthropic default for main model_pricing - Add channel_account_stats_pricing_intervals table and repo layer support for interval-based pricing in account stats rules - calculateTokenStatsCost now uses interval pricing when available - Replace smtp.SendMail/tls.Dial with net.Dialer timeout (10s dial, 20s IO) to prevent goroutine leak on SMTP hang - Fix gofmt formatting issues - Web Search label: black text with red warning hint
-
erio authored
- Fix web_search_emulation toggle: explicitly write false for disabled platforms instead of leaving stale true from cloned features_config - Extract validatePricingEntries from validateChannelConfig for reuse - Validate account_stats_pricing_rules[].pricing in both Create and Update paths (negative prices, bad intervals, missing per_request price)
-
erio authored
Security (HIGH): - Normalize all Redis cache keys to lowercase (verifyCode, passwordReset) - Fix verify code TTL renewal on failed attempts: use remaining TTL via ExpiresAt field instead of resetting to full 15-minute window - Add 3 missing fields to diffSettings audit log (promo_code, invitation_code, custom_endpoints) Code quality (MEDIUM): - Extract filterVerifiedEmails shared helper (balance_notify_service.go) - Add Pricing array non-empty validation for channel pricing rules - Add platform token semantics comment in gateway_service.go - Complete validatePlanPatch test coverage (+10 test cases) - Replace string types with QuotaThresholdType/QuotaResetMode across frontend - Remove duplicate getPlatformTextColor/getRateBadgeClass in ChannelsView - Return EMAIL_NOT_FOUND error on RemoveNotifyEmail miss UI improvements: - Reorder cost tooltip: user billing above separator, account billing below - Add NaN guard to accountBilled function - Move timezone selector inline into reset-mode row (no longer standalone)
-
erio authored
- Fix websearch provider failover: proxy error from provider-specific proxy now continues to next provider instead of aborting the entire loop - Fix SMTP failure locking users out: send email first, then write cache and increment rate counter - Fix notify email cache key case sensitivity: normalize to lowercase - Add OriginalPrice validation to validatePlanPatch and validatePlanRequired - Add empty scope validation for channel pricing rules (group_ids/account_ids) - Add platform color to account search dropdown in channel pricing rules
-
erio authored
M5: New composable frontend/src/composables/useQuotaNotifyState.ts - Replaces 9 individual refs in both Create/Edit modals with reactive state - Provides loadFromExtra/writeToExtra/reset helpers - Eliminates ~120 lines of duplicated code across the two modals H14: Vue file length violations fixed - AdminPaymentPlansView.vue: 325 → 183 lines (extracted PlanEditDialog.vue) - QuotaLimitCard.vue: 327 → 268 lines (extracted QuotaDimensionRow.vue) - PlanEditDialog.vue: 181 lines (new, plan create/edit form) - QuotaDimensionRow.vue: 108 lines (new, single quota dimension row)
-
erio authored
H5: diffSettings now tracks 5 balance/quota notify fields in audit log M15: log.Printf audit log migrated to slog.Info, removed "log" import M14: New frontend/src/constants/account.ts with shared constants QuotaNotifyToggle.vue uses QUOTA_THRESHOLD_TYPE_FIXED/PERCENTAGE L2: UsageTable.vue uses BILLING_MODE_TOKEN/IMAGE from billingMode.ts -
erio authored
fix: batch 1 audit fixes — quota SQL fixed mode, public recharge URL, WebSearch bool fallback, UpdatePlan validation H1: incrementUsageBillingAccountQuota now uses shared dailyExpiredExpr/weeklyExpiredExpr constants (supporting fixed reset mode) instead of hardcoded '24 hours'/'168 hours' H4: public settings endpoint now maps balance_low_notify_recharge_url H6: GetWebSearchEmulationMode tolerates legacy bool values (true→enabled) H7: UpdatePlan validates non-nil patch fields (rejects negative price, empty name, etc.) H8: UsageTable accountBilled() helper with total_cost ?? 0 null guard H9: AdminUsageLog TS type adds channel_id + billing_tier M2: account.go "fixed" literals replaced with thresholdTypeFixed constant M13: SystemSettings TS type adds web_search_emulation_enabled UI: QuotaLimitCard title labels now use flex-1 to align with flex-1 input boxes -
erio authored
- EditAccountModal width changed from "normal" to "wide" (match CreateAccountModal) - CreateAccountModal now passes all quota notify props to QuotaLimitCard - QuotaLimitCard: when global notify disabled, hide title row, input takes full width - Quota alert email: show remaining quota + threshold (fixed/$, percentage/%) instead of usage trigger point
-
erio authored
-
erio authored
-
erio authored
- Quota alert email now shows account ID and platform - Balance low email includes a "Top Up Now" button when recharge URL is configured - New setting: balance_low_notify_recharge_url in admin settings
-
erio authored
-
erio authored
Threshold now represents remaining quota instead of usage amount: - Fixed ($): threshold=400, limit=1000 → alert when remaining drops to $400 (i.e., usage reaches $600) - Percentage (%): threshold=30%, limit=1000 → alert when remaining drops to 30% (i.e., usage reaches $700) Also: - Rename 告警阈值 → 提醒阈值 in i18n - Widen type dropdown to w-16 for proper $ / % display
-
erio authored
Move QuotaNotifyToggle to the same row as the limit $ input for all three dimensions (daily/weekly/total), significantly reducing card height.
-