You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
313 lines
8.8 KiB
Go
313 lines
8.8 KiB
Go
package service
|
|
|
|
import (
|
|
"bufio"
|
|
"fmt"
|
|
"github.com/1Panel-dev/1Panel/agent/app/dto"
|
|
"github.com/1Panel-dev/1Panel/agent/app/dto/request"
|
|
"github.com/1Panel-dev/1Panel/agent/app/dto/response"
|
|
"github.com/1Panel-dev/1Panel/agent/app/model"
|
|
"github.com/1Panel-dev/1Panel/agent/app/repo"
|
|
"github.com/1Panel-dev/1Panel/agent/buserr"
|
|
"github.com/1Panel-dev/1Panel/agent/cmd/server/nginx_conf"
|
|
"github.com/1Panel-dev/1Panel/agent/constant"
|
|
"github.com/1Panel-dev/1Panel/agent/utils/files"
|
|
"github.com/1Panel-dev/1Panel/agent/utils/nginx"
|
|
"github.com/1Panel-dev/1Panel/agent/utils/nginx/components"
|
|
"github.com/1Panel-dev/1Panel/agent/utils/nginx/parser"
|
|
"golang.org/x/crypto/bcrypt"
|
|
"os"
|
|
"path"
|
|
"strings"
|
|
)
|
|
|
|
func (w WebsiteService) GetAuthBasics(req request.NginxAuthReq) (res response.NginxAuthRes, err error) {
|
|
var (
|
|
website model.Website
|
|
authContent []byte
|
|
nginxParams []response.NginxParam
|
|
)
|
|
website, err = websiteRepo.GetFirst(repo.WithByID(req.WebsiteID))
|
|
if err != nil {
|
|
return
|
|
}
|
|
absoluteAuthPath := GetSitePath(website, SiteRootAuthBasicPath)
|
|
fileOp := files.NewFileOp()
|
|
if !fileOp.Stat(absoluteAuthPath) {
|
|
return
|
|
}
|
|
nginxParams, err = getNginxParamsByKeys(constant.NginxScopeServer, []string{"auth_basic"}, &website)
|
|
if err != nil {
|
|
return
|
|
}
|
|
res.Enable = len(nginxParams[0].Params) > 0
|
|
authContent, err = fileOp.GetContent(absoluteAuthPath)
|
|
authArray := strings.Split(string(authContent), "\n")
|
|
for _, line := range authArray {
|
|
if line == "" {
|
|
continue
|
|
}
|
|
params := strings.Split(line, ":")
|
|
auth := dto.NginxAuth{
|
|
Username: params[0],
|
|
}
|
|
if len(params) == 3 {
|
|
auth.Remark = params[2]
|
|
}
|
|
res.Items = append(res.Items, auth)
|
|
}
|
|
return
|
|
}
|
|
|
|
func (w WebsiteService) UpdateAuthBasic(req request.NginxAuthUpdate) (err error) {
|
|
var (
|
|
website model.Website
|
|
params []dto.NginxParam
|
|
authContent []byte
|
|
authArray []string
|
|
)
|
|
website, err = websiteRepo.GetFirst(repo.WithByID(req.WebsiteID))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
authPath := fmt.Sprintf("/www/sites/%s/auth_basic/auth.pass", website.Alias)
|
|
absoluteAuthPath := GetSitePath(website, SiteRootAuthBasicPath)
|
|
fileOp := files.NewFileOp()
|
|
if !fileOp.Stat(path.Dir(absoluteAuthPath)) {
|
|
_ = fileOp.CreateDir(path.Dir(absoluteAuthPath), constant.DirPerm)
|
|
}
|
|
if !fileOp.Stat(absoluteAuthPath) {
|
|
_ = fileOp.CreateFile(absoluteAuthPath)
|
|
}
|
|
|
|
params = append(params, dto.NginxParam{Name: "auth_basic", Params: []string{`"Authentication"`}})
|
|
params = append(params, dto.NginxParam{Name: "auth_basic_user_file", Params: []string{authPath}})
|
|
authContent, err = fileOp.GetContent(absoluteAuthPath)
|
|
if err != nil {
|
|
return
|
|
}
|
|
if len(authContent) > 0 {
|
|
authArray = strings.Split(string(authContent), "\n")
|
|
}
|
|
switch req.Operate {
|
|
case "disable":
|
|
return deleteNginxConfig(constant.NginxScopeServer, params, &website)
|
|
case "enable":
|
|
return updateNginxConfig(constant.NginxScopeServer, params, &website)
|
|
case "create":
|
|
for _, line := range authArray {
|
|
authParams := strings.Split(line, ":")
|
|
username := authParams[0]
|
|
if username == req.Username {
|
|
err = buserr.New("ErrUsernameIsExist")
|
|
return
|
|
}
|
|
}
|
|
var passwdHash []byte
|
|
passwdHash, err = bcrypt.GenerateFromPassword([]byte(req.Password), bcrypt.DefaultCost)
|
|
if err != nil {
|
|
return
|
|
}
|
|
line := fmt.Sprintf("%s:%s\n", req.Username, passwdHash)
|
|
if req.Remark != "" {
|
|
line = fmt.Sprintf("%s:%s:%s\n", req.Username, passwdHash, req.Remark)
|
|
}
|
|
authArray = append(authArray, line)
|
|
case "edit":
|
|
userExist := false
|
|
for index, line := range authArray {
|
|
authParams := strings.Split(line, ":")
|
|
username := authParams[0]
|
|
if username == req.Username {
|
|
userExist = true
|
|
var passwdHash []byte
|
|
passwdHash, err = bcrypt.GenerateFromPassword([]byte(req.Password), bcrypt.DefaultCost)
|
|
if err != nil {
|
|
return
|
|
}
|
|
userPasswd := fmt.Sprintf("%s:%s\n", req.Username, passwdHash)
|
|
if req.Remark != "" {
|
|
userPasswd = fmt.Sprintf("%s:%s:%s\n", req.Username, passwdHash, req.Remark)
|
|
}
|
|
authArray[index] = userPasswd
|
|
}
|
|
}
|
|
if !userExist {
|
|
err = buserr.New("ErrUsernameIsNotExist")
|
|
return
|
|
}
|
|
case "delete":
|
|
deleteIndex := -1
|
|
for index, line := range authArray {
|
|
authParams := strings.Split(line, ":")
|
|
username := authParams[0]
|
|
if username == req.Username {
|
|
deleteIndex = index
|
|
}
|
|
}
|
|
if deleteIndex < 0 {
|
|
return
|
|
}
|
|
authArray = append(authArray[:deleteIndex], authArray[deleteIndex+1:]...)
|
|
}
|
|
|
|
var passFile *os.File
|
|
passFile, err = os.Create(absoluteAuthPath)
|
|
if err != nil {
|
|
return
|
|
}
|
|
defer passFile.Close()
|
|
writer := bufio.NewWriter(passFile)
|
|
for _, line := range authArray {
|
|
if line == "" {
|
|
continue
|
|
}
|
|
_, err = writer.WriteString(line + "\n")
|
|
if err != nil {
|
|
return
|
|
}
|
|
}
|
|
err = writer.Flush()
|
|
if err != nil {
|
|
return
|
|
}
|
|
authContent, err = fileOp.GetContent(absoluteAuthPath)
|
|
if err != nil {
|
|
return
|
|
}
|
|
if len(authContent) == 0 {
|
|
if err = deleteNginxConfig(constant.NginxScopeServer, params, &website); err != nil {
|
|
return
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
func (w WebsiteService) GetPathAuthBasics(req request.NginxAuthReq) (res []response.NginxPathAuthRes, err error) {
|
|
var (
|
|
website model.Website
|
|
authContent []byte
|
|
)
|
|
website, err = websiteRepo.GetFirst(repo.WithByID(req.WebsiteID))
|
|
if err != nil {
|
|
return
|
|
}
|
|
fileOp := files.NewFileOp()
|
|
absoluteAuthDir := GetSitePath(website, SitePathAuthBasicDir)
|
|
passDir := path.Join(absoluteAuthDir, "pass")
|
|
if !fileOp.Stat(absoluteAuthDir) || !fileOp.Stat(passDir) {
|
|
return
|
|
}
|
|
|
|
entries, err := os.ReadDir(absoluteAuthDir)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
for _, entry := range entries {
|
|
if !entry.IsDir() {
|
|
name := strings.TrimSuffix(entry.Name(), ".conf")
|
|
pathAuth := dto.NginxPathAuth{
|
|
Name: name,
|
|
}
|
|
configPath := path.Join(absoluteAuthDir, entry.Name())
|
|
content, err := fileOp.GetContent(configPath)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
config, err := parser.NewStringParser(string(content)).Parse()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
directives := config.Directives
|
|
location, _ := directives[0].(*components.Location)
|
|
pathAuth.Path = strings.TrimPrefix(location.Match, "^")
|
|
passPath := path.Join(passDir, fmt.Sprintf("%s.pass", name))
|
|
authContent, err = fileOp.GetContent(passPath)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
authArray := strings.Split(string(authContent), "\n")
|
|
for _, line := range authArray {
|
|
if line == "" {
|
|
continue
|
|
}
|
|
params := strings.Split(line, ":")
|
|
pathAuth.Username = params[0]
|
|
if len(params) == 3 {
|
|
pathAuth.Remark = params[2]
|
|
}
|
|
}
|
|
res = append(res, response.NginxPathAuthRes{
|
|
NginxPathAuth: pathAuth,
|
|
})
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
func (w WebsiteService) UpdatePathAuthBasic(req request.NginxPathAuthUpdate) error {
|
|
website, err := websiteRepo.GetFirst(repo.WithByID(req.WebsiteID))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
fileOp := files.NewFileOp()
|
|
authDir := GetSitePath(website, SitePathAuthBasicDir)
|
|
if !fileOp.Stat(authDir) {
|
|
_ = fileOp.CreateDir(authDir, constant.DirPerm)
|
|
}
|
|
passDir := path.Join(authDir, "pass")
|
|
if !fileOp.Stat(passDir) {
|
|
_ = fileOp.CreateDir(passDir, constant.DirPerm)
|
|
}
|
|
confPath := path.Join(authDir, fmt.Sprintf("%s.conf", req.Name))
|
|
passPath := path.Join(passDir, fmt.Sprintf("%s.pass", req.Name))
|
|
var config *components.Config
|
|
switch req.Operate {
|
|
case "delete":
|
|
_ = fileOp.DeleteFile(confPath)
|
|
_ = fileOp.DeleteFile(passPath)
|
|
return updateNginxConfig(constant.NginxScopeServer, nil, &website)
|
|
case "create":
|
|
config, err = parser.NewStringParser(string(nginx_conf.PathAuth)).Parse()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if fileOp.Stat(confPath) || fileOp.Stat(passPath) {
|
|
return buserr.New("ErrNameIsExist")
|
|
}
|
|
case "edit":
|
|
par, err := parser.NewParser(confPath)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
config, err = par.Parse()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
config.FilePath = confPath
|
|
directives := config.Directives
|
|
location, _ := directives[0].(*components.Location)
|
|
location.UpdateDirective("auth_basic_user_file", []string{fmt.Sprintf("/www/sites/%s/path_auth/pass/%s", website.Alias, fmt.Sprintf("%s.pass", req.Name))})
|
|
location.ChangePath("~*", fmt.Sprintf("^%s", req.Path))
|
|
var passwdHash []byte
|
|
passwdHash, err = bcrypt.GenerateFromPassword([]byte(req.Password), bcrypt.DefaultCost)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
line := fmt.Sprintf("%s:%s\n", req.Username, passwdHash)
|
|
if req.Remark != "" {
|
|
line = fmt.Sprintf("%s:%s:%s\n", req.Username, passwdHash, req.Remark)
|
|
}
|
|
_ = fileOp.SaveFile(passPath, line, constant.DirPerm)
|
|
if err = nginx.WriteConfig(config, nginx.IndentedStyle); err != nil {
|
|
return buserr.WithErr("ErrUpdateBuWebsite", err)
|
|
}
|
|
nginxInclude := fmt.Sprintf("/www/sites/%s/path_auth/*.conf", website.Alias)
|
|
if err = updateNginxConfig(constant.NginxScopeServer, []dto.NginxParam{{Name: "include", Params: []string{nginxInclude}}}, &website); err != nil {
|
|
return nil
|
|
}
|
|
return nil
|
|
}
|