Skip to content

Commit

Permalink
Merge branch 'v2.1'
Browse files Browse the repository at this point in the history
  • Loading branch information
devhaozi committed Oct 23, 2023
2 parents 949248b + 4203f1b commit 5217e04
Show file tree
Hide file tree
Showing 13 changed files with 176 additions and 111 deletions.
7 changes: 7 additions & 0 deletions .github/workflows/goreleaser.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,13 @@ jobs:
uses: actions/setup-go@v4
with:
go-version: 'stable'
- name: Fetch Latest Frontend
run: |
apt install -y curl jq unzip zip
curl -s https://api.github.com/repos/haozi-team/panel-frontend/releases/latest | jq -r ".assets[] | select(.name | contains(\"dist\")) | .browser_download_url" | xargs curl -L -o frontend.zip
rm -rf public
unzip frontend.zip
mv dist public
- name: Run GoReleaser
uses: goreleaser/goreleaser-action@v5
with:
Expand Down
22 changes: 20 additions & 2 deletions .gitlab-ci.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
image: golang:bookworm
image: golang:alpine

# 在每个任务执行前运行
before_script:
Expand Down Expand Up @@ -52,11 +52,29 @@ build:
- $OUTPUT_NAME
expire_in: 3 days

fetch:
stage: build
before_script:
- sed -i 's/dl-cdn.alpinelinux.org/mirrors.tuna.tsinghua.edu.cn/g' /etc/apk/repositories
- apk add --no-cache curl jq unzip zip
script:
- curl -s "https://jihulab.com/api/v4/projects/haozi-team%2Fpanel-frontend/releases" | jq -r '.[0].assets.links[] | select(.name | contains("dist")) | .direct_asset_url' | xargs curl -L -o frontend.zip
- rm -rf public
- unzip frontend.zip
- mv dist public
artifacts:
name: "frontend"
paths:
- public
expire_in: 3 days

release:
stage: release
dependencies:
- build
image:
name: goreleaser/goreleaser
entrypoint: ['']
entrypoint: [ '' ]
only:
- tags
variables:
Expand Down
2 changes: 1 addition & 1 deletion app/http/controllers/cron_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ func (c *CronController) Add(ctx http.Context) http.Response {
backupName = ctx.Request().Input("website")
}
backupPath := ctx.Request().Input("backup_path")
if len(backupName) == 0 {
if len(backupPath) == 0 {
backupPath = c.setting.Get(models.SettingKeyBackupPath) + "/" + backupType
}
backupSave := ctx.Request().InputInt("save", 10)
Expand Down
22 changes: 15 additions & 7 deletions app/http/controllers/info_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,24 +123,32 @@ func (c *InfoController) InstalledDbAndPhp(ctx http.Context) http.Response {
}

type data struct {
Slug string `json:"slug"`
Name string `json:"name"`
Label string `json:"label"`
Value string `json:"value"`
}
var phpData []data
phpData = append(phpData, data{Slug: "0", Name: "不使用"})
var dbData []data
phpData = append(phpData, data{Value: "0", Label: "不使用"})
dbData = append(dbData, data{Value: "0", Label: "不使用"})
for _, p := range php {
match := regexp.MustCompile(`php(\d+)`).FindStringSubmatch(p.Slug)
if len(match) == 0 {
continue
}

phpData = append(phpData, data{Slug: strings.ReplaceAll(p.Slug, "php", ""), Name: c.plugin.GetBySlug(p.Slug).Name})
phpData = append(phpData, data{Value: strings.ReplaceAll(p.Slug, "php", ""), Label: c.plugin.GetBySlug(p.Slug).Name})
}

if mysqlInstalled {
dbData = append(dbData, data{Value: "mysql", Label: "MySQL"})
}
if postgresqlInstalled {
dbData = append(dbData, data{Value: "postgresql", Label: "PostgreSQL"})
}

return Success(ctx, http.Json{
"php": phpData,
"mysql": mysqlInstalled,
"postgresql": postgresqlInstalled,
"php": phpData,
"db": dbData,
})
}

Expand Down
2 changes: 1 addition & 1 deletion app/http/controllers/monitor_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ func NewMonitorController() *MonitorController {

// Switch 监控开关
func (r *MonitorController) Switch(ctx http.Context) http.Response {
value := ctx.Request().InputBool("switch")
value := ctx.Request().InputBool("monitor")
err := r.setting.Set(models.SettingKeyMonitor, cast.ToString(value))
if err != nil {
facades.Log().Error("[面板][MonitorController] 更新监控开关失败 ", err)
Expand Down
24 changes: 21 additions & 3 deletions app/http/controllers/safe_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,17 +132,35 @@ func (r *SafeController) AddFirewallRule(ctx http.Context) http.Response {
return Error(ctx, http.StatusBadRequest, "防火墙未启动")
}

port := ctx.Request().InputInt("port", 0)
protocol := ctx.Request().Input("protocol", "")
if port == 0 || protocol == "" {
port := ctx.Request().Input("port")
protocol := ctx.Request().Input("protocol")
if port == "" || protocol == "" || (protocol != "tcp" && protocol != "udp") {
return Error(ctx, http.StatusBadRequest, "参数错误")
}
// 端口有 2 种写法,一种是 80-443,一种是 80
if strings.Contains(port, "-") {
ports := strings.Split(port, "-")
startPort := cast.ToInt(ports[0])
endPort := cast.ToInt(ports[1])
if startPort < 1 || startPort > 65535 || endPort < 1 || endPort > 65535 || startPort > endPort {
return Error(ctx, http.StatusBadRequest, "参数错误")
}
} else {
port := cast.ToInt(port)
if port < 1 || port > 65535 {
return Error(ctx, http.StatusBadRequest, "参数错误")
}
}

if tools.IsRHEL() {
tools.Exec("firewall-cmd --remove-port=" + cast.ToString(port) + "/" + protocol + " --permanent 2>&1")
tools.Exec("firewall-cmd --add-port=" + cast.ToString(port) + "/" + protocol + " --permanent 2>&1")
tools.Exec("firewall-cmd --reload")
} else {
// ufw 需要替换 - 为 : 添加
if strings.Contains(port, "-") {
port = strings.ReplaceAll(port, "-", ":")
}
tools.Exec("ufw delete allow " + cast.ToString(port) + "/" + protocol)
tools.Exec("ufw allow " + cast.ToString(port) + "/" + protocol)
tools.Exec("ufw reload")
Expand Down
30 changes: 19 additions & 11 deletions app/http/controllers/setting_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,25 +28,33 @@ func (r *SettingController) List(ctx http.Context) http.Response {
return Error(ctx, http.StatusInternalServerError, "系统内部错误")
}

var result = make(map[string]string)
for _, setting := range settings {
if setting.Key == models.SettingKeyMysqlRootPassword {
continue
}

result[setting.Key] = setting.Value
}
type data struct {
Name string `json:"name"`
Username string `json:"username"`
Password string `json:"password"`
Email string `json:"email"`
Port string `json:"port"`
Entrance string `json:"entrance"`
WebsitePath string `json:"website_path"`
BackupPath string `json:"backup_path"`
}

var result data
result.Name = r.setting.Get(models.SettingKeyName)
result.Entrance = r.setting.Get(models.SettingKeyEntrance)
result.WebsitePath = r.setting.Get(models.SettingKeyWebsitePath)
result.BackupPath = r.setting.Get(models.SettingKeyBackupPath)

var user models.User
err = facades.Auth().User(ctx, &user)
if err != nil {
facades.Log().Error("[面板][SettingController] 获取用户失败 ", err)
return Error(ctx, http.StatusInternalServerError, "系统内部错误")
}
result["username"] = user.Username
result["email"] = user.Email
result.Username = user.Username
result.Email = user.Email

result["port"] = tools.Exec(`cat /www/panel/panel.conf | grep APP_PORT | awk -F '=' '{print $2}' | tr -d '\n'`)
result.Port = tools.Exec(`cat /www/panel/panel.conf | grep APP_PORT | awk -F '=' '{print $2}' | tr -d '\n'`)

return Success(ctx, result)
}
Expand Down
3 changes: 2 additions & 1 deletion app/http/controllers/ssh_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"github.com/goravel/framework/contracts/http"
"github.com/goravel/framework/facades"
"github.com/gorilla/websocket"
"github.com/spf13/cast"

"panel/app/models"
"panel/app/services"
Expand Down Expand Up @@ -40,7 +41,7 @@ func (r *SshController) GetInfo(ctx http.Context) http.Response {

return Success(ctx, http.Json{
"host": host,
"port": port,
"port": cast.ToInt(port),
"user": user,
"password": password,
})
Expand Down
14 changes: 10 additions & 4 deletions app/http/controllers/user_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ func (r *UserController) Login(ctx http.Context) http.Response {
return Error(ctx, http.StatusUnprocessableEntity, err.Error())
}
if errors != nil {
return Error(ctx, http.StatusUnprocessableEntity, errors.All())
return Error(ctx, http.StatusUnprocessableEntity, errors.One())
}

var user models.User
Expand Down Expand Up @@ -61,12 +61,18 @@ func (r *UserController) Login(ctx http.Context) http.Response {

// Info 用户信息
func (r *UserController) Info(ctx http.Context) http.Response {
user, ok := ctx.Value("user").(models.User)
if !ok {
return Error(ctx, http.StatusUnauthorized, "登录已过期")
var user models.User
err := facades.Auth().User(ctx, &user)
if err != nil {
facades.Log().With(map[string]any{
"error": err.Error(),
}).Error("[面板][UserController] 查询用户信息失败")
return Error(ctx, http.StatusInternalServerError, "系统内部错误")
}

return Success(ctx, http.Json{
"id": user.ID,
"role": []string{"admin"},
"username": user.Username,
"email": user.Email,
})
Expand Down
25 changes: 15 additions & 10 deletions app/http/controllers/website_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ func (c *WebsiteController) Add(ctx http.Context) http.Response {
}
validator, err := ctx.Request().Validate(map[string]string{
"name": "required|regex:^[a-zA-Z0-9_-]+(\\.[a-zA-Z0-9_-]+)*$|not_exists:websites,name",
"domain": "required",
"domains": "required|slice",
"ports": "required|slice",
"php": "required",
"db": "bool",
"db_type": "required_if:db,true",
Expand All @@ -70,7 +71,8 @@ func (c *WebsiteController) Add(ctx http.Context) http.Response {

var website services.PanelWebsite
website.Name = ctx.Request().Input("name")
website.Domain = ctx.Request().Input("domain")
website.Domains = ctx.Request().InputArray("domains")
website.Ports = ctx.Request().InputArray("ports")
website.Php = ctx.Request().InputInt("php")
website.Db = ctx.Request().InputBool("db")
website.DbType = ctx.Request().Input("db_type")
Expand Down Expand Up @@ -167,14 +169,13 @@ func (c *WebsiteController) SaveConfig(ctx http.Context) http.Response {
return check
}
validator, err := ctx.Request().Validate(map[string]string{
"id": "required",
"domains": "required",
"ports": "required",
"domains": "required|slice",
"ports": "required|slice",
"hsts": "bool",
"ssl": "bool",
"http_redirect": "bool",
"open_basedir": "bool",
"waf": "required",
"waf": "bool",
"waf_cache": "required",
"waf_mode": "required",
"waf_cc_deny": "required",
Expand Down Expand Up @@ -219,7 +220,7 @@ func (c *WebsiteController) SaveConfig(ctx http.Context) http.Response {

// 域名
domain := "server_name"
domains := strings.Split(ctx.Request().Input("domains"), "\n")
domains := ctx.Request().InputArray("domains")
if len(domains) == 0 {
return Error(ctx, http.StatusBadRequest, "域名不能为空")
}
Expand All @@ -238,7 +239,7 @@ func (c *WebsiteController) SaveConfig(ctx http.Context) http.Response {

// 端口
var port strings.Builder
ports := strings.Split(ctx.Request().Input("ports"), "\n")
ports := ctx.Request().InputArray("ports")
if len(ports) == 0 {
return Error(ctx, http.StatusBadRequest, "端口不能为空")
}
Expand Down Expand Up @@ -299,12 +300,16 @@ func (c *WebsiteController) SaveConfig(ctx http.Context) http.Response {
}

// WAF
waf := ctx.Request().Input("waf")
waf := ctx.Request().InputBool("waf")
wafStr := "off"
if waf {
wafStr = "on"
}
wafMode := ctx.Request().Input("waf_mode", "DYNAMIC")
wafCcDeny := ctx.Request().Input("waf_cc_deny", "rate=1000r/m duration=60m")
wafCache := ctx.Request().Input("waf_cache", "capacity=50")
wafConfig := `# waf标记位开始
waf ` + waf + `;
waf ` + wafStr + `;
waf_rule_path /www/server/openresty/ngx_waf/assets/rules/;
waf_mode ` + wafMode + `;
waf_cc_deny ` + wafCcDeny + `;
Expand Down
20 changes: 3 additions & 17 deletions app/http/middleware/jwt.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,14 @@ import (
"github.com/goravel/framework/auth"
"github.com/goravel/framework/contracts/http"
"github.com/goravel/framework/facades"

"panel/app/models"
)

// Jwt 确保通过 JWT 鉴权
func Jwt() http.Middleware {
return func(ctx http.Context) {
token := ctx.Request().Header("access_token", ctx.Request().Input("access_token", ctx.Request().Header("Sec-WebSocket-Protocol")))
token := ctx.Request().Header("Authorization", ctx.Request().Header("Sec-WebSocket-Protocol"))
if len(token) == 0 {
ctx.Request().AbortWithStatusJson(http.StatusUnauthorized, http.Json{
ctx.Request().AbortWithStatusJson(http.StatusOK, http.Json{
"code": 401,
"message": "未登录",
})
Expand All @@ -27,7 +25,7 @@ func Jwt() http.Middleware {
if errors.Is(err, auth.ErrorTokenExpired) {
token, err = facades.Auth().Refresh(ctx)
if err != nil {
// Refresh time exceeded
// 到达刷新时间上限
ctx.Request().AbortWithStatusJson(http.StatusOK, http.Json{
"code": 401,
"message": "登录已过期",
Expand All @@ -45,18 +43,6 @@ func Jwt() http.Middleware {
}
}

// 取出用户信息
var user models.User
if err := facades.Auth().User(ctx, &user); err != nil {
ctx.Request().AbortWithStatusJson(http.StatusForbidden, http.Json{
"code": 403,
"message": "用户不存在",
})
return
}

ctx.WithValue("user", user)

ctx.Response().Header("Authorization", token)
ctx.Request().Next()
}
Expand Down
Loading

0 comments on commit 5217e04

Please sign in to comment.