mirror of https://gitee.com/answerdev/answer.git
Merge remote-tracking branch 'origin/main' into feat/orm-init
This commit is contained in:
commit
25e167d957
21
docs/docs.go
21
docs/docs.go
|
@ -4092,7 +4092,7 @@ const docTemplate = `{
|
|||
"type": "string"
|
||||
},
|
||||
"html": {
|
||||
"description": "解析后的html",
|
||||
"description": "html",
|
||||
"type": "string"
|
||||
},
|
||||
"question_id": {
|
||||
|
@ -4146,7 +4146,7 @@ const docTemplate = `{
|
|||
"type": "string"
|
||||
},
|
||||
"html": {
|
||||
"description": "解析后的html",
|
||||
"description": "html",
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
|
@ -4622,15 +4622,18 @@ const docTemplate = `{
|
|||
"type": "object",
|
||||
"properties": {
|
||||
"encryption": {
|
||||
"description": "\"\" SSL TLS",
|
||||
"description": "\"\" SSL",
|
||||
"type": "string"
|
||||
},
|
||||
"from_email_address": {
|
||||
"from_email": {
|
||||
"type": "string"
|
||||
},
|
||||
"from_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"smtp_authentication": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"smtp_host": {
|
||||
"type": "string"
|
||||
},
|
||||
|
@ -5530,13 +5533,13 @@ const docTemplate = `{
|
|||
"type": "object",
|
||||
"properties": {
|
||||
"encryption": {
|
||||
"description": "\"\" SSL TLS",
|
||||
"description": "\"\" SSL",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"SSL"
|
||||
]
|
||||
},
|
||||
"from_email_address": {
|
||||
"from_email": {
|
||||
"type": "string",
|
||||
"maxLength": 256
|
||||
},
|
||||
|
@ -5544,6 +5547,9 @@ const docTemplate = `{
|
|||
"type": "string",
|
||||
"maxLength": 256
|
||||
},
|
||||
"smtp_authentication": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"smtp_host": {
|
||||
"type": "string",
|
||||
"maxLength": 256
|
||||
|
@ -5560,6 +5566,9 @@ const docTemplate = `{
|
|||
"smtp_username": {
|
||||
"type": "string",
|
||||
"maxLength": 256
|
||||
},
|
||||
"test_email_recipient": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -4080,7 +4080,7 @@
|
|||
"type": "string"
|
||||
},
|
||||
"html": {
|
||||
"description": "解析后的html",
|
||||
"description": "html",
|
||||
"type": "string"
|
||||
},
|
||||
"question_id": {
|
||||
|
@ -4134,7 +4134,7 @@
|
|||
"type": "string"
|
||||
},
|
||||
"html": {
|
||||
"description": "解析后的html",
|
||||
"description": "html",
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
|
@ -4610,15 +4610,18 @@
|
|||
"type": "object",
|
||||
"properties": {
|
||||
"encryption": {
|
||||
"description": "\"\" SSL TLS",
|
||||
"description": "\"\" SSL",
|
||||
"type": "string"
|
||||
},
|
||||
"from_email_address": {
|
||||
"from_email": {
|
||||
"type": "string"
|
||||
},
|
||||
"from_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"smtp_authentication": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"smtp_host": {
|
||||
"type": "string"
|
||||
},
|
||||
|
@ -5518,13 +5521,13 @@
|
|||
"type": "object",
|
||||
"properties": {
|
||||
"encryption": {
|
||||
"description": "\"\" SSL TLS",
|
||||
"description": "\"\" SSL",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"SSL"
|
||||
]
|
||||
},
|
||||
"from_email_address": {
|
||||
"from_email": {
|
||||
"type": "string",
|
||||
"maxLength": 256
|
||||
},
|
||||
|
@ -5532,6 +5535,9 @@
|
|||
"type": "string",
|
||||
"maxLength": 256
|
||||
},
|
||||
"smtp_authentication": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"smtp_host": {
|
||||
"type": "string",
|
||||
"maxLength": 256
|
||||
|
@ -5548,6 +5554,9 @@
|
|||
"smtp_username": {
|
||||
"type": "string",
|
||||
"maxLength": 256
|
||||
},
|
||||
"test_email_recipient": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -129,7 +129,7 @@ definitions:
|
|||
description: content
|
||||
type: string
|
||||
html:
|
||||
description: 解析后的html
|
||||
description: html
|
||||
type: string
|
||||
question_id:
|
||||
description: question_id
|
||||
|
@ -167,7 +167,7 @@ definitions:
|
|||
description: edit_summary
|
||||
type: string
|
||||
html:
|
||||
description: 解析后的html
|
||||
description: html
|
||||
type: string
|
||||
id:
|
||||
description: id
|
||||
|
@ -513,12 +513,14 @@ definitions:
|
|||
schema.GetSMTPConfigResp:
|
||||
properties:
|
||||
encryption:
|
||||
description: '"" SSL TLS'
|
||||
description: '"" SSL'
|
||||
type: string
|
||||
from_email_address:
|
||||
from_email:
|
||||
type: string
|
||||
from_name:
|
||||
type: string
|
||||
smtp_authentication:
|
||||
type: boolean
|
||||
smtp_host:
|
||||
type: string
|
||||
smtp_password:
|
||||
|
@ -1167,16 +1169,18 @@ definitions:
|
|||
schema.UpdateSMTPConfigReq:
|
||||
properties:
|
||||
encryption:
|
||||
description: '"" SSL TLS'
|
||||
description: '"" SSL'
|
||||
enum:
|
||||
- SSL
|
||||
type: string
|
||||
from_email_address:
|
||||
from_email:
|
||||
maxLength: 256
|
||||
type: string
|
||||
from_name:
|
||||
maxLength: 256
|
||||
type: string
|
||||
smtp_authentication:
|
||||
type: boolean
|
||||
smtp_host:
|
||||
maxLength: 256
|
||||
type: string
|
||||
|
@ -1190,6 +1194,8 @@ definitions:
|
|||
smtp_username:
|
||||
maxLength: 256
|
||||
type: string
|
||||
test_email_recipient:
|
||||
type: string
|
||||
type: object
|
||||
schema.UpdateTagReq:
|
||||
properties:
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package entity
|
||||
|
||||
// UserCacheInfo 用户缓存信息
|
||||
// UserCacheInfo User Cache Information
|
||||
type UserCacheInfo struct {
|
||||
UserID string `json:"user_id"`
|
||||
UserStatus int `json:"user_status"`
|
||||
|
|
|
@ -16,7 +16,7 @@ const (
|
|||
type AnswerAddReq struct {
|
||||
QuestionId string `json:"question_id" ` // question_id
|
||||
Content string `json:"content" ` // content
|
||||
Html string `json:"html" ` // 解析后的html
|
||||
Html string `json:"html" ` // html
|
||||
UserID string `json:"-" ` // user_id
|
||||
}
|
||||
|
||||
|
@ -26,7 +26,7 @@ type AnswerUpdateReq struct {
|
|||
UserID string `json:"-" ` // user_id
|
||||
Title string `json:"title" ` // title
|
||||
Content string `json:"content"` // content
|
||||
Html string `json:"html" ` // 解析后的html
|
||||
Html string `json:"html" ` // html
|
||||
EditSummary string `validate:"omitempty" json:"edit_summary"` //edit_summary
|
||||
}
|
||||
|
||||
|
|
|
@ -52,27 +52,27 @@ type QuestionUpdate struct {
|
|||
|
||||
type QuestionBaseInfo struct {
|
||||
ID string `json:"id" `
|
||||
Title string `json:"title" xorm:"title"` // 标题
|
||||
ViewCount int `json:"view_count" xorm:"view_count"` // view_count
|
||||
AnswerCount int `json:"answer_count" xorm:"answer_count"` // 回复总数
|
||||
CollectionCount int `json:"collection_count" xorm:"collection_count"` // 收藏总数
|
||||
FollowCount int `json:"follow_count" xorm:"follow_count"` // 关注数
|
||||
Title string `json:"title" xorm:"title"` // title
|
||||
ViewCount int `json:"view_count" xorm:"view_count"` // view count
|
||||
AnswerCount int `json:"answer_count" xorm:"answer_count"` // answer count
|
||||
CollectionCount int `json:"collection_count" xorm:"collection_count"` // collection count
|
||||
FollowCount int `json:"follow_count" xorm:"follow_count"` // follow count
|
||||
Status string `json:"status"`
|
||||
AcceptedAnswer bool `json:"accepted_answer"`
|
||||
}
|
||||
|
||||
type QuestionInfo struct {
|
||||
ID string `json:"id" `
|
||||
Title string `json:"title" xorm:"title"` // 标题
|
||||
Content string `json:"content" xorm:"content"` // 内容
|
||||
Html string `json:"html" xorm:"html"` // 解析后的html
|
||||
Title string `json:"title" xorm:"title"` // title
|
||||
Content string `json:"content" xorm:"content"` // content
|
||||
Html string `json:"html" xorm:"html"` // html
|
||||
Tags []*TagResp `json:"tags" ` // tags
|
||||
ViewCount int `json:"view_count" xorm:"view_count"` // view_count
|
||||
UniqueViewCount int `json:"unique_view_count" xorm:"unique_view_count"` // unique_view_count
|
||||
VoteCount int `json:"vote_count" xorm:"vote_count"` // vote_count
|
||||
AnswerCount int `json:"answer_count" xorm:"answer_count"` // 回复总数
|
||||
CollectionCount int `json:"collection_count" xorm:"collection_count"` // 收藏总数
|
||||
FollowCount int `json:"follow_count" xorm:"follow_count"` // 关注数
|
||||
AnswerCount int `json:"answer_count" xorm:"answer_count"` // answer count
|
||||
CollectionCount int `json:"collection_count" xorm:"collection_count"` // collection count
|
||||
FollowCount int `json:"follow_count" xorm:"follow_count"` // follow count
|
||||
AcceptedAnswerId string `json:"accepted_answer_id" ` // accepted_answer_id
|
||||
LastAnswerId string `json:"last_answer_id" ` // last_answer_id
|
||||
CreateTime int64 `json:"create_time" ` // create_time
|
||||
|
|
|
@ -27,22 +27,25 @@ type SiteInfoResp struct {
|
|||
|
||||
// UpdateSMTPConfigReq get smtp config request
|
||||
type UpdateSMTPConfigReq struct {
|
||||
FromEmailAddress string `validate:"omitempty,gt=0,lte=256" json:"from_email_address"`
|
||||
FromEmail string `validate:"omitempty,gt=0,lte=256" json:"from_email"`
|
||||
FromName string `validate:"omitempty,gt=0,lte=256" json:"from_name"`
|
||||
SMTPHost string `validate:"omitempty,gt=0,lte=256" json:"smtp_host"`
|
||||
SMTPPort int `validate:"omitempty,min=1,max=65535" json:"smtp_port"`
|
||||
Encryption string `validate:"omitempty,oneof=SSL" json:"encryption"` // "" SSL TLS
|
||||
Encryption string `validate:"omitempty,oneof=SSL" json:"encryption"` // "" SSL
|
||||
SMTPUsername string `validate:"omitempty,gt=0,lte=256" json:"smtp_username"`
|
||||
SMTPPassword string `validate:"omitempty,gt=0,lte=256" json:"smtp_password"`
|
||||
SMTPAuthentication bool `validate:"omitempty" json:"smtp_authentication"`
|
||||
TestEmailRecipient string `validate:"omitempty,email" json:"test_email_recipient"`
|
||||
}
|
||||
|
||||
// GetSMTPConfigResp get smtp config response
|
||||
type GetSMTPConfigResp struct {
|
||||
FromEmailAddress string `json:"from_email_address"`
|
||||
FromEmail string `json:"from_email"`
|
||||
FromName string `json:"from_name"`
|
||||
SMTPHost string `json:"smtp_host"`
|
||||
SMTPPort int `json:"smtp_port"`
|
||||
Encryption string `json:"encryption"` // "" SSL TLS
|
||||
Encryption string `json:"encryption"` // "" SSL
|
||||
SMTPUsername string `json:"smtp_username"`
|
||||
SMTPPassword string `json:"smtp_password"`
|
||||
SMTPAuthentication bool `json:"smtp_authentication"`
|
||||
}
|
||||
|
|
|
@ -365,7 +365,6 @@ func (as *AnswerService) SearchList(ctx context.Context, search *schema.AnswerLi
|
|||
|
||||
func (as *AnswerService) SearchFormatInfo(ctx context.Context, dblist []*entity.Answer, loginUserId string) ([]*schema.AnswerInfo, error) {
|
||||
list := make([]*schema.AnswerInfo, 0)
|
||||
//todo 依赖其他接口
|
||||
objectIds := make([]string, 0)
|
||||
userIds := make([]string, 0)
|
||||
for _, dbitem := range dblist {
|
||||
|
|
|
@ -3,6 +3,7 @@ package export
|
|||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"html/template"
|
||||
|
||||
"github.com/segmentfault/answer/internal/base/reason"
|
||||
|
@ -35,13 +36,14 @@ func NewEmailService(configRepo config.ConfigRepo, emailRepo EmailRepo) *EmailSe
|
|||
|
||||
// EmailConfig email config
|
||||
type EmailConfig struct {
|
||||
FromEmailAddress string `json:"from_email_address"`
|
||||
FromEmail string `json:"from_email"`
|
||||
FromName string `json:"from_name"`
|
||||
SMTPHost string `json:"smtp_host"`
|
||||
SMTPPort int `json:"smtp_port"`
|
||||
Encryption string `json:"encryption"` // "" SSL
|
||||
SMTPUsername string `json:"smtp_username"`
|
||||
SMTPPassword string `json:"smtp_password"`
|
||||
SMTPAuthentication bool `json:"smtp_authentication"`
|
||||
|
||||
RegisterTitle string `json:"register_title"`
|
||||
RegisterBody string `json:"register_body"`
|
||||
|
@ -49,6 +51,8 @@ type EmailConfig struct {
|
|||
PassResetBody string `json:"pass_reset_body"`
|
||||
ChangeTitle string `json:"change_title"`
|
||||
ChangeBody string `json:"change_body"`
|
||||
TestTitle string `json:"test_title"`
|
||||
TestBody string `json:"test_body"`
|
||||
}
|
||||
|
||||
func (e *EmailConfig) IsSSL() bool {
|
||||
|
@ -70,16 +74,21 @@ type ChangeEmailTemplateData struct {
|
|||
ChangeEmailUrl string
|
||||
}
|
||||
|
||||
type TestTemplateData struct {
|
||||
SiteName string
|
||||
}
|
||||
|
||||
// Send email send
|
||||
func (es *EmailService) Send(ctx context.Context, toEmailAddr, subject, body, code, codeContent string) {
|
||||
log.Infof("try to send email to %s", toEmailAddr)
|
||||
ec, err := es.GetEmailConfig()
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
log.Errorf("get email config failed: %s", err)
|
||||
return
|
||||
}
|
||||
|
||||
m := gomail.NewMessage()
|
||||
m.SetHeader("From", ec.FromEmailAddress)
|
||||
m.SetHeader("From", ec.FromEmail)
|
||||
m.SetHeader("To", toEmailAddr)
|
||||
m.SetHeader("Subject", subject)
|
||||
m.SetBody("text/html", body)
|
||||
|
@ -89,13 +98,17 @@ func (es *EmailService) Send(ctx context.Context, toEmailAddr, subject, body, co
|
|||
d.SSL = true
|
||||
}
|
||||
if err := d.DialAndSend(m); err != nil {
|
||||
log.Error(err)
|
||||
log.Errorf("send email to %s failed: %s", toEmailAddr, err)
|
||||
} else {
|
||||
log.Infof("send email to %s success", toEmailAddr)
|
||||
}
|
||||
|
||||
if len(code) > 0 {
|
||||
err = es.emailRepo.SetCode(ctx, code, codeContent)
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -192,6 +205,35 @@ func (es *EmailService) ChangeEmailTemplate(changeEmailUrl string) (title, body
|
|||
return titleBuf.String(), bodyBuf.String(), nil
|
||||
}
|
||||
|
||||
func (es *EmailService) TestTemplate() (title, body string, err error) {
|
||||
ec, err := es.GetEmailConfig()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
templateData := TestTemplateData{
|
||||
SiteName: ec.FromName,
|
||||
}
|
||||
|
||||
titleBuf := &bytes.Buffer{}
|
||||
bodyBuf := &bytes.Buffer{}
|
||||
|
||||
tmpl, err := template.New("test_title").Parse(ec.TestTitle)
|
||||
if err != nil {
|
||||
return "", "", fmt.Errorf("email test title template parse error: %s", err)
|
||||
}
|
||||
err = tmpl.Execute(titleBuf, templateData)
|
||||
if err != nil {
|
||||
return "", "", fmt.Errorf("email test body template parse error: %s", err)
|
||||
}
|
||||
tmpl, err = template.New("test_body").Parse(ec.TestBody)
|
||||
err = tmpl.Execute(bodyBuf, templateData)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
return titleBuf.String(), bodyBuf.String(), nil
|
||||
}
|
||||
|
||||
func (es *EmailService) GetEmailConfig() (ec *EmailConfig, err error) {
|
||||
emailConf, err := es.configRepo.GetString("email.config")
|
||||
if err != nil {
|
||||
|
|
|
@ -132,7 +132,22 @@ func (s *SiteInfoService) GetSMTPConfig(ctx context.Context) (
|
|||
|
||||
// UpdateSMTPConfig get smtp config
|
||||
func (s *SiteInfoService) UpdateSMTPConfig(ctx context.Context, req *schema.UpdateSMTPConfigReq) (err error) {
|
||||
ec := &export.EmailConfig{}
|
||||
_ = copier.Copy(ec, req)
|
||||
return s.emailService.SetEmailConfig(ec)
|
||||
oldEmailConfig, err := s.emailService.GetEmailConfig()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_ = copier.Copy(oldEmailConfig, req)
|
||||
|
||||
err = s.emailService.SetEmailConfig(oldEmailConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(req.TestEmailRecipient) > 0 {
|
||||
title, body, err := s.emailService.TestTemplate()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
go s.emailService.Send(ctx, req.TestEmailRecipient, title, body, "", "")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
|
|
@ -14,13 +14,13 @@ const (
|
|||
)
|
||||
|
||||
/*
|
||||
* minLength: 指定密码的最小长度
|
||||
* maxLength:指定密码的最大长度
|
||||
* minLevel:指定密码最低要求的强度等级
|
||||
* pwd:明文密码
|
||||
* minLength: Specifies the minimum length of a password
|
||||
* maxLength:Specifies the maximum length of a password
|
||||
* minLevel:Specifies the minimum strength level required for passwords
|
||||
* pwd:Text passwords
|
||||
*/
|
||||
func PassWordCheck(minLength, maxLength, minLevel int, pwd string) error {
|
||||
// 首先校验密码长度是否在范围内
|
||||
// First check whether the password length is within the range
|
||||
if len(pwd) < minLength {
|
||||
return fmt.Errorf("BAD PASSWORD: The password is shorter than %d characters", minLength)
|
||||
}
|
||||
|
@ -28,7 +28,9 @@ func PassWordCheck(minLength, maxLength, minLevel int, pwd string) error {
|
|||
return fmt.Errorf("BAD PASSWORD: The password is logner than %d characters", maxLength)
|
||||
}
|
||||
|
||||
// 初始化密码强度等级为D,利用正则校验密码强度,若匹配成功则强度自增1
|
||||
// The password strength level is initialized to D.
|
||||
// The regular is used to verify the password strength.
|
||||
// If the matching is successful, the password strength increases by 1
|
||||
var level int = levelD
|
||||
patternList := []string{`[0-9]+`, `[a-z]+`, `[A-Z]+`, `[~!@#$%^&*?_-]+`}
|
||||
for _, pattern := range patternList {
|
||||
|
@ -38,7 +40,7 @@ func PassWordCheck(minLength, maxLength, minLevel int, pwd string) error {
|
|||
}
|
||||
}
|
||||
|
||||
// 如果最终密码强度低于要求的最低强度,返回并报错
|
||||
// If the final password strength falls below the required minimum strength, return with an error
|
||||
if level < minLevel {
|
||||
return fmt.Errorf("The password does not satisfy the current policy requirements. ")
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue