mirror of
https://github.com/0xJacky/nginx-ui.git
synced 2025-05-11 02:15:48 +02:00
change work dir
This commit is contained in:
parent
ce850f5e59
commit
08b54b5bbb
31 changed files with 260 additions and 259 deletions
12
main.go
12
main.go
|
@ -3,10 +3,10 @@ package main
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"flag"
|
"flag"
|
||||||
"github.com/0xJacky/Nginx-UI/model"
|
"github.com/0xJacky/Nginx-UI/server/model"
|
||||||
"github.com/0xJacky/Nginx-UI/router"
|
"github.com/0xJacky/Nginx-UI/server/router"
|
||||||
"github.com/0xJacky/Nginx-UI/settings"
|
"github.com/0xJacky/Nginx-UI/server/settings"
|
||||||
"github.com/0xJacky/Nginx-UI/tool"
|
tool2 "github.com/0xJacky/Nginx-UI/server/tool"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
|
@ -31,9 +31,9 @@ func main() {
|
||||||
Handler: router.InitRouter(),
|
Handler: router.InitRouter(),
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Printf("nginx config dir path: %s", tool.GetNginxConfPath(""))
|
log.Printf("nginx config dir path: %s", tool2.GetNginxConfPath(""))
|
||||||
|
|
||||||
go tool.AutoCert()
|
go tool2.AutoCert()
|
||||||
|
|
||||||
// Initializing the server in a goroutine so that
|
// Initializing the server in a goroutine so that
|
||||||
// it won't block the graceful shutdown handling below
|
// it won't block the graceful shutdown handling below
|
||||||
|
|
|
@ -6,5 +6,6 @@ After=network.target
|
||||||
[Service]
|
[Service]
|
||||||
Type=simple
|
Type=simple
|
||||||
ExecStart=/usr/local/bin/nginx-ui -d /usr/local/etc/nginx-ui
|
ExecStart=/usr/local/bin/nginx-ui -d /usr/local/etc/nginx-ui
|
||||||
|
Restart=on-failure
|
||||||
TimeoutStopSec=5
|
TimeoutStopSec=5
|
||||||
KillMode=mixed
|
KillMode=mixed
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package api
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/0xJacky/Nginx-UI/model"
|
"github.com/0xJacky/Nginx-UI/server/model"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"golang.org/x/crypto/bcrypt"
|
"golang.org/x/crypto/bcrypt"
|
||||||
"net/http"
|
"net/http"
|
|
@ -1,7 +1,7 @@
|
||||||
package api
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/0xJacky/Nginx-UI/model"
|
"github.com/0xJacky/Nginx-UI/server/model"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/unknwon/com"
|
"github.com/unknwon/com"
|
||||||
"net/http"
|
"net/http"
|
|
@ -2,7 +2,7 @@ package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"github.com/0xJacky/Nginx-UI/tool"
|
tool2 "github.com/0xJacky/Nginx-UI/server/tool"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/gorilla/websocket"
|
"github.com/gorilla/websocket"
|
||||||
"log"
|
"log"
|
||||||
|
@ -13,7 +13,7 @@ import (
|
||||||
func CertInfo(c *gin.Context) {
|
func CertInfo(c *gin.Context) {
|
||||||
domain := c.Param("domain")
|
domain := c.Param("domain")
|
||||||
|
|
||||||
key := tool.GetCertInfo(domain)
|
key := tool2.GetCertInfo(domain)
|
||||||
|
|
||||||
c.JSON(http.StatusOK, gin.H{
|
c.JSON(http.StatusOK, gin.H{
|
||||||
"subject_name": key.Subject.CommonName,
|
"subject_name": key.Subject.CommonName,
|
||||||
|
@ -55,7 +55,7 @@ func IssueCert(c *gin.Context) {
|
||||||
if string(message) == "go" {
|
if string(message) == "go" {
|
||||||
var m []byte
|
var m []byte
|
||||||
|
|
||||||
err = tool.IssueCert(domain)
|
err = tool2.IssueCert(domain)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
m, err = json.Marshal(gin.H{
|
m, err = json.Marshal(gin.H{
|
||||||
"status": "error",
|
"status": "error",
|
||||||
|
@ -78,7 +78,7 @@ func IssueCert(c *gin.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
sslCertificatePath := tool.GetNginxConfPath("ssl/" + domain + "/fullchain.cer")
|
sslCertificatePath := tool2.GetNginxConfPath("ssl/" + domain + "/fullchain.cer")
|
||||||
_, err = os.Stat(sslCertificatePath)
|
_, err = os.Stat(sslCertificatePath)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -104,7 +104,7 @@ func IssueCert(c *gin.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
sslCertificateKeyPath := tool.GetNginxConfPath("ssl/" + domain + "/" + domain + ".key")
|
sslCertificateKeyPath := tool2.GetNginxConfPath("ssl/" + domain + "/" + domain + ".key")
|
||||||
_, err = os.Stat(sslCertificateKeyPath)
|
_, err = os.Stat(sslCertificateKeyPath)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
|
@ -1,7 +1,7 @@
|
||||||
package api
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/0xJacky/Nginx-UI/tool"
|
tool2 "github.com/0xJacky/Nginx-UI/server/tool"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
|
@ -19,7 +19,7 @@ func GetConfigs(c *gin.Context) {
|
||||||
"modify": "time",
|
"modify": "time",
|
||||||
}
|
}
|
||||||
|
|
||||||
configFiles, err := ioutil.ReadDir(tool.GetNginxConfPath("/"))
|
configFiles, err := ioutil.ReadDir(tool2.GetNginxConfPath("/"))
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ErrHandler(c, err)
|
ErrHandler(c, err)
|
||||||
|
@ -40,7 +40,7 @@ func GetConfigs(c *gin.Context) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
configs = tool.Sort(orderBy, sort, mySort[orderBy], configs)
|
configs = tool2.Sort(orderBy, sort, mySort[orderBy], configs)
|
||||||
|
|
||||||
c.JSON(http.StatusOK, gin.H{
|
c.JSON(http.StatusOK, gin.H{
|
||||||
"configs": configs,
|
"configs": configs,
|
||||||
|
@ -49,7 +49,7 @@ func GetConfigs(c *gin.Context) {
|
||||||
|
|
||||||
func GetConfig(c *gin.Context) {
|
func GetConfig(c *gin.Context) {
|
||||||
name := c.Param("name")
|
name := c.Param("name")
|
||||||
path := filepath.Join(tool.GetNginxConfPath("/"), name)
|
path := filepath.Join(tool2.GetNginxConfPath("/"), name)
|
||||||
|
|
||||||
content, err := ioutil.ReadFile(path)
|
content, err := ioutil.ReadFile(path)
|
||||||
|
|
||||||
|
@ -80,7 +80,7 @@ func AddConfig(c *gin.Context) {
|
||||||
name := request.Name
|
name := request.Name
|
||||||
content := request.Content
|
content := request.Content
|
||||||
|
|
||||||
path := filepath.Join(tool.GetNginxConfPath("/"), name)
|
path := filepath.Join(tool2.GetNginxConfPath("/"), name)
|
||||||
|
|
||||||
log.Println(path)
|
log.Println(path)
|
||||||
if _, err = os.Stat(path); err == nil {
|
if _, err = os.Stat(path); err == nil {
|
||||||
|
@ -98,7 +98,7 @@ func AddConfig(c *gin.Context) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
output := tool.ReloadNginx()
|
output := tool2.ReloadNginx()
|
||||||
|
|
||||||
if output != "" {
|
if output != "" {
|
||||||
c.JSON(http.StatusInternalServerError, gin.H{
|
c.JSON(http.StatusInternalServerError, gin.H{
|
||||||
|
@ -126,7 +126,7 @@ func EditConfig(c *gin.Context) {
|
||||||
ErrHandler(c, err)
|
ErrHandler(c, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
path := filepath.Join(tool.GetNginxConfPath("/"), name)
|
path := filepath.Join(tool2.GetNginxConfPath("/"), name)
|
||||||
content := request.Content
|
content := request.Content
|
||||||
|
|
||||||
origContent, err := ioutil.ReadFile(path)
|
origContent, err := ioutil.ReadFile(path)
|
||||||
|
@ -144,7 +144,7 @@ func EditConfig(c *gin.Context) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
output := tool.ReloadNginx()
|
output := tool2.ReloadNginx()
|
||||||
|
|
||||||
if output != "" {
|
if output != "" {
|
||||||
c.JSON(http.StatusInternalServerError, gin.H{
|
c.JSON(http.StatusInternalServerError, gin.H{
|
|
@ -1,8 +1,8 @@
|
||||||
package api
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/0xJacky/Nginx-UI/model"
|
"github.com/0xJacky/Nginx-UI/server/model"
|
||||||
"github.com/0xJacky/Nginx-UI/tool"
|
tool2 "github.com/0xJacky/Nginx-UI/server/tool"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
@ -20,14 +20,14 @@ func GetDomains(c *gin.Context) {
|
||||||
"modify": "time",
|
"modify": "time",
|
||||||
}
|
}
|
||||||
|
|
||||||
configFiles, err := ioutil.ReadDir(tool.GetNginxConfPath("sites-available"))
|
configFiles, err := ioutil.ReadDir(tool2.GetNginxConfPath("sites-available"))
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ErrHandler(c, err)
|
ErrHandler(c, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
enabledConfig, err := ioutil.ReadDir(filepath.Join(tool.GetNginxConfPath("sites-enabled")))
|
enabledConfig, err := ioutil.ReadDir(filepath.Join(tool2.GetNginxConfPath("sites-enabled")))
|
||||||
|
|
||||||
enabledConfigMap := make(map[string]bool)
|
enabledConfigMap := make(map[string]bool)
|
||||||
for i := range enabledConfig {
|
for i := range enabledConfig {
|
||||||
|
@ -53,7 +53,7 @@ func GetDomains(c *gin.Context) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
configs = tool.Sort(orderBy, sort, mySort[orderBy], configs)
|
configs = tool2.Sort(orderBy, sort, mySort[orderBy], configs)
|
||||||
|
|
||||||
c.JSON(http.StatusOK, gin.H{
|
c.JSON(http.StatusOK, gin.H{
|
||||||
"configs": configs,
|
"configs": configs,
|
||||||
|
@ -62,10 +62,10 @@ func GetDomains(c *gin.Context) {
|
||||||
|
|
||||||
func GetDomain(c *gin.Context) {
|
func GetDomain(c *gin.Context) {
|
||||||
name := c.Param("name")
|
name := c.Param("name")
|
||||||
path := filepath.Join(tool.GetNginxConfPath("sites-available"), name)
|
path := filepath.Join(tool2.GetNginxConfPath("sites-available"), name)
|
||||||
|
|
||||||
enabled := true
|
enabled := true
|
||||||
if _, err := os.Stat(filepath.Join(tool.GetNginxConfPath("sites-enabled"), name)); os.IsNotExist(err) {
|
if _, err := os.Stat(filepath.Join(tool2.GetNginxConfPath("sites-enabled"), name)); os.IsNotExist(err) {
|
||||||
enabled = false
|
enabled = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,7 +98,7 @@ func EditDomain(c *gin.Context) {
|
||||||
name := c.Param("name")
|
name := c.Param("name")
|
||||||
request := make(gin.H)
|
request := make(gin.H)
|
||||||
err = c.BindJSON(&request)
|
err = c.BindJSON(&request)
|
||||||
path := filepath.Join(tool.GetNginxConfPath("sites-available"), name)
|
path := filepath.Join(tool2.GetNginxConfPath("sites-available"), name)
|
||||||
|
|
||||||
err = ioutil.WriteFile(path, []byte(request["content"].(string)), 0644)
|
err = ioutil.WriteFile(path, []byte(request["content"].(string)), 0644)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -106,10 +106,10 @@ func EditDomain(c *gin.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
enabledConfigFilePath := filepath.Join(tool.GetNginxConfPath("sites-enabled"), name)
|
enabledConfigFilePath := filepath.Join(tool2.GetNginxConfPath("sites-enabled"), name)
|
||||||
if _, err = os.Stat(enabledConfigFilePath); err == nil {
|
if _, err = os.Stat(enabledConfigFilePath); err == nil {
|
||||||
// 测试配置文件
|
// 测试配置文件
|
||||||
err = tool.TestNginxConf(enabledConfigFilePath)
|
err = tool2.TestNginxConf(enabledConfigFilePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(http.StatusInternalServerError, gin.H{
|
c.JSON(http.StatusInternalServerError, gin.H{
|
||||||
"message": err.Error(),
|
"message": err.Error(),
|
||||||
|
@ -117,7 +117,7 @@ func EditDomain(c *gin.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
output := tool.ReloadNginx()
|
output := tool2.ReloadNginx()
|
||||||
|
|
||||||
if output != "" {
|
if output != "" {
|
||||||
c.JSON(http.StatusInternalServerError, gin.H{
|
c.JSON(http.StatusInternalServerError, gin.H{
|
||||||
|
@ -131,8 +131,8 @@ func EditDomain(c *gin.Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func EnableDomain(c *gin.Context) {
|
func EnableDomain(c *gin.Context) {
|
||||||
configFilePath := filepath.Join(tool.GetNginxConfPath("sites-available"), c.Param("name"))
|
configFilePath := filepath.Join(tool2.GetNginxConfPath("sites-available"), c.Param("name"))
|
||||||
enabledConfigFilePath := filepath.Join(tool.GetNginxConfPath("sites-enabled"), c.Param("name"))
|
enabledConfigFilePath := filepath.Join(tool2.GetNginxConfPath("sites-enabled"), c.Param("name"))
|
||||||
|
|
||||||
_, err := os.Stat(configFilePath)
|
_, err := os.Stat(configFilePath)
|
||||||
|
|
||||||
|
@ -149,7 +149,7 @@ func EnableDomain(c *gin.Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 测试配置文件,不通过则撤回启用
|
// 测试配置文件,不通过则撤回启用
|
||||||
err = tool.TestNginxConf(enabledConfigFilePath)
|
err = tool2.TestNginxConf(enabledConfigFilePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
_ = os.Remove(enabledConfigFilePath)
|
_ = os.Remove(enabledConfigFilePath)
|
||||||
c.JSON(http.StatusInternalServerError, gin.H{
|
c.JSON(http.StatusInternalServerError, gin.H{
|
||||||
|
@ -158,7 +158,7 @@ func EnableDomain(c *gin.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
output := tool.ReloadNginx()
|
output := tool2.ReloadNginx()
|
||||||
|
|
||||||
if output != "" {
|
if output != "" {
|
||||||
c.JSON(http.StatusInternalServerError, gin.H{
|
c.JSON(http.StatusInternalServerError, gin.H{
|
||||||
|
@ -173,7 +173,7 @@ func EnableDomain(c *gin.Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func DisableDomain(c *gin.Context) {
|
func DisableDomain(c *gin.Context) {
|
||||||
enabledConfigFilePath := filepath.Join(tool.GetNginxConfPath("sites-enabled"), c.Param("name"))
|
enabledConfigFilePath := filepath.Join(tool2.GetNginxConfPath("sites-enabled"), c.Param("name"))
|
||||||
|
|
||||||
_, err := os.Stat(enabledConfigFilePath)
|
_, err := os.Stat(enabledConfigFilePath)
|
||||||
|
|
||||||
|
@ -189,7 +189,7 @@ func DisableDomain(c *gin.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
output := tool.ReloadNginx()
|
output := tool2.ReloadNginx()
|
||||||
|
|
||||||
if output != "" {
|
if output != "" {
|
||||||
c.JSON(http.StatusInternalServerError, gin.H{
|
c.JSON(http.StatusInternalServerError, gin.H{
|
||||||
|
@ -206,8 +206,8 @@ func DisableDomain(c *gin.Context) {
|
||||||
func DeleteDomain(c *gin.Context) {
|
func DeleteDomain(c *gin.Context) {
|
||||||
var err error
|
var err error
|
||||||
name := c.Param("name")
|
name := c.Param("name")
|
||||||
availablePath := filepath.Join(tool.GetNginxConfPath("sites-available"), name)
|
availablePath := filepath.Join(tool2.GetNginxConfPath("sites-available"), name)
|
||||||
enabledPath := filepath.Join(tool.GetNginxConfPath("sites-enabled"), name)
|
enabledPath := filepath.Join(tool2.GetNginxConfPath("sites-enabled"), name)
|
||||||
|
|
||||||
if _, err = os.Stat(availablePath); os.IsNotExist(err) {
|
if _, err = os.Stat(availablePath); os.IsNotExist(err) {
|
||||||
c.JSON(http.StatusNotFound, gin.H{
|
c.JSON(http.StatusNotFound, gin.H{
|
|
@ -1,8 +1,8 @@
|
||||||
package api
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/0xJacky/Nginx-UI/model"
|
model2 "github.com/0xJacky/Nginx-UI/server/model"
|
||||||
"github.com/0xJacky/Nginx-UI/settings"
|
"github.com/0xJacky/Nginx-UI/server/settings"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"golang.org/x/crypto/bcrypt"
|
"golang.org/x/crypto/bcrypt"
|
||||||
|
@ -54,9 +54,9 @@ func InstallNginxUI(c *gin.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
curd := model.NewCurd(&model.Auth{})
|
curd := model2.NewCurd(&model2.Auth{})
|
||||||
pwd, _ := bcrypt.GenerateFromPassword([]byte(json.Password), bcrypt.DefaultCost)
|
pwd, _ := bcrypt.GenerateFromPassword([]byte(json.Password), bcrypt.DefaultCost)
|
||||||
err = curd.Add(&model.Auth{
|
err = curd.Add(&model2.Auth{
|
||||||
Name: json.Username,
|
Name: json.Username,
|
||||||
Password: string(pwd),
|
Password: string(pwd),
|
||||||
})
|
})
|
|
@ -1,7 +1,7 @@
|
||||||
package api
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/0xJacky/Nginx-UI/settings"
|
"github.com/0xJacky/Nginx-UI/server/settings"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
|
@ -2,7 +2,7 @@ package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"github.com/0xJacky/Nginx-UI/model"
|
model2 "github.com/0xJacky/Nginx-UI/server/model"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/spf13/cast"
|
"github.com/spf13/cast"
|
||||||
"golang.org/x/crypto/bcrypt"
|
"golang.org/x/crypto/bcrypt"
|
||||||
|
@ -10,9 +10,9 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetUsers(c *gin.Context) {
|
func GetUsers(c *gin.Context) {
|
||||||
curd := model.NewCurd(&model.Auth{})
|
curd := model2.NewCurd(&model2.Auth{})
|
||||||
|
|
||||||
var list []model.Auth
|
var list []model2.Auth
|
||||||
err := curd.GetList(&list)
|
err := curd.GetList(&list)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -25,10 +25,10 @@ func GetUsers(c *gin.Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetUser(c *gin.Context) {
|
func GetUser(c *gin.Context) {
|
||||||
curd := model.NewCurd(&model.Auth{})
|
curd := model2.NewCurd(&model2.Auth{})
|
||||||
id := c.Param("id")
|
id := c.Param("id")
|
||||||
|
|
||||||
var user model.Auth
|
var user model2.Auth
|
||||||
err := curd.First(&user, id)
|
err := curd.First(&user, id)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -49,7 +49,7 @@ func AddUser(c *gin.Context) {
|
||||||
if !ok {
|
if !ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
curd := model.NewCurd(&model.Auth{})
|
curd := model2.NewCurd(&model2.Auth{})
|
||||||
|
|
||||||
pwd, err := bcrypt.GenerateFromPassword([]byte(json.Password), bcrypt.DefaultCost)
|
pwd, err := bcrypt.GenerateFromPassword([]byte(json.Password), bcrypt.DefaultCost)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -58,7 +58,7 @@ func AddUser(c *gin.Context) {
|
||||||
}
|
}
|
||||||
json.Password = string(pwd)
|
json.Password = string(pwd)
|
||||||
|
|
||||||
user := model.Auth{
|
user := model2.Auth{
|
||||||
Name: json.Name,
|
Name: json.Name,
|
||||||
Password: json.Password,
|
Password: json.Password,
|
||||||
}
|
}
|
||||||
|
@ -80,9 +80,9 @@ func EditUser(c *gin.Context) {
|
||||||
if !ok {
|
if !ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
curd := model.NewCurd(&model.Auth{})
|
curd := model2.NewCurd(&model2.Auth{})
|
||||||
|
|
||||||
var user, edit model.Auth
|
var user, edit model2.Auth
|
||||||
|
|
||||||
err := curd.First(&user, c.Param("id"))
|
err := curd.First(&user, c.Param("id"))
|
||||||
|
|
||||||
|
@ -120,8 +120,8 @@ func DeleteUser(c *gin.Context) {
|
||||||
ErrHandler(c, errors.New("不允许删除默认账户"))
|
ErrHandler(c, errors.New("不允许删除默认账户"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
curd := model.NewCurd(&model.Auth{})
|
curd := model2.NewCurd(&model2.Auth{})
|
||||||
err := curd.Delete(&model.Auth{}, "id", id)
|
err := curd.Delete(&model2.Auth{}, "id", id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ErrHandler(c, err)
|
ErrHandler(c, err)
|
||||||
return
|
return
|
|
@ -1,7 +1,7 @@
|
||||||
package model
|
package model
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/0xJacky/Nginx-UI/settings"
|
"github.com/0xJacky/Nginx-UI/server/settings"
|
||||||
"github.com/dgrijalva/jwt-go"
|
"github.com/dgrijalva/jwt-go"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
|
@ -1,7 +1,7 @@
|
||||||
package model
|
package model
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/0xJacky/Nginx-UI/settings"
|
"github.com/0xJacky/Nginx-UI/server/settings"
|
||||||
"gorm.io/driver/sqlite"
|
"gorm.io/driver/sqlite"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
"gorm.io/gorm/logger"
|
"gorm.io/gorm/logger"
|
|
@ -3,9 +3,9 @@ package router
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"github.com/0xJacky/Nginx-UI/api"
|
|
||||||
"github.com/0xJacky/Nginx-UI/frontend"
|
"github.com/0xJacky/Nginx-UI/frontend"
|
||||||
"github.com/0xJacky/Nginx-UI/model"
|
api2 "github.com/0xJacky/Nginx-UI/server/api"
|
||||||
|
"github.com/0xJacky/Nginx-UI/server/model"
|
||||||
"github.com/gin-contrib/static"
|
"github.com/gin-contrib/static"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"io/fs"
|
"io/fs"
|
||||||
|
@ -87,46 +87,46 @@ func InitRouter() *gin.Engine {
|
||||||
|
|
||||||
g := r.Group("/api")
|
g := r.Group("/api")
|
||||||
{
|
{
|
||||||
g.GET("install", api.InstallLockCheck)
|
g.GET("install", api2.InstallLockCheck)
|
||||||
g.POST("install", api.InstallNginxUI)
|
g.POST("install", api2.InstallNginxUI)
|
||||||
|
|
||||||
g.POST("/login", api.Login)
|
g.POST("/login", api2.Login)
|
||||||
g.DELETE("/logout", api.Logout)
|
g.DELETE("/logout", api2.Logout)
|
||||||
|
|
||||||
g := g.Group("/", authRequired())
|
g := g.Group("/", authRequired())
|
||||||
{
|
{
|
||||||
g.GET("/analytic", api.Analytic)
|
g.GET("/analytic", api2.Analytic)
|
||||||
|
|
||||||
g.GET("/users", api.GetUsers)
|
g.GET("/users", api2.GetUsers)
|
||||||
g.GET("/user/:id", api.GetUser)
|
g.GET("/user/:id", api2.GetUser)
|
||||||
g.POST("/user", api.AddUser)
|
g.POST("/user", api2.AddUser)
|
||||||
g.POST("/user/:id", api.EditUser)
|
g.POST("/user/:id", api2.EditUser)
|
||||||
g.DELETE("/user/:id", api.DeleteUser)
|
g.DELETE("/user/:id", api2.DeleteUser)
|
||||||
|
|
||||||
g.GET("domains", api.GetDomains)
|
g.GET("domains", api2.GetDomains)
|
||||||
g.GET("domain/:name", api.GetDomain)
|
g.GET("domain/:name", api2.GetDomain)
|
||||||
g.POST("domain/:name", api.EditDomain)
|
g.POST("domain/:name", api2.EditDomain)
|
||||||
g.POST("domain/:name/enable", api.EnableDomain)
|
g.POST("domain/:name/enable", api2.EnableDomain)
|
||||||
g.POST("domain/:name/disable", api.DisableDomain)
|
g.POST("domain/:name/disable", api2.DisableDomain)
|
||||||
g.DELETE("domain/:name", api.DeleteDomain)
|
g.DELETE("domain/:name", api2.DeleteDomain)
|
||||||
|
|
||||||
g.GET("configs", api.GetConfigs)
|
g.GET("configs", api2.GetConfigs)
|
||||||
g.GET("config/:name", api.GetConfig)
|
g.GET("config/:name", api2.GetConfig)
|
||||||
g.POST("config", api.AddConfig)
|
g.POST("config", api2.AddConfig)
|
||||||
g.POST("config/:name", api.EditConfig)
|
g.POST("config/:name", api2.EditConfig)
|
||||||
|
|
||||||
g.GET("backups", api.GetFileBackupList)
|
g.GET("backups", api2.GetFileBackupList)
|
||||||
g.GET("backup/:id", api.GetFileBackup)
|
g.GET("backup/:id", api2.GetFileBackup)
|
||||||
|
|
||||||
g.GET("template/:name", api.GetTemplate)
|
g.GET("template/:name", api2.GetTemplate)
|
||||||
|
|
||||||
g.GET("cert/issue/:domain", api.IssueCert)
|
g.GET("cert/issue/:domain", api2.IssueCert)
|
||||||
g.GET("cert/:domain/info", api.CertInfo)
|
g.GET("cert/:domain/info", api2.CertInfo)
|
||||||
|
|
||||||
// 添加域名到自动续期列表
|
// 添加域名到自动续期列表
|
||||||
g.POST("cert/:domain", api.AddDomainToAutoCert)
|
g.POST("cert/:domain", api2.AddDomainToAutoCert)
|
||||||
// 从自动续期列表中删除域名
|
// 从自动续期列表中删除域名
|
||||||
g.DELETE("cert/:domain", api.RemoveDomainFromAutoCert)
|
g.DELETE("cert/:domain", api2.RemoveDomainFromAutoCert)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ package test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/0xJacky/Nginx-UI/tool"
|
"github.com/0xJacky/Nginx-UI/server/tool"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
|
@ -2,7 +2,7 @@ package test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/0xJacky/Nginx-UI/tool"
|
"github.com/0xJacky/Nginx-UI/server/tool"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
169
server/tool/cert.go
Normal file
169
server/tool/cert.go
Normal file
|
@ -0,0 +1,169 @@
|
||||||
|
package tool
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto"
|
||||||
|
"crypto/ecdsa"
|
||||||
|
"crypto/elliptic"
|
||||||
|
"crypto/rand"
|
||||||
|
"crypto/tls"
|
||||||
|
"crypto/x509"
|
||||||
|
"github.com/0xJacky/Nginx-UI/server/model"
|
||||||
|
"github.com/0xJacky/Nginx-UI/server/settings"
|
||||||
|
"github.com/go-acme/lego/v4/certcrypto"
|
||||||
|
"github.com/go-acme/lego/v4/certificate"
|
||||||
|
"github.com/go-acme/lego/v4/challenge/http01"
|
||||||
|
"github.com/go-acme/lego/v4/lego"
|
||||||
|
"github.com/go-acme/lego/v4/registration"
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MyUser You'll need a user or account type that implements acme.User
|
||||||
|
type MyUser struct {
|
||||||
|
Email string
|
||||||
|
Registration *registration.Resource
|
||||||
|
key crypto.PrivateKey
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *MyUser) GetEmail() string {
|
||||||
|
return u.Email
|
||||||
|
}
|
||||||
|
func (u MyUser) GetRegistration() *registration.Resource {
|
||||||
|
return u.Registration
|
||||||
|
}
|
||||||
|
func (u *MyUser) GetPrivateKey() crypto.PrivateKey {
|
||||||
|
return u.key
|
||||||
|
}
|
||||||
|
|
||||||
|
func AutoCert() {
|
||||||
|
for {
|
||||||
|
log.Println("[AutoCert] Start")
|
||||||
|
autoCertList := model.GetAutoCertList()
|
||||||
|
for i := range autoCertList {
|
||||||
|
domain := autoCertList[i].Domain
|
||||||
|
key := GetCertInfo(domain)
|
||||||
|
// 未到一个月
|
||||||
|
if time.Now().Before(key.NotBefore.AddDate(0, 1, 0)) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// 过一个月了
|
||||||
|
err := IssueCert(domain)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
time.Sleep(1 * time.Hour)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetCertInfo(domain string) (key *x509.Certificate) {
|
||||||
|
ts := &http.Transport{
|
||||||
|
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
||||||
|
}
|
||||||
|
|
||||||
|
client := &http.Client{Transport: ts}
|
||||||
|
|
||||||
|
response, err := client.Get("https://" + domain)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
defer func(Body io.ReadCloser) {
|
||||||
|
err = Body.Close()
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}(response.Body)
|
||||||
|
|
||||||
|
key = response.TLS.PeerCertificates[0]
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func IssueCert(domain string) error {
|
||||||
|
// Create a user. New accounts need an email and private key to start.
|
||||||
|
privateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
myUser := MyUser{
|
||||||
|
Email: settings.ServerSettings.Email,
|
||||||
|
key: privateKey,
|
||||||
|
}
|
||||||
|
|
||||||
|
config := lego.NewConfig(&myUser)
|
||||||
|
|
||||||
|
//config.CADirURL = "https://acme-staging-v02.api.letsencrypt.org/directory"
|
||||||
|
config.Certificate.KeyType = certcrypto.RSA2048
|
||||||
|
|
||||||
|
// A client facilitates communication with the CA server.
|
||||||
|
client, err := lego.NewClient(config)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = client.Challenge.SetHTTP01Provider(
|
||||||
|
http01.NewProviderServer("",
|
||||||
|
settings.ServerSettings.HTTPChallengePort,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// New users will need to register
|
||||||
|
reg, err := client.Registration.Register(registration.RegisterOptions{TermsOfServiceAgreed: true})
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
myUser.Registration = reg
|
||||||
|
|
||||||
|
request := certificate.ObtainRequest{
|
||||||
|
Domains: []string{domain},
|
||||||
|
Bundle: true,
|
||||||
|
}
|
||||||
|
certificates, err := client.Certificate.Obtain(request)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
saveDir := GetNginxConfPath("ssl/" + domain)
|
||||||
|
if _, err := os.Stat(saveDir); os.IsNotExist(err) {
|
||||||
|
err = os.Mkdir(saveDir, 0755)
|
||||||
|
if err != nil {
|
||||||
|
log.Println("fail to create", saveDir)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Each certificate comes back with the cert bytes, the bytes of the client's
|
||||||
|
// private key, and a certificate URL. SAVE THESE TO DISK.
|
||||||
|
err = ioutil.WriteFile(filepath.Join(saveDir, "fullchain.cer"),
|
||||||
|
certificates.Certificate, 0644)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = ioutil.WriteFile(filepath.Join(saveDir, domain+".key"),
|
||||||
|
certificates.PrivateKey, 0644)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
ReloadNginx()
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
169
tool/cert.go
169
tool/cert.go
|
@ -1,169 +0,0 @@
|
||||||
package tool
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto"
|
|
||||||
"crypto/ecdsa"
|
|
||||||
"crypto/elliptic"
|
|
||||||
"crypto/rand"
|
|
||||||
"crypto/tls"
|
|
||||||
"crypto/x509"
|
|
||||||
"github.com/0xJacky/Nginx-UI/model"
|
|
||||||
"github.com/0xJacky/Nginx-UI/settings"
|
|
||||||
"github.com/go-acme/lego/v4/certcrypto"
|
|
||||||
"github.com/go-acme/lego/v4/certificate"
|
|
||||||
"github.com/go-acme/lego/v4/challenge/http01"
|
|
||||||
"github.com/go-acme/lego/v4/lego"
|
|
||||||
"github.com/go-acme/lego/v4/registration"
|
|
||||||
"io"
|
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
|
||||||
"net/http"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
// MyUser You'll need a user or account type that implements acme.User
|
|
||||||
type MyUser struct {
|
|
||||||
Email string
|
|
||||||
Registration *registration.Resource
|
|
||||||
key crypto.PrivateKey
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *MyUser) GetEmail() string {
|
|
||||||
return u.Email
|
|
||||||
}
|
|
||||||
func (u MyUser) GetRegistration() *registration.Resource {
|
|
||||||
return u.Registration
|
|
||||||
}
|
|
||||||
func (u *MyUser) GetPrivateKey() crypto.PrivateKey {
|
|
||||||
return u.key
|
|
||||||
}
|
|
||||||
|
|
||||||
func AutoCert() {
|
|
||||||
for {
|
|
||||||
log.Println("[AutoCert] Start")
|
|
||||||
autoCertList := model.GetAutoCertList()
|
|
||||||
for i := range autoCertList {
|
|
||||||
domain := autoCertList[i].Domain
|
|
||||||
key := GetCertInfo(domain)
|
|
||||||
// 未到一个月
|
|
||||||
if time.Now().Before(key.NotBefore.AddDate(0, 1, 0)) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
// 过一个月了
|
|
||||||
err := IssueCert(domain)
|
|
||||||
if err != nil {
|
|
||||||
log.Println(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
time.Sleep(1 * time.Hour)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetCertInfo(domain string) (key *x509.Certificate) {
|
|
||||||
ts := &http.Transport{
|
|
||||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
|
||||||
}
|
|
||||||
|
|
||||||
client := &http.Client{Transport: ts}
|
|
||||||
|
|
||||||
response, err := client.Get("https://" + domain)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
defer func(Body io.ReadCloser) {
|
|
||||||
err = Body.Close()
|
|
||||||
if err != nil {
|
|
||||||
log.Println(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}(response.Body)
|
|
||||||
|
|
||||||
key = response.TLS.PeerCertificates[0]
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func IssueCert(domain string) error {
|
|
||||||
// Create a user. New accounts need an email and private key to start.
|
|
||||||
privateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
|
||||||
if err != nil {
|
|
||||||
log.Println(err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
myUser := MyUser{
|
|
||||||
Email: settings.ServerSettings.Email,
|
|
||||||
key: privateKey,
|
|
||||||
}
|
|
||||||
|
|
||||||
config := lego.NewConfig(&myUser)
|
|
||||||
|
|
||||||
//config.CADirURL = "https://acme-staging-v02.api.letsencrypt.org/directory"
|
|
||||||
config.Certificate.KeyType = certcrypto.RSA2048
|
|
||||||
|
|
||||||
// A client facilitates communication with the CA server.
|
|
||||||
client, err := lego.NewClient(config)
|
|
||||||
if err != nil {
|
|
||||||
log.Println(err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = client.Challenge.SetHTTP01Provider(
|
|
||||||
http01.NewProviderServer("",
|
|
||||||
settings.ServerSettings.HTTPChallengePort,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
log.Println(err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// New users will need to register
|
|
||||||
reg, err := client.Registration.Register(registration.RegisterOptions{TermsOfServiceAgreed: true})
|
|
||||||
if err != nil {
|
|
||||||
log.Println(err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
myUser.Registration = reg
|
|
||||||
|
|
||||||
request := certificate.ObtainRequest{
|
|
||||||
Domains: []string{domain},
|
|
||||||
Bundle: true,
|
|
||||||
}
|
|
||||||
certificates, err := client.Certificate.Obtain(request)
|
|
||||||
if err != nil {
|
|
||||||
log.Println(err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
saveDir := GetNginxConfPath("ssl/" + domain)
|
|
||||||
if _, err := os.Stat(saveDir); os.IsNotExist(err) {
|
|
||||||
err = os.Mkdir(saveDir, 0755)
|
|
||||||
if err != nil {
|
|
||||||
log.Println("fail to create", saveDir)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Each certificate comes back with the cert bytes, the bytes of the client's
|
|
||||||
// private key, and a certificate URL. SAVE THESE TO DISK.
|
|
||||||
err = ioutil.WriteFile(filepath.Join(saveDir, "fullchain.cer"),
|
|
||||||
certificates.Certificate, 0644)
|
|
||||||
if err != nil {
|
|
||||||
log.Println(err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
err = ioutil.WriteFile(filepath.Join(saveDir, domain+".key"),
|
|
||||||
certificates.PrivateKey, 0644)
|
|
||||||
if err != nil {
|
|
||||||
log.Println(err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
ReloadNginx()
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
Loading…
Add table
Add a link
Reference in a new issue