diff --git a/app/console/commands/monitoring.go b/app/console/commands/monitoring.go
index b788809f..37bfa496 100644
--- a/app/console/commands/monitoring.go
+++ b/app/console/commands/monitoring.go
@@ -45,8 +45,9 @@ func (receiver *Monitoring) Handle(console.Context) error {
}
// 将等待中的任务分发
- task := services.NewTaskImpl()
- _ = task.DispatchWaiting()
+ // TODO 有bug,需要设计一个锁机制防止重复分发
+ //task := services.NewTaskImpl()
+ //_ = task.DispatchWaiting()
setting := services.NewSettingImpl()
monitor := setting.Get(models.SettingKeyMonitor)
diff --git a/app/http/controllers/plugins/gitea_controller.go b/app/http/controllers/plugins/gitea_controller.go
new file mode 100644
index 00000000..b21e3aaf
--- /dev/null
+++ b/app/http/controllers/plugins/gitea_controller.go
@@ -0,0 +1,193 @@
+package plugins
+
+import (
+ "github.com/goravel/framework/contracts/http"
+
+ "github.com/TheTNB/panel/app/http/controllers"
+ requests "github.com/TheTNB/panel/app/http/requests/plugins/gitea"
+ "github.com/TheTNB/panel/pkg/tools"
+)
+
+type GiteaController struct {
+}
+
+func NewGiteaController() *GiteaController {
+ return &GiteaController{}
+}
+
+// Status
+//
+// @Summary 服务状态
+// @Description 获取 Gitea 服务状态
+// @Tags 插件-Gitea
+// @Produce json
+// @Security BearerToken
+// @Success 200 {object} controllers.SuccessResponse
+// @Router /plugins/gitea/status [get]
+func (r *GiteaController) Status(ctx http.Context) http.Response {
+ status, err := tools.ServiceStatus("gitea")
+ if err != nil {
+ return controllers.Error(ctx, http.StatusInternalServerError, "获取 Gitea 服务运行状态失败")
+ }
+
+ return controllers.Success(ctx, status)
+}
+
+// IsEnabled
+//
+// @Summary 是否启用服务
+// @Description 获取是否启用 Gitea 服务
+// @Tags 插件-Gitea
+// @Produce json
+// @Security BearerToken
+// @Success 200 {object} controllers.SuccessResponse
+// @Router /plugins/gitea/isEnabled [get]
+func (r *GiteaController) IsEnabled(ctx http.Context) http.Response {
+ enabled, err := tools.ServiceIsEnabled("gitea")
+ if err != nil {
+ return controllers.Error(ctx, http.StatusInternalServerError, "获取 Gitea 服务启用状态失败")
+ }
+
+ return controllers.Success(ctx, enabled)
+}
+
+// Enable
+//
+// @Summary 启用服务
+// @Description 启用 Gitea 服务
+// @Tags 插件-Gitea
+// @Produce json
+// @Security BearerToken
+// @Success 200 {object} controllers.SuccessResponse
+// @Router /plugins/gitea/enable [post]
+func (r *GiteaController) Enable(ctx http.Context) http.Response {
+ if err := tools.ServiceEnable("gitea"); err != nil {
+ return controllers.Error(ctx, http.StatusInternalServerError, "启用 Gitea 服务失败")
+ }
+
+ return controllers.Success(ctx, nil)
+}
+
+// Disable
+//
+// @Summary 禁用服务
+// @Description 禁用 Gitea 服务
+// @Tags 插件-Gitea
+// @Produce json
+// @Security BearerToken
+// @Success 200 {object} controllers.SuccessResponse
+// @Router /plugins/gitea/disable [post]
+func (r *GiteaController) Disable(ctx http.Context) http.Response {
+ if err := tools.ServiceDisable("gitea"); err != nil {
+ return controllers.Error(ctx, http.StatusInternalServerError, "禁用 Gitea 服务失败")
+ }
+
+ return controllers.Success(ctx, nil)
+}
+
+// Restart
+//
+// @Summary 重启服务
+// @Description 重启 Gitea 服务
+// @Tags 插件-Gitea
+// @Produce json
+// @Security BearerToken
+// @Success 200 {object} controllers.SuccessResponse
+// @Router /plugins/gitea/restart [post]
+func (r *GiteaController) Restart(ctx http.Context) http.Response {
+ if err := tools.ServiceRestart("gitea"); err != nil {
+ return controllers.Error(ctx, http.StatusInternalServerError, "重启 Gitea 服务失败")
+ }
+
+ return controllers.Success(ctx, nil)
+}
+
+// Start
+//
+// @Summary 启动服务
+// @Description 启动 Gitea 服务
+// @Tags 插件-Gitea
+// @Produce json
+// @Security BearerToken
+// @Success 200 {object} controllers.SuccessResponse
+// @Router /plugins/gitea/start [post]
+func (r *GiteaController) Start(ctx http.Context) http.Response {
+ if err := tools.ServiceStart("gitea"); err != nil {
+ return controllers.Error(ctx, http.StatusInternalServerError, "启动 Gitea 服务失败")
+ }
+
+ status, err := tools.ServiceStatus("gitea")
+ if err != nil {
+ return controllers.Error(ctx, http.StatusInternalServerError, "获取 Gitea 服务运行状态失败")
+ }
+
+ return controllers.Success(ctx, status)
+}
+
+// Stop
+//
+// @Summary 停止服务
+// @Description 停止 Gitea 服务
+// @Tags 插件-Gitea
+// @Produce json
+// @Security BearerToken
+// @Success 200 {object} controllers.SuccessResponse
+// @Router /plugins/gitea/stop [post]
+func (r *GiteaController) Stop(ctx http.Context) http.Response {
+ if err := tools.ServiceStop("gitea"); err != nil {
+ return controllers.Error(ctx, http.StatusInternalServerError, "停止 Gitea 服务失败")
+ }
+
+ status, err := tools.ServiceStatus("gitea")
+ if err != nil {
+ return controllers.Error(ctx, http.StatusInternalServerError, "获取 Gitea 服务运行状态失败")
+ }
+
+ return controllers.Success(ctx, !status)
+}
+
+// GetConfig
+//
+// @Summary 获取配置
+// @Description 获取 Gitea 配置
+// @Tags 插件-Gitea
+// @Produce json
+// @Security BearerToken
+// @Success 200 {object} controllers.SuccessResponse
+// @Router /plugins/gitea/config [get]
+func (r *GiteaController) GetConfig(ctx http.Context) http.Response {
+ config, err := tools.Read("/www/server/gitea/app.ini")
+ if err != nil {
+ return controllers.Error(ctx, http.StatusInternalServerError, err.Error())
+ }
+
+ return controllers.Success(ctx, config)
+}
+
+// UpdateConfig
+//
+// @Summary 更新配置
+// @Description 更新 Gitea 配置
+// @Tags 插件-Gitea
+// @Produce json
+// @Security BearerToken
+// @Param data body requests.UpdateConfig true "request"
+// @Success 200 {object} controllers.SuccessResponse
+// @Router /plugins/gitea/config [post]
+func (r *GiteaController) UpdateConfig(ctx http.Context) http.Response {
+ var updateRequest requests.UpdateConfig
+ sanitize := controllers.Sanitize(ctx, &updateRequest)
+ if sanitize != nil {
+ return sanitize
+ }
+
+ if err := tools.Write("/www/server/gitea/app.ini", updateRequest.Config, 0644); err != nil {
+ return controllers.Error(ctx, http.StatusInternalServerError, err.Error())
+ }
+
+ if err := tools.ServiceRestart("gitea"); err != nil {
+ return controllers.Error(ctx, http.StatusInternalServerError, err.Error())
+ }
+
+ return controllers.Success(ctx, nil)
+}
diff --git a/app/http/requests/plugins/gitea/update_config.go b/app/http/requests/plugins/gitea/update_config.go
new file mode 100644
index 00000000..f954af57
--- /dev/null
+++ b/app/http/requests/plugins/gitea/update_config.go
@@ -0,0 +1,32 @@
+package requests
+
+import (
+ "github.com/goravel/framework/contracts/http"
+ "github.com/goravel/framework/contracts/validation"
+)
+
+type UpdateConfig struct {
+ Config string `form:"config" json:"config"`
+}
+
+func (r *UpdateConfig) Authorize(ctx http.Context) error {
+ return nil
+}
+
+func (r *UpdateConfig) Rules(ctx http.Context) map[string]string {
+ return map[string]string{
+ "config": "required|string",
+ }
+}
+
+func (r *UpdateConfig) Messages(ctx http.Context) map[string]string {
+ return map[string]string{}
+}
+
+func (r *UpdateConfig) Attributes(ctx http.Context) map[string]string {
+ return map[string]string{}
+}
+
+func (r *UpdateConfig) PrepareForValidation(ctx http.Context, data validation.Data) error {
+ return nil
+}
diff --git a/internal/services/plugin.go b/internal/services/plugin.go
index 26ce5b81..16612bdf 100644
--- a/internal/services/plugin.go
+++ b/internal/services/plugin.go
@@ -53,6 +53,7 @@ func (r *PluginImpl) All() []types.Plugin {
types.PluginSupervisor,
types.PluginFail2ban,
types.PluginFrp,
+ types.PluginGitea,
types.PluginToolBox,
}
diff --git a/routes/plugin.go b/routes/plugin.go
index c19bf6de..40889c4c 100644
--- a/routes/plugin.go
+++ b/routes/plugin.go
@@ -365,6 +365,18 @@ func Plugin() {
route.Get("config", frpController.GetConfig)
route.Post("config", frpController.UpdateConfig)
})
+ r.Prefix("gitea").Group(func(route route.Router) {
+ giteaController := plugins.NewGiteaController()
+ route.Get("status", giteaController.Status)
+ route.Get("isEnabled", giteaController.IsEnabled)
+ route.Post("enable", giteaController.Enable)
+ route.Post("disable", giteaController.Disable)
+ route.Post("start", giteaController.Start)
+ route.Post("stop", giteaController.Stop)
+ route.Post("restart", giteaController.Restart)
+ route.Get("config", giteaController.GetConfig)
+ route.Post("config", giteaController.UpdateConfig)
+ })
r.Prefix("toolbox").Group(func(route route.Router) {
toolboxController := plugins.NewToolBoxController()
route.Get("dns", toolboxController.GetDNS)
diff --git a/scripts/frp/install.sh b/scripts/frp/install.sh
index 825fcc48..7a391336 100644
--- a/scripts/frp/install.sh
+++ b/scripts/frp/install.sh
@@ -96,4 +96,7 @@ systemctl start frps
systemctl start frpc
panel writePlugin frp ${frpVersion}
-echo -e "${HR}\nfrp 安装完成\n${HR}"
+echo -e ${HR}
+echo "frp 安装完成"
+echo -e ${HR}
+
diff --git a/scripts/frp/uninstall.sh b/scripts/frp/uninstall.sh
index ff494a0c..e2e3db94 100644
--- a/scripts/frp/uninstall.sh
+++ b/scripts/frp/uninstall.sh
@@ -19,7 +19,7 @@ along with this program. If not, see .
'
HR="+----------------------------------------------------"
-frpPath="/usr/local/frp"
+frpPath="/www/server/frp"
systemctl stop frps
systemctl stop frpc
@@ -34,4 +34,4 @@ systemctl daemon-reload
panel deletePlugin frp
echo -e $HR
echo "frp 卸载完成"
-echo -e $HR
\ No newline at end of file
+echo -e $HR
diff --git a/scripts/gitea/install.sh b/scripts/gitea/install.sh
new file mode 100644
index 00000000..12093c6f
--- /dev/null
+++ b/scripts/gitea/install.sh
@@ -0,0 +1,143 @@
+#!/bin/bash
+export PATH=/bin:/sbin:/usr/bin:/usr/sbin:/www/server/bin:/www/server/sbin:$PATH
+
+: '
+Copyright (C) 2022 - now HaoZi Technology Co., Ltd.
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU Affero General Public License as published
+by the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Affero General Public License for more details.
+
+You should have received a copy of the GNU Affero General Public License
+along with this program. If not, see .
+'
+
+HR="+----------------------------------------------------"
+ARCH=$(uname -m)
+OS=$(source /etc/os-release && { [[ "$ID" == "debian" ]] && echo "debian"; } || { [[ "$ID" == "centos" ]] || [[ "$ID" == "rhel" ]] || [[ "$ID" == "rocky" ]] || [[ "$ID" == "almalinux" ]] && echo "centos"; } || echo "unknown")
+downloadUrl="https://dl.cdn.haozi.net/panel/gitea"
+giteaPath="/www/server/gitea"
+giteaVersion="1.22.0"
+
+if [ ! -d "${giteaPath}" ]; then
+ mkdir -p ${giteaPath}
+fi
+
+# 架构判断
+if [ "${ARCH}" == "x86_64" ]; then
+ giteaFile="gitea-${giteaVersion}-linux-amd64.7z"
+elif [ "${ARCH}" == "aarch64" ]; then
+ giteaFile="gitea-${giteaVersion}-linux-arm64.7z"
+else
+ echo -e $HR
+ echo "错误:不支持的架构"
+ exit 1
+fi
+
+# 安装依赖
+if [ "${OS}" == "centos" ]; then
+ dnf makecache -y
+ dnf install git git-lfs -y
+elif [ "${OS}" == "debian" ]; then
+ apt-get update
+ apt-get install git git-lfs -y
+else
+ echo -e $HR
+ echo "错误:耗子 Linux 面板不支持该系统"
+ exit 1
+fi
+
+git lfs install
+git lfs version
+
+# 下载
+cd ${giteaPath}
+wget -T 120 -t 3 -O ${giteaPath}/${giteaFile} ${downloadUrl}/${giteaFile}
+wget -T 20 -t 3 -O ${giteaPath}/${giteaFile}.checksum.txt ${downloadUrl}/${giteaFile}.checksum.txt
+if ! sha256sum --status -c ${giteaPath}/${giteaFile}.checksum.txt; then
+ echo -e $HR
+ echo "错误:gitea checksum 校验失败,文件可能被篡改或不完整,已终止操作"
+ rm -rf ${giteaPath}
+ exit 1
+fi
+
+# 解压
+cd ${giteaPath}
+7z x ${giteaFile}
+rm -f ${giteaFile} ${giteaFile}.checksum.txt
+mv gitea-${giteaVersion}-linux-* gitea
+if [ ! -f "${giteaPath}/gitea" ]; then
+ echo -e $HR
+ echo "错误:gitea 解压失败"
+ rm -rf ${giteaPath}
+ exit 1
+fi
+
+# 初始化目录
+mkdir -p ${giteaPath}/{custom,data,log}
+chown -R www:www ${giteaPath}
+chmod -R 750 ${giteaPath}
+ln -sf ${giteaPath}/gitea /usr/local/bin/gitea
+
+# 配置systemd
+cat >/etc/systemd/system/gitea.service <.
+'
+
+HR="+----------------------------------------------------"
+giteaPath="/www/server/gitea"
+
+systemctl stop gitea
+systemctl disable gitea
+
+rm -f /usr/local/bin/gitea
+rm -rf ${giteaPath}
+rm -f /etc/systemd/system/gitea.service
+systemctl daemon-reload
+
+panel deletePlugin gitea
+echo -e $HR
+echo "gitea 卸载完成,数据库可能需自行删除"
+echo -e $HR
diff --git a/scripts/gitea/update.sh b/scripts/gitea/update.sh
new file mode 100644
index 00000000..6aa748d1
--- /dev/null
+++ b/scripts/gitea/update.sh
@@ -0,0 +1,72 @@
+#!/bin/bash
+export PATH=/bin:/sbin:/usr/bin:/usr/sbin:/www/server/bin:/www/server/sbin:$PATH
+
+: '
+Copyright (C) 2022 - now HaoZi Technology Co., Ltd.
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU Affero General Public License as published
+by the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Affero General Public License for more details.
+
+You should have received a copy of the GNU Affero General Public License
+along with this program. If not, see .
+'
+
+HR="+----------------------------------------------------"
+ARCH=$(uname -m)
+downloadUrl="https://dl.cdn.haozi.net/panel/gitea"
+giteaPath="/www/server/gitea"
+giteaVersion="1.22.0"
+
+# 架构判断
+if [ "${ARCH}" == "x86_64" ]; then
+ giteaFile="gitea-${giteaVersion}-linux-amd64.7z"
+elif [ "${ARCH}" == "aarch64" ]; then
+ giteaFile="gitea-${giteaVersion}-linux-arm64.7z"
+else
+ echo -e $HR
+ echo "错误:不支持的架构"
+ exit 1
+fi
+
+# 下载
+cd ${giteaPath}
+wget -T 120 -t 3 -O ${giteaPath}/${giteaFile} ${downloadUrl}/${giteaFile}
+wget -T 20 -t 3 -O ${giteaPath}/${giteaFile}.checksum.txt ${downloadUrl}/${giteaFile}.checksum.txt
+if ! sha256sum --status -c ${giteaPath}/${giteaFile}.checksum.txt; then
+ echo -e $HR
+ echo "错误:gitea checksum 校验失败,文件可能被篡改或不完整,已终止操作"
+ rm -rf ${giteaPath}
+ exit 1
+fi
+
+# 解压
+cd ${giteaPath}
+7z x ${giteaFile}
+rm -f ${giteaFile} ${giteaFile}.checksum.txt
+
+# 替换文件
+systemctl stop gitea
+rm -f gitea
+mv gitea-${giteaVersion}-linux-* gitea
+if [ ! -f "${giteaPath}/gitea" ]; then
+ echo -e $HR
+ echo "错误:gitea 解压失败"
+ rm -rf ${giteaPath}
+ exit 1
+fi
+
+chown -R www:www ${giteaPath}
+chmod -R 750 ${giteaPath}
+systemctl start gitea
+
+panel writePlugin gitea ${giteaVersion}
+echo -e $HR
+echo "gitea 升级完成"
+echo -e $HR
diff --git a/scripts/mysql/install.sh b/scripts/mysql/install.sh
index 0456b6bb..c042caaa 100644
--- a/scripts/mysql/install.sh
+++ b/scripts/mysql/install.sh
@@ -94,8 +94,8 @@ sed -i 's/ADD_SUBDIRECTORY(mysql-test)//g' CMakeLists.txt
mkdir build
cd build
-# 5.7 需要 boost
-if [[ "${1}" == "57" ]]; then
+# 5.7 和 8.0 需要 boost
+if [[ "${1}" == "57" ]] || [[ "${1}" == "80" ]]; then
MAYBE_WITH_BOOST="-DWITH_BOOST=../boost"
fi
diff --git a/types/plugin_list.go b/types/plugin_list.go
index 37bf7806..9a3b0e5b 100644
--- a/types/plugin_list.go
+++ b/types/plugin_list.go
@@ -228,6 +228,18 @@ var PluginFrp = Plugin{
Update: `bash /www/panel/scripts/frp/install.sh`,
}
+var PluginGitea = Plugin{
+ Name: "Gitea",
+ Description: "Gitea 是一款极易搭建的自助 Git 服务,它包括 Git 托管、代码审查、团队协作、软件包注册和 CI/CD。",
+ Slug: "gitea",
+ Version: "1.22.0",
+ Requires: []string{},
+ Excludes: []string{},
+ Install: `bash /www/panel/scripts/gitea/install.sh`,
+ Uninstall: `bash /www/panel/scripts/gitea/uninstall.sh`,
+ Update: `bash /www/panel/scripts/gitea/install.sh`,
+}
+
var PluginToolBox = Plugin{
Name: "系统工具箱",
Description: "可视化调整一些常用的配置项,如 DNS、SWAP、时区等",