feat: add compatible Trojan manager image
This commit is contained in:
@@ -123,6 +123,12 @@ func RequestUsername(c *gin.Context) string {
|
||||
return claims[identityKey].(string)
|
||||
}
|
||||
|
||||
func RequireAdmin(c *gin.Context) bool {
|
||||
if RequestUsername(c) == "admin" { return true }
|
||||
c.JSON(403, gin.H{"code": 403, "message": "administrator access required"})
|
||||
return false
|
||||
}
|
||||
|
||||
// Auth 权限router
|
||||
func Auth(r *gin.Engine, timeout int) *jwt.GinJWTMiddleware {
|
||||
jwtInit(timeout)
|
||||
@@ -152,7 +158,10 @@ func Auth(r *gin.Engine, timeout int) *jwt.GinJWTMiddleware {
|
||||
}
|
||||
})
|
||||
r.POST("/auth/login", authMiddleware.LoginHandler)
|
||||
r.POST("/auth/register", updateUser)
|
||||
r.POST("/auth/register", func(c *gin.Context) {
|
||||
if result, _ := core.GetValue("admin_pass"); result != "" { c.JSON(403, gin.H{"code":403,"message":"administrator already initialized"}); return }
|
||||
updateUser(c)
|
||||
})
|
||||
authO := r.Group("/auth")
|
||||
authO.Use(authMiddleware.MiddlewareFunc())
|
||||
{
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"crypto/x509"
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
"os"
|
||||
"time"
|
||||
"trojan/managerconfig"
|
||||
)
|
||||
|
||||
func SystemConfig() *ResponseBody { c, err := managerconfig.Load(); r := &ResponseBody{Msg:"success", Data:c}; if err != nil { r.Msg=err.Error() }; return r }
|
||||
func ValidateSystemConfig(c managerconfig.Config) *ResponseBody { r:=&ResponseBody{Msg:"success"}; if err:=managerconfig.Validate(c); err != nil { r.Msg=err.Error() }; return r }
|
||||
func ApplySystemConfig(c managerconfig.Config) *ResponseBody { r:=ValidateSystemConfig(c); if r.Msg!="success" { return r }; if err:=managerconfig.Save(c); err!=nil { r.Msg=err.Error(); return r }; r.Data=map[string]bool{"restartRequired":true,"nginxReloadRequired":false,"containerRecreateRequired":false}; return r }
|
||||
func CertificateStatus() *ResponseBody {
|
||||
r:=&ResponseBody{Msg:"success"}; b,err:=os.ReadFile("/etc/trojan/certs/fullchain.pem"); if err!=nil { r.Msg=err.Error(); return r }; block,_:=pem.Decode(b); if block==nil { r.Msg="invalid certificate PEM"; return r }; cert,err:=x509.ParseCertificate(block.Bytes); if err!=nil { r.Msg=err.Error(); return r }
|
||||
r.Data=map[string]interface{}{"subject":cert.Subject.String(),"issuer":cert.Issuer.String(),"dnsNames":cert.DNSNames,"notBefore":cert.NotBefore,"notAfter":cert.NotAfter,"daysRemaining":int(time.Until(cert.NotAfter).Hours()/24),"serialNumber":fmt.Sprint(cert.SerialNumber)}; return r
|
||||
}
|
||||
@@ -20,7 +20,7 @@ import (
|
||||
func Start() *ResponseBody {
|
||||
responseBody := ResponseBody{Msg: "success"}
|
||||
defer TimeCost(time.Now(), &responseBody)
|
||||
trojan.Start()
|
||||
if err := trojan.Start(); err != nil { responseBody.Msg = err.Error() }
|
||||
return &responseBody
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ func Start() *ResponseBody {
|
||||
func Stop() *ResponseBody {
|
||||
responseBody := ResponseBody{Msg: "success"}
|
||||
defer TimeCost(time.Now(), &responseBody)
|
||||
trojan.Stop()
|
||||
if err := trojan.Stop(); err != nil { responseBody.Msg = err.Error() }
|
||||
return &responseBody
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ func Stop() *ResponseBody {
|
||||
func Restart() *ResponseBody {
|
||||
responseBody := ResponseBody{Msg: "success"}
|
||||
defer TimeCost(time.Now(), &responseBody)
|
||||
trojan.Restart()
|
||||
if err := trojan.Restart(); err != nil { responseBody.Msg = err.Error() }
|
||||
return &responseBody
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ func SetLogLevel(level int) *ResponseBody {
|
||||
responseBody := ResponseBody{Msg: "success"}
|
||||
defer TimeCost(time.Now(), &responseBody)
|
||||
core.WriteLogLevel(level)
|
||||
trojan.Restart()
|
||||
if err := trojan.Restart(); err != nil { responseBody.Msg = err.Error() }
|
||||
return &responseBody
|
||||
}
|
||||
|
||||
|
||||
@@ -36,8 +36,8 @@ func UserList(requestUser string) *ResponseBody {
|
||||
}
|
||||
domain, port := trojan.GetDomainAndPort()
|
||||
responseBody.Data = map[string]interface{}{
|
||||
"domain": domain,
|
||||
"port": port,
|
||||
"domain": domain, "port": port, "publicPort": port,
|
||||
"listenPort": core.GetConfig().LocalPort,
|
||||
"userList": userList,
|
||||
}
|
||||
return &responseBody
|
||||
@@ -55,8 +55,8 @@ func PageUserList(curPage int, pageSize int) *ResponseBody {
|
||||
}
|
||||
domain, port := trojan.GetDomainAndPort()
|
||||
responseBody.Data = map[string]interface{}{
|
||||
"domain": domain,
|
||||
"port": port,
|
||||
"domain": domain, "port": port, "publicPort": port,
|
||||
"listenPort": core.GetConfig().LocalPort,
|
||||
"pageData": pageData,
|
||||
}
|
||||
return &responseBody
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"io/fs"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"trojan/managerconfig"
|
||||
"trojan/core"
|
||||
"trojan/util"
|
||||
"trojan/web/controller"
|
||||
@@ -171,6 +172,14 @@ func noTokenRouter(router *gin.Engine) {
|
||||
})
|
||||
}
|
||||
|
||||
func systemRouter(router *gin.Engine) {
|
||||
system := router.Group("/system")
|
||||
system.GET("/config", func(c *gin.Context) { if !RequireAdmin(c) { return }; c.JSON(200, controller.SystemConfig()) })
|
||||
system.POST("/config/validate", func(c *gin.Context) { if !RequireAdmin(c) { return }; var cfg managerconfig.Config; if err:=c.ShouldBindJSON(&cfg); err!=nil { c.JSON(400, gin.H{"message":err.Error()}); return }; c.JSON(200, controller.ValidateSystemConfig(cfg)) })
|
||||
system.POST("/config/apply", func(c *gin.Context) { if !RequireAdmin(c) { return }; var cfg managerconfig.Config; if err:=c.ShouldBindJSON(&cfg); err!=nil { c.JSON(400, gin.H{"message":err.Error()}); return }; c.JSON(200, controller.ApplySystemConfig(cfg)) })
|
||||
system.GET("/certificate", func(c *gin.Context) { if !RequireAdmin(c) { return }; c.JSON(200, controller.CertificateStatus()) })
|
||||
}
|
||||
|
||||
// Start web启动入口
|
||||
func Start(host string, port, timeout int, isSSL bool) {
|
||||
router := gin.Default()
|
||||
@@ -178,7 +187,10 @@ func Start(host string, port, timeout int, isSSL bool) {
|
||||
router.Use(gzip.Gzip(gzip.DefaultCompression))
|
||||
staticRouter(router)
|
||||
noTokenRouter(router)
|
||||
router.GET("/healthz", func(c *gin.Context) { c.JSON(200, gin.H{"status":"ok"}) })
|
||||
router.GET("/readyz", func(c *gin.Context) { if core.GetConfig()==nil { c.JSON(503, gin.H{"status":"not ready"}); return }; c.JSON(200, gin.H{"status":"ready"}) })
|
||||
router.Use(Auth(router, timeout).MiddlewareFunc())
|
||||
systemRouter(router)
|
||||
trojanRouter(router)
|
||||
userRouter(router)
|
||||
dataRouter(router)
|
||||
|
||||
Reference in New Issue
Block a user