Skip to content

Commit

Permalink
Merge branch 'v2.5.1'
Browse files Browse the repository at this point in the history
  • Loading branch information
Jinnrry committed Jul 5, 2024
2 parents c67d52d + 7860908 commit e4c5ec5
Show file tree
Hide file tree
Showing 10 changed files with 305 additions and 251 deletions.
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ clean:

build_fe:
cd fe && yarn && yarn build
rm -rf server/http_server/dist
cd server && cp -rf ../fe/dist http_server

build_server:
Expand Down
6 changes: 4 additions & 2 deletions fe/src/i18n/i18n.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ var lang = {
"web_domain": "Web Domain",
"dns_desc": "Please add the following information to your DNS records",
"ssl_auto": "Automatically configure SSL certificates (recommended)",
"wait_desc": "HTTP challenge mode completes in approximately 1 minute.",
"wait_desc": "Please Wait.",
"dns_challenge_wait": "DNS propagation and cache refreshes take a long time, and a wait of 10-30 minutes is possible here.",
"ssl_challenge_type":"Challenge Type",
"ssl_auto_http":"Http Request",
"ssl_auto_dns":"DNS Records",
Expand Down Expand Up @@ -176,7 +177,8 @@ var zhCN = {
"ssl_challenge_type":"验证方式",
"ssl_manuallyf": "手动配置SSL证书",
"challenge_typ_desc": "如果PMail直接使用80端口,建议使用HTTP验证方式。",
"wait_desc": "HTTP验证模式大约1分钟完成",
"wait_desc": "请稍等",
"dns_challenge_wait": "DNS传播和缓存刷新时间较长,此处可能等待10-30分钟",
"ssl_key_path": "ssl key文件位置",
"ssl_crt_path": "ssl crt文件位置",
"group_settings": "分组",
Expand Down
237 changes: 56 additions & 181 deletions fe/src/views/SetupView.vue

Large diffs are not rendered by default.

39 changes: 37 additions & 2 deletions server/config/config.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
package config

import (
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"crypto/x509"
"encoding/json"
"encoding/pem"
"os"
)

Expand Down Expand Up @@ -48,8 +53,8 @@ func (c *Config) SetSetupPort(setupPort int) {
const DBTypeMySQL = "mysql"
const DBTypeSQLite = "sqlite"
const SSLTypeAutoHTTP = "0" //自动生成证书
// const SSLTypeAutoDNS = "2" //自动生成证书,DNS api验证
const SSLTypeUser = "1" //用户上传证书
const SSLTypeAutoDNS = "2" //自动生成证书,DNS api验证
const SSLTypeUser = "1" //用户上传证书

var DBTypes []string = []string{DBTypeMySQL, DBTypeSQLite}

Expand Down Expand Up @@ -86,3 +91,33 @@ func Init() {
}

}

func ReadPrivateKey() (*ecdsa.PrivateKey, bool) {
key, err := os.ReadFile("./config/ssl/account_private.pem")
if err != nil {
return createNewPrivateKey(), true
}

block, _ := pem.Decode(key)
x509Encoded := block.Bytes
privateKey, _ := x509.ParseECPrivateKey(x509Encoded)

return privateKey, false
}

func createNewPrivateKey() *ecdsa.PrivateKey {
// Create a user. New accounts need an email and private key to start.
privateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
if err != nil {
panic(err)
}
x509Encoded, _ := x509.MarshalECPrivateKey(privateKey)

// 将ec 密钥写入到 pem文件里
keypem, _ := os.OpenFile("./config/ssl/account_private.pem", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666)
err = pem.Encode(keypem, &pem.Block{Type: "EC PRIVATE KEY", Bytes: x509Encoded})
if err != nil {
panic(err)
}
return privateKey
}
47 changes: 22 additions & 25 deletions server/controllers/setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
log "github.com/sirupsen/logrus"
"io"
"net/http"
"os"
"pmail/config"
"pmail/dto/response"
"pmail/services/setup"
Expand Down Expand Up @@ -134,40 +135,36 @@ func Setup(ctx *context.Context, w http.ResponseWriter, req *http.Request) {
return
}

//if reqData["step"] == "ssl" && reqData["action"] == "getParams" {
// params, err := ssl.GetServerParamsList(reqData["serverName"])
// if err != nil {
// response.NewErrorResponse(response.ServerError, err.Error(), "").FPrint(w)
// return
// }
// response.NewSuccessResponse(params).FPrint(w)
// return
//}

//if reqData["step"] == "ssl" && reqData["action"] == "setParams" {
// for key, v := range reqData {
// if key != "step" && key != "action" {
// ssl.SetDomainServerParams(key, v)
// }
// }
// response.NewSuccessResponse("Succ").FPrint(w)
// return
//}
if reqData["step"] == "ssl" && reqData["action"] == "getParams" {
dnsChallenge := ssl.GetDnsChallengeInstance()

response.NewSuccessResponse(dnsChallenge.GetDNSSettings(ctx)).FPrint(w)
return
}

if reqData["step"] == "ssl" && reqData["action"] == "set" {
keyPath := reqData["key_path"]
crtPath := reqData["crt_path"]

_, err := os.Stat(keyPath)
if err != nil {
response.NewErrorResponse(response.ServerError, err.Error(), "").FPrint(w)
return
}

serviceName, ok := reqData["serviceName"]
if !ok {
serviceName = ""
_, err = os.Stat(crtPath)
if err != nil {
response.NewErrorResponse(response.ServerError, err.Error(), "").FPrint(w)
return
}
err := ssl.SetSSL(reqData["ssl_type"], reqData["key_path"], reqData["crt_path"], serviceName)

err = ssl.SetSSL(reqData["ssl_type"], reqData["key_path"], reqData["crt_path"])
if err != nil {
response.NewErrorResponse(response.ServerError, err.Error(), "").FPrint(w)
return
}

//if reqData["ssl_type"] == config.SSLTypeAutoHTTP || reqData["ssl_type"] == config.SSLTypeAutoDNS {
if reqData["ssl_type"] == config.SSLTypeAutoHTTP {
if reqData["ssl_type"] == config.SSLTypeAutoHTTP || reqData["ssl_type"] == config.SSLTypeAutoDNS {
err = ssl.GenSSL(false)
if err != nil {
response.NewErrorResponse(response.ServerError, err.Error(), "").FPrint(w)
Expand Down
3 changes: 2 additions & 1 deletion server/cron_server/ssl_update.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ func Start() {
}
}

if config.Instance.SSLType == "0" {
if config.Instance.SSLType == config.SSLTypeAutoHTTP || config.Instance.SSLType == config.SSLTypeAutoDNS {
go sslUpdateLoop()
} else {
go sslCheck()
Expand All @@ -45,6 +45,7 @@ func sslCheck() {
log.Errorf("SSL Check Error! %+v", err)
}
if newExpTime != expiredTime {
expiredTime = newExpTime
log.Infoln("SSL certificate had update! restarting")
signal.RestartChan <- true
}
Expand Down
19 changes: 19 additions & 0 deletions server/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ func TestMaster(t *testing.T) {
t.Run("testSendEmail", testSendEmail)
time.Sleep(8 * time.Second)
t.Run("testEmailList", testEmailList)
t.Run("testGetDetail", testGetEmailDetail)
t.Run("testDelEmail", testDelEmail)

t.Run("testSendEmail2User1", testSendEmail2User1)
Expand Down Expand Up @@ -108,6 +109,23 @@ func testCheckRule(t *testing.T) {
}
}

func testGetEmailDetail(t *testing.T) {
ret, err := httpClient.Post(TestHost+"/api/email/detail", "application/json", strings.NewReader(`{
"id":1
}`))
if err != nil {
t.Error(err)
}
data, err := readResponse(ret.Body)
if err != nil {
t.Error(err)
}
if data.ErrorNo != 0 {
t.Error("GetEmailDetail Error! ", data)
}

}

func testCreateRule(t *testing.T) {
ret, err := httpClient.Post(TestHost+"/api/rule/add", "application/json", strings.NewReader(`{
"name":"Move Group",
Expand Down Expand Up @@ -703,6 +721,7 @@ func testSendEmail2User3(t *testing.T) {
t.Logf("testSendEmail2User3 Success! Response: %+v", data)

}

func testEmailList(t *testing.T) {
ret, err := httpClient.Post(TestHost+"/api/email/list", "application/json", strings.NewReader(`{}`))
if err != nil {
Expand Down
2 changes: 1 addition & 1 deletion server/services/detail/detail.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ func GetEmailDetail(ctx *context.Context, id int, markRead bool) (*response.Emai

//获取邮件内容
var email response.EmailResponseData
_, err = db.Instance.ID(id).Get(&email)
_, err = db.Instance.Select("*,1 as is_read").Table("email").Where("id=?", id).Get(&email)
if err != nil {
log.WithContext(ctx).Errorf("SQL error:%+v", err)
return nil, err
Expand Down
65 changes: 65 additions & 0 deletions server/services/setup/ssl/challenge.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
package ssl

import (
"github.com/go-acme/lego/v4/challenge/dns01"
log "github.com/sirupsen/logrus"
"pmail/utils/context"
"time"
)

type authInfo struct {
Domain string
Token string
Expand Down Expand Up @@ -35,3 +42,61 @@ func GetHttpChallengeInstance() *HttpChallenge {
}
return instance
}

type DNSChallenge struct {
AuthInfo map[string]*authInfo
}

var dnsInstance *DNSChallenge

func GetDnsChallengeInstance() *DNSChallenge {
if dnsInstance == nil {
dnsInstance = &DNSChallenge{
AuthInfo: map[string]*authInfo{},
}
}
return dnsInstance
}

func (h *DNSChallenge) Present(domain, token, keyAuth string) error {
info := dns01.GetChallengeInfo(domain, keyAuth)
log.Infof("Presenting challenge Info : %+v", info)
h.AuthInfo[token] = &authInfo{
Domain: info.FQDN,
Token: token,
KeyAuth: info.Value,
}
log.Infof("SSL Log:%s %s %s", domain, token, keyAuth)
return nil
}

func (h *DNSChallenge) CleanUp(domain, token, keyAuth string) error {
delete(h.AuthInfo, token)
return nil
}

func (h *DNSChallenge) Timeout() (timeout, interval time.Duration) {
return 60 * time.Minute, 5 * time.Second
}

type DNSItem struct {
Type string `json:"type"`
Host string `json:"host"`
Value string `json:"value"`
TTL int `json:"ttl"`
Tips string `json:"tips"`
}

func (h *DNSChallenge) GetDNSSettings(ctx *context.Context) []*DNSItem {
ret := []*DNSItem{}
for _, info := range h.AuthInfo {
ret = append(ret, &DNSItem{
Type: "TXT",
Host: info.Domain,
Value: info.KeyAuth,
TTL: 3600,
})
}

return ret
}
Loading

0 comments on commit e4c5ec5

Please sign in to comment.