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、时区等",