feat: 添加登录注册条款确认
This commit is contained in:
@@ -117,6 +117,10 @@ func (h *SettingHandler) GetSettings(c *gin.Context) {
|
||||
InvitationCodeEnabled: settings.InvitationCodeEnabled,
|
||||
TotpEnabled: settings.TotpEnabled,
|
||||
TotpEncryptionKeyConfigured: h.settingService.IsTotpEncryptionKeyConfigured(),
|
||||
LoginAgreementEnabled: settings.LoginAgreementEnabled,
|
||||
LoginAgreementMode: settings.LoginAgreementMode,
|
||||
LoginAgreementUpdatedAt: settings.LoginAgreementUpdatedAt,
|
||||
LoginAgreementDocuments: loginAgreementDocumentsToDTO(settings.LoginAgreementDocuments),
|
||||
SMTPHost: settings.SMTPHost,
|
||||
SMTPPort: settings.SMTPPort,
|
||||
SMTPUsername: settings.SMTPUsername,
|
||||
@@ -305,17 +309,50 @@ func openaiFastPolicySettingsFromDTO(s *dto.OpenAIFastPolicySettings) *service.O
|
||||
return &service.OpenAIFastPolicySettings{Rules: rules}
|
||||
}
|
||||
|
||||
func loginAgreementDocumentsToDTO(items []service.LoginAgreementDocument) []dto.LoginAgreementDocument {
|
||||
result := make([]dto.LoginAgreementDocument, 0, len(items))
|
||||
for _, item := range items {
|
||||
result = append(result, dto.LoginAgreementDocument{
|
||||
ID: item.ID,
|
||||
Title: item.Title,
|
||||
ContentMD: item.ContentMD,
|
||||
})
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func loginAgreementDocumentsToService(items []dto.LoginAgreementDocument) []service.LoginAgreementDocument {
|
||||
result := make([]service.LoginAgreementDocument, 0, len(items))
|
||||
for _, item := range items {
|
||||
title := strings.TrimSpace(item.Title)
|
||||
content := strings.TrimSpace(item.ContentMD)
|
||||
if title == "" && content == "" {
|
||||
continue
|
||||
}
|
||||
result = append(result, service.LoginAgreementDocument{
|
||||
ID: strings.TrimSpace(item.ID),
|
||||
Title: title,
|
||||
ContentMD: content,
|
||||
})
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// UpdateSettingsRequest 更新设置请求
|
||||
type UpdateSettingsRequest struct {
|
||||
// 注册设置
|
||||
RegistrationEnabled bool `json:"registration_enabled"`
|
||||
EmailVerifyEnabled bool `json:"email_verify_enabled"`
|
||||
RegistrationEmailSuffixWhitelist []string `json:"registration_email_suffix_whitelist"`
|
||||
PromoCodeEnabled bool `json:"promo_code_enabled"`
|
||||
PasswordResetEnabled bool `json:"password_reset_enabled"`
|
||||
FrontendURL string `json:"frontend_url"`
|
||||
InvitationCodeEnabled bool `json:"invitation_code_enabled"`
|
||||
TotpEnabled bool `json:"totp_enabled"` // TOTP 双因素认证
|
||||
RegistrationEnabled bool `json:"registration_enabled"`
|
||||
EmailVerifyEnabled bool `json:"email_verify_enabled"`
|
||||
RegistrationEmailSuffixWhitelist []string `json:"registration_email_suffix_whitelist"`
|
||||
PromoCodeEnabled bool `json:"promo_code_enabled"`
|
||||
PasswordResetEnabled bool `json:"password_reset_enabled"`
|
||||
FrontendURL string `json:"frontend_url"`
|
||||
InvitationCodeEnabled bool `json:"invitation_code_enabled"`
|
||||
TotpEnabled bool `json:"totp_enabled"` // TOTP 双因素认证
|
||||
LoginAgreementEnabled bool `json:"login_agreement_enabled"`
|
||||
LoginAgreementMode string `json:"login_agreement_mode"`
|
||||
LoginAgreementUpdatedAt string `json:"login_agreement_updated_at"`
|
||||
LoginAgreementDocuments []dto.LoginAgreementDocument `json:"login_agreement_documents"`
|
||||
|
||||
// 邮件服务设置
|
||||
SMTPHost string `json:"smtp_host"`
|
||||
@@ -668,6 +705,44 @@ func (h *SettingHandler) UpdateSettings(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
}
|
||||
loginAgreementMode := strings.ToLower(strings.TrimSpace(req.LoginAgreementMode))
|
||||
if loginAgreementMode == "" {
|
||||
loginAgreementMode = strings.ToLower(strings.TrimSpace(previousSettings.LoginAgreementMode))
|
||||
}
|
||||
switch loginAgreementMode {
|
||||
case "", "modal":
|
||||
loginAgreementMode = "modal"
|
||||
case "checkbox":
|
||||
default:
|
||||
response.BadRequest(c, "Login agreement mode must be modal or checkbox")
|
||||
return
|
||||
}
|
||||
loginAgreementUpdatedAt := strings.TrimSpace(req.LoginAgreementUpdatedAt)
|
||||
if loginAgreementUpdatedAt == "" {
|
||||
loginAgreementUpdatedAt = strings.TrimSpace(previousSettings.LoginAgreementUpdatedAt)
|
||||
}
|
||||
loginAgreementDocuments := loginAgreementDocumentsToService(req.LoginAgreementDocuments)
|
||||
if len(loginAgreementDocuments) == 0 {
|
||||
loginAgreementDocuments = previousSettings.LoginAgreementDocuments
|
||||
}
|
||||
for _, doc := range loginAgreementDocuments {
|
||||
if strings.TrimSpace(doc.Title) == "" {
|
||||
response.BadRequest(c, "Login agreement document title is required")
|
||||
return
|
||||
}
|
||||
if len(doc.Title) > 80 {
|
||||
response.BadRequest(c, "Login agreement document title is too long (max 80 characters)")
|
||||
return
|
||||
}
|
||||
if len(doc.ContentMD) > 200*1024 {
|
||||
response.BadRequest(c, "Login agreement document content is too large (max 200KB)")
|
||||
return
|
||||
}
|
||||
}
|
||||
if req.LoginAgreementEnabled && len(loginAgreementDocuments) == 0 {
|
||||
response.BadRequest(c, "Login agreement documents are required when enabled")
|
||||
return
|
||||
}
|
||||
|
||||
// LinuxDo Connect 参数验证
|
||||
if req.LinuxDoConnectEnabled {
|
||||
@@ -1193,6 +1268,10 @@ func (h *SettingHandler) UpdateSettings(c *gin.Context) {
|
||||
FrontendURL: req.FrontendURL,
|
||||
InvitationCodeEnabled: req.InvitationCodeEnabled,
|
||||
TotpEnabled: req.TotpEnabled,
|
||||
LoginAgreementEnabled: req.LoginAgreementEnabled,
|
||||
LoginAgreementMode: loginAgreementMode,
|
||||
LoginAgreementUpdatedAt: loginAgreementUpdatedAt,
|
||||
LoginAgreementDocuments: loginAgreementDocuments,
|
||||
SMTPHost: req.SMTPHost,
|
||||
SMTPPort: req.SMTPPort,
|
||||
SMTPUsername: req.SMTPUsername,
|
||||
@@ -1561,6 +1640,10 @@ func (h *SettingHandler) UpdateSettings(c *gin.Context) {
|
||||
InvitationCodeEnabled: updatedSettings.InvitationCodeEnabled,
|
||||
TotpEnabled: updatedSettings.TotpEnabled,
|
||||
TotpEncryptionKeyConfigured: h.settingService.IsTotpEncryptionKeyConfigured(),
|
||||
LoginAgreementEnabled: updatedSettings.LoginAgreementEnabled,
|
||||
LoginAgreementMode: updatedSettings.LoginAgreementMode,
|
||||
LoginAgreementUpdatedAt: updatedSettings.LoginAgreementUpdatedAt,
|
||||
LoginAgreementDocuments: loginAgreementDocumentsToDTO(updatedSettings.LoginAgreementDocuments),
|
||||
SMTPHost: updatedSettings.SMTPHost,
|
||||
SMTPPort: updatedSettings.SMTPPort,
|
||||
SMTPUsername: updatedSettings.SMTPUsername,
|
||||
@@ -1772,6 +1855,18 @@ func diffSettings(before *service.SystemSettings, after *service.SystemSettings,
|
||||
if before.TotpEnabled != after.TotpEnabled {
|
||||
changed = append(changed, "totp_enabled")
|
||||
}
|
||||
if before.LoginAgreementEnabled != after.LoginAgreementEnabled {
|
||||
changed = append(changed, "login_agreement_enabled")
|
||||
}
|
||||
if before.LoginAgreementMode != after.LoginAgreementMode {
|
||||
changed = append(changed, "login_agreement_mode")
|
||||
}
|
||||
if before.LoginAgreementUpdatedAt != after.LoginAgreementUpdatedAt {
|
||||
changed = append(changed, "login_agreement_updated_at")
|
||||
}
|
||||
if !equalLoginAgreementDocuments(before.LoginAgreementDocuments, after.LoginAgreementDocuments) {
|
||||
changed = append(changed, "login_agreement_documents")
|
||||
}
|
||||
if before.SMTPHost != after.SMTPHost {
|
||||
changed = append(changed, "smtp_host")
|
||||
}
|
||||
@@ -2272,6 +2367,18 @@ func equalDefaultSubscriptions(a, b []service.DefaultSubscriptionSetting) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func equalLoginAgreementDocuments(a, b []service.LoginAgreementDocument) bool {
|
||||
if len(a) != len(b) {
|
||||
return false
|
||||
}
|
||||
for i := range a {
|
||||
if a[i].ID != b[i].ID || a[i].Title != b[i].Title || a[i].ContentMD != b[i].ContentMD {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func equalIntSlice(a, b []int) bool {
|
||||
if len(a) != len(b) {
|
||||
return false
|
||||
|
||||
Reference in New Issue
Block a user