feat(promo-code): complete promo code feature implementation
- Add promo_code_enabled field to SystemSettings and PublicSettings DTOs - Add promo code validation in registration flow - Add admin settings UI for promo code configuration - Add i18n translations for promo code feature
This commit is contained in:
@@ -47,6 +47,7 @@ func (h *SettingHandler) GetSettings(c *gin.Context) {
|
|||||||
response.Success(c, dto.SystemSettings{
|
response.Success(c, dto.SystemSettings{
|
||||||
RegistrationEnabled: settings.RegistrationEnabled,
|
RegistrationEnabled: settings.RegistrationEnabled,
|
||||||
EmailVerifyEnabled: settings.EmailVerifyEnabled,
|
EmailVerifyEnabled: settings.EmailVerifyEnabled,
|
||||||
|
PromoCodeEnabled: settings.PromoCodeEnabled,
|
||||||
SMTPHost: settings.SMTPHost,
|
SMTPHost: settings.SMTPHost,
|
||||||
SMTPPort: settings.SMTPPort,
|
SMTPPort: settings.SMTPPort,
|
||||||
SMTPUsername: settings.SMTPUsername,
|
SMTPUsername: settings.SMTPUsername,
|
||||||
@@ -90,6 +91,7 @@ type UpdateSettingsRequest struct {
|
|||||||
// 注册设置
|
// 注册设置
|
||||||
RegistrationEnabled bool `json:"registration_enabled"`
|
RegistrationEnabled bool `json:"registration_enabled"`
|
||||||
EmailVerifyEnabled bool `json:"email_verify_enabled"`
|
EmailVerifyEnabled bool `json:"email_verify_enabled"`
|
||||||
|
PromoCodeEnabled bool `json:"promo_code_enabled"`
|
||||||
|
|
||||||
// 邮件服务设置
|
// 邮件服务设置
|
||||||
SMTPHost string `json:"smtp_host"`
|
SMTPHost string `json:"smtp_host"`
|
||||||
@@ -240,6 +242,7 @@ func (h *SettingHandler) UpdateSettings(c *gin.Context) {
|
|||||||
settings := &service.SystemSettings{
|
settings := &service.SystemSettings{
|
||||||
RegistrationEnabled: req.RegistrationEnabled,
|
RegistrationEnabled: req.RegistrationEnabled,
|
||||||
EmailVerifyEnabled: req.EmailVerifyEnabled,
|
EmailVerifyEnabled: req.EmailVerifyEnabled,
|
||||||
|
PromoCodeEnabled: req.PromoCodeEnabled,
|
||||||
SMTPHost: req.SMTPHost,
|
SMTPHost: req.SMTPHost,
|
||||||
SMTPPort: req.SMTPPort,
|
SMTPPort: req.SMTPPort,
|
||||||
SMTPUsername: req.SMTPUsername,
|
SMTPUsername: req.SMTPUsername,
|
||||||
@@ -314,6 +317,7 @@ func (h *SettingHandler) UpdateSettings(c *gin.Context) {
|
|||||||
response.Success(c, dto.SystemSettings{
|
response.Success(c, dto.SystemSettings{
|
||||||
RegistrationEnabled: updatedSettings.RegistrationEnabled,
|
RegistrationEnabled: updatedSettings.RegistrationEnabled,
|
||||||
EmailVerifyEnabled: updatedSettings.EmailVerifyEnabled,
|
EmailVerifyEnabled: updatedSettings.EmailVerifyEnabled,
|
||||||
|
PromoCodeEnabled: updatedSettings.PromoCodeEnabled,
|
||||||
SMTPHost: updatedSettings.SMTPHost,
|
SMTPHost: updatedSettings.SMTPHost,
|
||||||
SMTPPort: updatedSettings.SMTPPort,
|
SMTPPort: updatedSettings.SMTPPort,
|
||||||
SMTPUsername: updatedSettings.SMTPUsername,
|
SMTPUsername: updatedSettings.SMTPUsername,
|
||||||
|
|||||||
@@ -195,6 +195,15 @@ type ValidatePromoCodeResponse struct {
|
|||||||
// ValidatePromoCode 验证优惠码(公开接口,注册前调用)
|
// ValidatePromoCode 验证优惠码(公开接口,注册前调用)
|
||||||
// POST /api/v1/auth/validate-promo-code
|
// POST /api/v1/auth/validate-promo-code
|
||||||
func (h *AuthHandler) ValidatePromoCode(c *gin.Context) {
|
func (h *AuthHandler) ValidatePromoCode(c *gin.Context) {
|
||||||
|
// 检查优惠码功能是否启用
|
||||||
|
if h.settingSvc != nil && !h.settingSvc.IsPromoCodeEnabled(c.Request.Context()) {
|
||||||
|
response.Success(c, ValidatePromoCodeResponse{
|
||||||
|
Valid: false,
|
||||||
|
ErrorCode: "PROMO_CODE_DISABLED",
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
var req ValidatePromoCodeRequest
|
var req ValidatePromoCodeRequest
|
||||||
if err := c.ShouldBindJSON(&req); err != nil {
|
if err := c.ShouldBindJSON(&req); err != nil {
|
||||||
response.BadRequest(c, "Invalid request: "+err.Error())
|
response.BadRequest(c, "Invalid request: "+err.Error())
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ package dto
|
|||||||
type SystemSettings struct {
|
type SystemSettings struct {
|
||||||
RegistrationEnabled bool `json:"registration_enabled"`
|
RegistrationEnabled bool `json:"registration_enabled"`
|
||||||
EmailVerifyEnabled bool `json:"email_verify_enabled"`
|
EmailVerifyEnabled bool `json:"email_verify_enabled"`
|
||||||
|
PromoCodeEnabled bool `json:"promo_code_enabled"`
|
||||||
|
|
||||||
SMTPHost string `json:"smtp_host"`
|
SMTPHost string `json:"smtp_host"`
|
||||||
SMTPPort int `json:"smtp_port"`
|
SMTPPort int `json:"smtp_port"`
|
||||||
@@ -55,6 +56,7 @@ type SystemSettings struct {
|
|||||||
type PublicSettings struct {
|
type PublicSettings struct {
|
||||||
RegistrationEnabled bool `json:"registration_enabled"`
|
RegistrationEnabled bool `json:"registration_enabled"`
|
||||||
EmailVerifyEnabled bool `json:"email_verify_enabled"`
|
EmailVerifyEnabled bool `json:"email_verify_enabled"`
|
||||||
|
PromoCodeEnabled bool `json:"promo_code_enabled"`
|
||||||
TurnstileEnabled bool `json:"turnstile_enabled"`
|
TurnstileEnabled bool `json:"turnstile_enabled"`
|
||||||
TurnstileSiteKey string `json:"turnstile_site_key"`
|
TurnstileSiteKey string `json:"turnstile_site_key"`
|
||||||
SiteName string `json:"site_name"`
|
SiteName string `json:"site_name"`
|
||||||
|
|||||||
@@ -153,8 +153,8 @@ func (s *AuthService) RegisterWithVerification(ctx context.Context, email, passw
|
|||||||
return "", nil, ErrServiceUnavailable
|
return "", nil, ErrServiceUnavailable
|
||||||
}
|
}
|
||||||
|
|
||||||
// 应用优惠码(如果提供)
|
// 应用优惠码(如果提供且功能已启用)
|
||||||
if promoCode != "" && s.promoService != nil {
|
if promoCode != "" && s.promoService != nil && s.settingService != nil && s.settingService.IsPromoCodeEnabled(ctx) {
|
||||||
if err := s.promoService.ApplyPromoCode(ctx, user.ID, promoCode); err != nil {
|
if err := s.promoService.ApplyPromoCode(ctx, user.ID, promoCode); err != nil {
|
||||||
// 优惠码应用失败不影响注册,只记录日志
|
// 优惠码应用失败不影响注册,只记录日志
|
||||||
log.Printf("[Auth] Failed to apply promo code for user %d: %v", user.ID, err)
|
log.Printf("[Auth] Failed to apply promo code for user %d: %v", user.ID, err)
|
||||||
|
|||||||
@@ -71,6 +71,7 @@ const (
|
|||||||
// 注册设置
|
// 注册设置
|
||||||
SettingKeyRegistrationEnabled = "registration_enabled" // 是否开放注册
|
SettingKeyRegistrationEnabled = "registration_enabled" // 是否开放注册
|
||||||
SettingKeyEmailVerifyEnabled = "email_verify_enabled" // 是否开启邮件验证
|
SettingKeyEmailVerifyEnabled = "email_verify_enabled" // 是否开启邮件验证
|
||||||
|
SettingKeyPromoCodeEnabled = "promo_code_enabled" // 是否启用优惠码功能
|
||||||
|
|
||||||
// 邮件服务设置
|
// 邮件服务设置
|
||||||
SettingKeySMTPHost = "smtp_host" // SMTP服务器地址
|
SettingKeySMTPHost = "smtp_host" // SMTP服务器地址
|
||||||
|
|||||||
@@ -60,6 +60,7 @@ func (s *SettingService) GetPublicSettings(ctx context.Context) (*PublicSettings
|
|||||||
keys := []string{
|
keys := []string{
|
||||||
SettingKeyRegistrationEnabled,
|
SettingKeyRegistrationEnabled,
|
||||||
SettingKeyEmailVerifyEnabled,
|
SettingKeyEmailVerifyEnabled,
|
||||||
|
SettingKeyPromoCodeEnabled,
|
||||||
SettingKeyTurnstileEnabled,
|
SettingKeyTurnstileEnabled,
|
||||||
SettingKeyTurnstileSiteKey,
|
SettingKeyTurnstileSiteKey,
|
||||||
SettingKeySiteName,
|
SettingKeySiteName,
|
||||||
@@ -88,6 +89,7 @@ func (s *SettingService) GetPublicSettings(ctx context.Context) (*PublicSettings
|
|||||||
return &PublicSettings{
|
return &PublicSettings{
|
||||||
RegistrationEnabled: settings[SettingKeyRegistrationEnabled] == "true",
|
RegistrationEnabled: settings[SettingKeyRegistrationEnabled] == "true",
|
||||||
EmailVerifyEnabled: settings[SettingKeyEmailVerifyEnabled] == "true",
|
EmailVerifyEnabled: settings[SettingKeyEmailVerifyEnabled] == "true",
|
||||||
|
PromoCodeEnabled: settings[SettingKeyPromoCodeEnabled] != "false", // 默认启用
|
||||||
TurnstileEnabled: settings[SettingKeyTurnstileEnabled] == "true",
|
TurnstileEnabled: settings[SettingKeyTurnstileEnabled] == "true",
|
||||||
TurnstileSiteKey: settings[SettingKeyTurnstileSiteKey],
|
TurnstileSiteKey: settings[SettingKeyTurnstileSiteKey],
|
||||||
SiteName: s.getStringOrDefault(settings, SettingKeySiteName, "Sub2API"),
|
SiteName: s.getStringOrDefault(settings, SettingKeySiteName, "Sub2API"),
|
||||||
@@ -125,6 +127,7 @@ func (s *SettingService) GetPublicSettingsForInjection(ctx context.Context) (any
|
|||||||
return &struct {
|
return &struct {
|
||||||
RegistrationEnabled bool `json:"registration_enabled"`
|
RegistrationEnabled bool `json:"registration_enabled"`
|
||||||
EmailVerifyEnabled bool `json:"email_verify_enabled"`
|
EmailVerifyEnabled bool `json:"email_verify_enabled"`
|
||||||
|
PromoCodeEnabled bool `json:"promo_code_enabled"`
|
||||||
TurnstileEnabled bool `json:"turnstile_enabled"`
|
TurnstileEnabled bool `json:"turnstile_enabled"`
|
||||||
TurnstileSiteKey string `json:"turnstile_site_key,omitempty"`
|
TurnstileSiteKey string `json:"turnstile_site_key,omitempty"`
|
||||||
SiteName string `json:"site_name"`
|
SiteName string `json:"site_name"`
|
||||||
@@ -140,6 +143,7 @@ func (s *SettingService) GetPublicSettingsForInjection(ctx context.Context) (any
|
|||||||
}{
|
}{
|
||||||
RegistrationEnabled: settings.RegistrationEnabled,
|
RegistrationEnabled: settings.RegistrationEnabled,
|
||||||
EmailVerifyEnabled: settings.EmailVerifyEnabled,
|
EmailVerifyEnabled: settings.EmailVerifyEnabled,
|
||||||
|
PromoCodeEnabled: settings.PromoCodeEnabled,
|
||||||
TurnstileEnabled: settings.TurnstileEnabled,
|
TurnstileEnabled: settings.TurnstileEnabled,
|
||||||
TurnstileSiteKey: settings.TurnstileSiteKey,
|
TurnstileSiteKey: settings.TurnstileSiteKey,
|
||||||
SiteName: settings.SiteName,
|
SiteName: settings.SiteName,
|
||||||
@@ -162,6 +166,7 @@ func (s *SettingService) UpdateSettings(ctx context.Context, settings *SystemSet
|
|||||||
// 注册设置
|
// 注册设置
|
||||||
updates[SettingKeyRegistrationEnabled] = strconv.FormatBool(settings.RegistrationEnabled)
|
updates[SettingKeyRegistrationEnabled] = strconv.FormatBool(settings.RegistrationEnabled)
|
||||||
updates[SettingKeyEmailVerifyEnabled] = strconv.FormatBool(settings.EmailVerifyEnabled)
|
updates[SettingKeyEmailVerifyEnabled] = strconv.FormatBool(settings.EmailVerifyEnabled)
|
||||||
|
updates[SettingKeyPromoCodeEnabled] = strconv.FormatBool(settings.PromoCodeEnabled)
|
||||||
|
|
||||||
// 邮件服务设置(只有非空才更新密码)
|
// 邮件服务设置(只有非空才更新密码)
|
||||||
updates[SettingKeySMTPHost] = settings.SMTPHost
|
updates[SettingKeySMTPHost] = settings.SMTPHost
|
||||||
@@ -248,6 +253,15 @@ func (s *SettingService) IsEmailVerifyEnabled(ctx context.Context) bool {
|
|||||||
return value == "true"
|
return value == "true"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsPromoCodeEnabled 检查是否启用优惠码功能
|
||||||
|
func (s *SettingService) IsPromoCodeEnabled(ctx context.Context) bool {
|
||||||
|
value, err := s.settingRepo.GetValue(ctx, SettingKeyPromoCodeEnabled)
|
||||||
|
if err != nil {
|
||||||
|
return true // 默认启用
|
||||||
|
}
|
||||||
|
return value != "false"
|
||||||
|
}
|
||||||
|
|
||||||
// GetSiteName 获取网站名称
|
// GetSiteName 获取网站名称
|
||||||
func (s *SettingService) GetSiteName(ctx context.Context) string {
|
func (s *SettingService) GetSiteName(ctx context.Context) string {
|
||||||
value, err := s.settingRepo.GetValue(ctx, SettingKeySiteName)
|
value, err := s.settingRepo.GetValue(ctx, SettingKeySiteName)
|
||||||
@@ -297,6 +311,7 @@ func (s *SettingService) InitializeDefaultSettings(ctx context.Context) error {
|
|||||||
defaults := map[string]string{
|
defaults := map[string]string{
|
||||||
SettingKeyRegistrationEnabled: "true",
|
SettingKeyRegistrationEnabled: "true",
|
||||||
SettingKeyEmailVerifyEnabled: "false",
|
SettingKeyEmailVerifyEnabled: "false",
|
||||||
|
SettingKeyPromoCodeEnabled: "true", // 默认启用优惠码功能
|
||||||
SettingKeySiteName: "Sub2API",
|
SettingKeySiteName: "Sub2API",
|
||||||
SettingKeySiteLogo: "",
|
SettingKeySiteLogo: "",
|
||||||
SettingKeyDefaultConcurrency: strconv.Itoa(s.cfg.Default.UserConcurrency),
|
SettingKeyDefaultConcurrency: strconv.Itoa(s.cfg.Default.UserConcurrency),
|
||||||
@@ -328,6 +343,7 @@ func (s *SettingService) parseSettings(settings map[string]string) *SystemSettin
|
|||||||
result := &SystemSettings{
|
result := &SystemSettings{
|
||||||
RegistrationEnabled: settings[SettingKeyRegistrationEnabled] == "true",
|
RegistrationEnabled: settings[SettingKeyRegistrationEnabled] == "true",
|
||||||
EmailVerifyEnabled: settings[SettingKeyEmailVerifyEnabled] == "true",
|
EmailVerifyEnabled: settings[SettingKeyEmailVerifyEnabled] == "true",
|
||||||
|
PromoCodeEnabled: settings[SettingKeyPromoCodeEnabled] != "false", // 默认启用
|
||||||
SMTPHost: settings[SettingKeySMTPHost],
|
SMTPHost: settings[SettingKeySMTPHost],
|
||||||
SMTPUsername: settings[SettingKeySMTPUsername],
|
SMTPUsername: settings[SettingKeySMTPUsername],
|
||||||
SMTPFrom: settings[SettingKeySMTPFrom],
|
SMTPFrom: settings[SettingKeySMTPFrom],
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package service
|
|||||||
type SystemSettings struct {
|
type SystemSettings struct {
|
||||||
RegistrationEnabled bool
|
RegistrationEnabled bool
|
||||||
EmailVerifyEnabled bool
|
EmailVerifyEnabled bool
|
||||||
|
PromoCodeEnabled bool
|
||||||
|
|
||||||
SMTPHost string
|
SMTPHost string
|
||||||
SMTPPort int
|
SMTPPort int
|
||||||
@@ -58,6 +59,7 @@ type SystemSettings struct {
|
|||||||
type PublicSettings struct {
|
type PublicSettings struct {
|
||||||
RegistrationEnabled bool
|
RegistrationEnabled bool
|
||||||
EmailVerifyEnabled bool
|
EmailVerifyEnabled bool
|
||||||
|
PromoCodeEnabled bool
|
||||||
TurnstileEnabled bool
|
TurnstileEnabled bool
|
||||||
TurnstileSiteKey string
|
TurnstileSiteKey string
|
||||||
SiteName string
|
SiteName string
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ export interface SystemSettings {
|
|||||||
// Registration settings
|
// Registration settings
|
||||||
registration_enabled: boolean
|
registration_enabled: boolean
|
||||||
email_verify_enabled: boolean
|
email_verify_enabled: boolean
|
||||||
|
promo_code_enabled: boolean
|
||||||
// Default settings
|
// Default settings
|
||||||
default_balance: number
|
default_balance: number
|
||||||
default_concurrency: number
|
default_concurrency: number
|
||||||
@@ -64,6 +65,7 @@ export interface SystemSettings {
|
|||||||
export interface UpdateSettingsRequest {
|
export interface UpdateSettingsRequest {
|
||||||
registration_enabled?: boolean
|
registration_enabled?: boolean
|
||||||
email_verify_enabled?: boolean
|
email_verify_enabled?: boolean
|
||||||
|
promo_code_enabled?: boolean
|
||||||
default_balance?: number
|
default_balance?: number
|
||||||
default_concurrency?: number
|
default_concurrency?: number
|
||||||
site_name?: string
|
site_name?: string
|
||||||
|
|||||||
@@ -2726,7 +2726,9 @@ export default {
|
|||||||
enableRegistration: 'Enable Registration',
|
enableRegistration: 'Enable Registration',
|
||||||
enableRegistrationHint: 'Allow new users to register',
|
enableRegistrationHint: 'Allow new users to register',
|
||||||
emailVerification: 'Email Verification',
|
emailVerification: 'Email Verification',
|
||||||
emailVerificationHint: 'Require email verification for new registrations'
|
emailVerificationHint: 'Require email verification for new registrations',
|
||||||
|
promoCode: 'Promo Code',
|
||||||
|
promoCodeHint: 'Allow users to use promo codes during registration'
|
||||||
},
|
},
|
||||||
turnstile: {
|
turnstile: {
|
||||||
title: 'Cloudflare Turnstile',
|
title: 'Cloudflare Turnstile',
|
||||||
|
|||||||
@@ -2879,7 +2879,9 @@ export default {
|
|||||||
enableRegistration: '开放注册',
|
enableRegistration: '开放注册',
|
||||||
enableRegistrationHint: '允许新用户注册',
|
enableRegistrationHint: '允许新用户注册',
|
||||||
emailVerification: '邮箱验证',
|
emailVerification: '邮箱验证',
|
||||||
emailVerificationHint: '新用户注册时需要验证邮箱'
|
emailVerificationHint: '新用户注册时需要验证邮箱',
|
||||||
|
promoCode: '优惠码',
|
||||||
|
promoCodeHint: '允许用户在注册时使用优惠码'
|
||||||
},
|
},
|
||||||
turnstile: {
|
turnstile: {
|
||||||
title: 'Cloudflare Turnstile',
|
title: 'Cloudflare Turnstile',
|
||||||
|
|||||||
@@ -312,6 +312,7 @@ export const useAppStore = defineStore('app', () => {
|
|||||||
return {
|
return {
|
||||||
registration_enabled: false,
|
registration_enabled: false,
|
||||||
email_verify_enabled: false,
|
email_verify_enabled: false,
|
||||||
|
promo_code_enabled: true,
|
||||||
turnstile_enabled: false,
|
turnstile_enabled: false,
|
||||||
turnstile_site_key: '',
|
turnstile_site_key: '',
|
||||||
site_name: siteName.value,
|
site_name: siteName.value,
|
||||||
|
|||||||
@@ -70,6 +70,7 @@ export interface SendVerifyCodeResponse {
|
|||||||
export interface PublicSettings {
|
export interface PublicSettings {
|
||||||
registration_enabled: boolean
|
registration_enabled: boolean
|
||||||
email_verify_enabled: boolean
|
email_verify_enabled: boolean
|
||||||
|
promo_code_enabled: boolean
|
||||||
turnstile_enabled: boolean
|
turnstile_enabled: boolean
|
||||||
turnstile_site_key: string
|
turnstile_site_key: string
|
||||||
site_name: string
|
site_name: string
|
||||||
|
|||||||
@@ -323,6 +323,21 @@
|
|||||||
</div>
|
</div>
|
||||||
<Toggle v-model="form.email_verify_enabled" />
|
<Toggle v-model="form.email_verify_enabled" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Promo Code -->
|
||||||
|
<div
|
||||||
|
class="flex items-center justify-between border-t border-gray-100 pt-4 dark:border-dark-700"
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
<label class="font-medium text-gray-900 dark:text-white">{{
|
||||||
|
t('admin.settings.registration.promoCode')
|
||||||
|
}}</label>
|
||||||
|
<p class="text-sm text-gray-500 dark:text-gray-400">
|
||||||
|
{{ t('admin.settings.registration.promoCodeHint') }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<Toggle v-model="form.promo_code_enabled" />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -1013,6 +1028,7 @@ type SettingsForm = SystemSettings & {
|
|||||||
const form = reactive<SettingsForm>({
|
const form = reactive<SettingsForm>({
|
||||||
registration_enabled: true,
|
registration_enabled: true,
|
||||||
email_verify_enabled: false,
|
email_verify_enabled: false,
|
||||||
|
promo_code_enabled: true,
|
||||||
default_balance: 0,
|
default_balance: 0,
|
||||||
default_concurrency: 1,
|
default_concurrency: 1,
|
||||||
site_name: 'Sub2API',
|
site_name: 'Sub2API',
|
||||||
@@ -1135,6 +1151,7 @@ async function saveSettings() {
|
|||||||
const payload: UpdateSettingsRequest = {
|
const payload: UpdateSettingsRequest = {
|
||||||
registration_enabled: form.registration_enabled,
|
registration_enabled: form.registration_enabled,
|
||||||
email_verify_enabled: form.email_verify_enabled,
|
email_verify_enabled: form.email_verify_enabled,
|
||||||
|
promo_code_enabled: form.promo_code_enabled,
|
||||||
default_balance: form.default_balance,
|
default_balance: form.default_balance,
|
||||||
default_concurrency: form.default_concurrency,
|
default_concurrency: form.default_concurrency,
|
||||||
site_name: form.site_name,
|
site_name: form.site_name,
|
||||||
|
|||||||
@@ -96,7 +96,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Promo Code Input (Optional) -->
|
<!-- Promo Code Input (Optional) -->
|
||||||
<div>
|
<div v-if="promoCodeEnabled">
|
||||||
<label for="promo_code" class="input-label">
|
<label for="promo_code" class="input-label">
|
||||||
{{ t('auth.promoCodeLabel') }}
|
{{ t('auth.promoCodeLabel') }}
|
||||||
<span class="ml-1 text-xs font-normal text-gray-400 dark:text-dark-500">({{ t('common.optional') }})</span>
|
<span class="ml-1 text-xs font-normal text-gray-400 dark:text-dark-500">({{ t('common.optional') }})</span>
|
||||||
@@ -260,6 +260,7 @@ const showPassword = ref<boolean>(false)
|
|||||||
// Public settings
|
// Public settings
|
||||||
const registrationEnabled = ref<boolean>(true)
|
const registrationEnabled = ref<boolean>(true)
|
||||||
const emailVerifyEnabled = ref<boolean>(false)
|
const emailVerifyEnabled = ref<boolean>(false)
|
||||||
|
const promoCodeEnabled = ref<boolean>(true)
|
||||||
const turnstileEnabled = ref<boolean>(false)
|
const turnstileEnabled = ref<boolean>(false)
|
||||||
const turnstileSiteKey = ref<string>('')
|
const turnstileSiteKey = ref<string>('')
|
||||||
const siteName = ref<string>('Sub2API')
|
const siteName = ref<string>('Sub2API')
|
||||||
@@ -294,22 +295,25 @@ const errors = reactive({
|
|||||||
// ==================== Lifecycle ====================
|
// ==================== Lifecycle ====================
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
// Read promo code from URL parameter
|
|
||||||
const promoParam = route.query.promo as string
|
|
||||||
if (promoParam) {
|
|
||||||
formData.promo_code = promoParam
|
|
||||||
// Validate the promo code from URL
|
|
||||||
await validatePromoCodeDebounced(promoParam)
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const settings = await getPublicSettings()
|
const settings = await getPublicSettings()
|
||||||
registrationEnabled.value = settings.registration_enabled
|
registrationEnabled.value = settings.registration_enabled
|
||||||
emailVerifyEnabled.value = settings.email_verify_enabled
|
emailVerifyEnabled.value = settings.email_verify_enabled
|
||||||
|
promoCodeEnabled.value = settings.promo_code_enabled
|
||||||
turnstileEnabled.value = settings.turnstile_enabled
|
turnstileEnabled.value = settings.turnstile_enabled
|
||||||
turnstileSiteKey.value = settings.turnstile_site_key || ''
|
turnstileSiteKey.value = settings.turnstile_site_key || ''
|
||||||
siteName.value = settings.site_name || 'Sub2API'
|
siteName.value = settings.site_name || 'Sub2API'
|
||||||
linuxdoOAuthEnabled.value = settings.linuxdo_oauth_enabled
|
linuxdoOAuthEnabled.value = settings.linuxdo_oauth_enabled
|
||||||
|
|
||||||
|
// Read promo code from URL parameter only if promo code is enabled
|
||||||
|
if (promoCodeEnabled.value) {
|
||||||
|
const promoParam = route.query.promo as string
|
||||||
|
if (promoParam) {
|
||||||
|
formData.promo_code = promoParam
|
||||||
|
// Validate the promo code from URL
|
||||||
|
await validatePromoCodeDebounced(promoParam)
|
||||||
|
}
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Failed to load public settings:', error)
|
console.error('Failed to load public settings:', error)
|
||||||
} finally {
|
} finally {
|
||||||
|
|||||||
Reference in New Issue
Block a user