diff --git a/app/http/controllers/plugins/mysql57_controller.go b/app/http/controllers/plugins/mysql57_controller.go deleted file mode 100644 index f08ff42a..00000000 --- a/app/http/controllers/plugins/mysql57_controller.go +++ /dev/null @@ -1,667 +0,0 @@ -package plugins - -import ( - "database/sql" - "fmt" - "regexp" - - "github.com/goravel/framework/contracts/http" - "github.com/spf13/cast" - - "panel/app/http/controllers" - "panel/app/models" - "panel/internal" - "panel/internal/services" - "panel/pkg/tools" -) - -type Mysql57Controller struct { - setting internal.Setting - backup internal.Backup -} - -func NewMysql57Controller() *Mysql57Controller { - return &Mysql57Controller{ - setting: services.NewSettingImpl(), - backup: services.NewBackupImpl(), - } -} - -// Status 获取运行状态 -func (r *Mysql57Controller) Status(ctx http.Context) http.Response { - status, err := tools.ServiceStatus("mysqld") - if err != nil { - return controllers.Error(ctx, http.StatusInternalServerError, "获取MySQL状态失败") - } - - return controllers.Success(ctx, status) -} - -// Reload 重载配置 -func (r *Mysql57Controller) Reload(ctx http.Context) http.Response { - if err := tools.ServiceReload("mysqld"); err != nil { - return controllers.Error(ctx, http.StatusInternalServerError, "重载MySQL失败") - } - - return controllers.Success(ctx, nil) -} - -// Restart 重启服务 -func (r *Mysql57Controller) Restart(ctx http.Context) http.Response { - if err := tools.ServiceRestart("mysqld"); err != nil { - return controllers.Error(ctx, http.StatusInternalServerError, "重启MySQL服务失败") - } - - return controllers.Success(ctx, nil) -} - -// Start 启动服务 -func (r *Mysql57Controller) Start(ctx http.Context) http.Response { - if err := tools.ServiceStart("mysqld"); err != nil { - return controllers.Error(ctx, http.StatusInternalServerError, "启动MySQL服务失败") - } - - return controllers.Success(ctx, nil) -} - -// Stop 停止服务 -func (r *Mysql57Controller) Stop(ctx http.Context) http.Response { - if err := tools.ServiceStop("mysqld"); err != nil { - return controllers.Error(ctx, http.StatusInternalServerError, "停止MySQL服务失败") - } - - return controllers.Success(ctx, nil) -} - -// GetConfig 获取配置 -func (r *Mysql57Controller) GetConfig(ctx http.Context) http.Response { - config, err := tools.Read("/www/server/mysql/conf/my.cnf") - if err != nil { - return controllers.Error(ctx, http.StatusInternalServerError, "获取MySQL配置失败") - } - - return controllers.Success(ctx, config) -} - -// SaveConfig 保存配置 -func (r *Mysql57Controller) SaveConfig(ctx http.Context) http.Response { - config := ctx.Request().Input("config") - if len(config) == 0 { - return controllers.Error(ctx, http.StatusUnprocessableEntity, "配置不能为空") - } - - if err := tools.Write("/www/server/mysql/conf/my.cnf", config, 0644); err != nil { - return controllers.Error(ctx, http.StatusInternalServerError, "写入MySQL配置失败") - } - - return r.Restart(ctx) -} - -// Load 获取负载 -func (r *Mysql57Controller) Load(ctx http.Context) http.Response { - rootPassword := r.setting.Get(models.SettingKeyMysqlRootPassword) - if len(rootPassword) == 0 { - return controllers.Error(ctx, http.StatusUnprocessableEntity, "MySQL root密码为空") - } - - status, err := tools.ServiceStatus("mysqld") - if err != nil { - return controllers.Error(ctx, http.StatusInternalServerError, "获取MySQL状态失败") - } - if !status { - return controllers.Error(ctx, http.StatusInternalServerError, "MySQL 未运行") - } - - raw, err := tools.Exec("/www/server/mysql/bin/mysqladmin -uroot -p" + rootPassword + " extended-status 2>&1") - if err != nil { - return controllers.Error(ctx, http.StatusInternalServerError, "获取MySQL负载失败") - } - - var data []map[string]string - expressions := []struct { - regex string - name string - }{ - {`Uptime\s+\|\s+(\d+)\s+\|`, "运行时间"}, - {`Queries\s+\|\s+(\d+)\s+\|`, "总查询次数"}, - {`Connections\s+\|\s+(\d+)\s+\|`, "总连接次数"}, - {`Com_commit\s+\|\s+(\d+)\s+\|`, "每秒事务"}, - {`Com_rollback\s+\|\s+(\d+)\s+\|`, "每秒回滚"}, - {`Bytes_sent\s+\|\s+(\d+)\s+\|`, "发送"}, - {`Bytes_received\s+\|\s+(\d+)\s+\|`, "接收"}, - {`Threads_connected\s+\|\s+(\d+)\s+\|`, "活动连接数"}, - {`Max_used_connections\s+\|\s+(\d+)\s+\|`, "峰值连接数"}, - {`Key_read_requests\s+\|\s+(\d+)\s+\|`, "索引命中率"}, - {`Innodb_buffer_pool_reads\s+\|\s+(\d+)\s+\|`, "Innodb索引命中率"}, - {`Created_tmp_disk_tables\s+\|\s+(\d+)\s+\|`, "创建临时表到磁盘"}, - {`Open_tables\s+\|\s+(\d+)\s+\|`, "已打开的表"}, - {`Select_full_join\s+\|\s+(\d+)\s+\|`, "没有使用索引的量"}, - {`Select_full_range_join\s+\|\s+(\d+)\s+\|`, "没有索引的JOIN量"}, - {`Select_range_check\s+\|\s+(\d+)\s+\|`, "没有索引的子查询量"}, - {`Sort_merge_passes\s+\|\s+(\d+)\s+\|`, "排序后的合并次数"}, - {`Table_locks_waited\s+\|\s+(\d+)\s+\|`, "锁表次数"}, - } - - for _, expression := range expressions { - re := regexp.MustCompile(expression.regex) - matches := re.FindStringSubmatch(raw) - if len(matches) > 1 { - d := map[string]string{"name": expression.name, "value": matches[1]} - if expression.name == "发送" || expression.name == "接收" { - d["value"] = tools.FormatBytes(cast.ToFloat64(matches[1])) - } - - data = append(data, d) - } - } - - // 索引命中率 - readRequests := cast.ToFloat64(data[9]["value"]) - reads := cast.ToFloat64(data[10]["value"]) - data[9]["value"] = fmt.Sprintf("%.2f%%", readRequests/(reads+readRequests)*100) - // Innodb 索引命中率 - bufferPoolReads := cast.ToFloat64(data[11]["value"]) - bufferPoolReadRequests := cast.ToFloat64(data[12]["value"]) - data[10]["value"] = fmt.Sprintf("%.2f%%", bufferPoolReadRequests/(bufferPoolReads+bufferPoolReadRequests)*100) - - return controllers.Success(ctx, data) -} - -// ErrorLog 获取错误日志 -func (r *Mysql57Controller) ErrorLog(ctx http.Context) http.Response { - log, err := tools.Exec("tail -n 100 /www/server/mysql/mysql-error.log") - if err != nil { - return controllers.Error(ctx, http.StatusInternalServerError, log) - } - - return controllers.Success(ctx, log) -} - -// ClearErrorLog 清空错误日志 -func (r *Mysql57Controller) ClearErrorLog(ctx http.Context) http.Response { - if out, err := tools.Exec("echo '' > /www/server/mysql/mysql-error.log"); err != nil { - return controllers.Error(ctx, http.StatusInternalServerError, out) - } - - return controllers.Success(ctx, nil) -} - -// SlowLog 获取慢查询日志 -func (r *Mysql57Controller) SlowLog(ctx http.Context) http.Response { - log, err := tools.Exec("tail -n 100 /www/server/mysql/mysql-slow.log") - if err != nil { - return controllers.Error(ctx, http.StatusInternalServerError, log) - } - - return controllers.Success(ctx, log) -} - -// ClearSlowLog 清空慢查询日志 -func (r *Mysql57Controller) ClearSlowLog(ctx http.Context) http.Response { - if out, err := tools.Exec("echo '' > /www/server/mysql/mysql-slow.log"); err != nil { - return controllers.Error(ctx, http.StatusInternalServerError, out) - } - return controllers.Success(ctx, nil) -} - -// GetRootPassword 获取root密码 -func (r *Mysql57Controller) GetRootPassword(ctx http.Context) http.Response { - rootPassword := r.setting.Get(models.SettingKeyMysqlRootPassword) - if len(rootPassword) == 0 { - return controllers.Error(ctx, http.StatusUnprocessableEntity, "MySQL root密码为空") - } - - return controllers.Success(ctx, rootPassword) -} - -// SetRootPassword 设置root密码 -func (r *Mysql57Controller) SetRootPassword(ctx http.Context) http.Response { - status, err := tools.ServiceStatus("mysqld") - if err != nil { - return controllers.Error(ctx, http.StatusInternalServerError, "获取MySQL状态失败") - } - if !status { - return controllers.Error(ctx, http.StatusInternalServerError, "MySQL 未运行") - } - - rootPassword := ctx.Request().Input("password") - if len(rootPassword) == 0 { - return controllers.Error(ctx, http.StatusUnprocessableEntity, "MySQL root密码不能为空") - } - - oldRootPassword := r.setting.Get(models.SettingKeyMysqlRootPassword) - if oldRootPassword != rootPassword { - if _, err := tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + oldRootPassword + " -e \"ALTER USER 'root'@'localhost' IDENTIFIED BY '" + rootPassword + "';\""); err != nil { - return controllers.Error(ctx, http.StatusInternalServerError, "设置root密码失败") - } - if _, err := tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + oldRootPassword + " -e \"FLUSH PRIVILEGES;\""); err != nil { - return controllers.Error(ctx, http.StatusInternalServerError, "设置root密码失败") - } - err := r.setting.Set(models.SettingKeyMysqlRootPassword, rootPassword) - if err != nil { - if _, err := tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + rootPassword + " -e \"ALTER USER 'root'@'localhost' IDENTIFIED BY '" + oldRootPassword + "';\""); err != nil { - return nil - } - if _, err := tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + rootPassword + " -e \"FLUSH PRIVILEGES;\""); err != nil { - return nil - } - return controllers.Error(ctx, http.StatusInternalServerError, "设置root密码失败") - } - } - - return controllers.Success(ctx, nil) -} - -// DatabaseList 获取数据库列表 -func (r *Mysql57Controller) DatabaseList(ctx http.Context) http.Response { - rootPassword := r.setting.Get(models.SettingKeyMysqlRootPassword) - type database struct { - Name string `json:"name"` - } - - db, err := sql.Open("mysql", "root:"+rootPassword+"@unix(/tmp/mysql.sock)/") - if err != nil { - return controllers.Error(ctx, http.StatusInternalServerError, err.Error()) - } - defer db.Close() - - rows, err := db.Query("SHOW DATABASES") - if err != nil { - return controllers.Error(ctx, http.StatusInternalServerError, err.Error()) - } - defer rows.Close() - - var databases []database - for rows.Next() { - var d database - err := rows.Scan(&d.Name) - if err != nil { - continue - } - - databases = append(databases, d) - } - - if err := rows.Err(); err != nil { - return controllers.Error(ctx, http.StatusInternalServerError, "获取数据库列表失败") - } - - page := ctx.Request().QueryInt("page", 1) - limit := ctx.Request().QueryInt("limit", 10) - startIndex := (page - 1) * limit - endIndex := page * limit - if startIndex > len(databases) { - return controllers.Success(ctx, http.Json{ - "total": 0, - "items": []database{}, - }) - } - if endIndex > len(databases) { - endIndex = len(databases) - } - pagedDatabases := databases[startIndex:endIndex] - - return controllers.Success(ctx, http.Json{ - "total": len(databases), - "items": pagedDatabases, - }) -} - -// AddDatabase 添加数据库 -func (r *Mysql57Controller) AddDatabase(ctx http.Context) http.Response { - validator, err := ctx.Request().Validate(map[string]string{ - "database": "required|min_len:1|max_len:255|regex:^[a-zA-Z][a-zA-Z0-9_]+$", - "user": "required|min_len:1|max_len:255|regex:^[a-zA-Z][a-zA-Z0-9_]+$", - "password": "required|min_len:8|max_len:255", - }) - if err != nil { - return controllers.Error(ctx, http.StatusUnprocessableEntity, err.Error()) - } - if validator.Fails() { - return controllers.Error(ctx, http.StatusUnprocessableEntity, validator.Errors().One()) - } - - rootPassword := r.setting.Get(models.SettingKeyMysqlRootPassword) - database := ctx.Request().Input("database") - user := ctx.Request().Input("user") - password := ctx.Request().Input("password") - - if out, err := tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + rootPassword + " -e \"CREATE DATABASE IF NOT EXISTS " + database + " DEFAULT CHARSET utf8mb4 COLLATE utf8mb4_general_ci;\""); err != nil { - return controllers.Error(ctx, http.StatusInternalServerError, out) - } - if out, err := tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + rootPassword + " -e \"CREATE USER '" + user + "'@'localhost' IDENTIFIED BY '" + password + "';\""); err != nil { - return controllers.Error(ctx, http.StatusInternalServerError, out) - } - if out, err := tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + rootPassword + " -e \"GRANT ALL PRIVILEGES ON " + database + ".* TO '" + user + "'@'localhost';\""); err != nil { - return controllers.Error(ctx, http.StatusInternalServerError, out) - } - if out, err := tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + rootPassword + " -e \"FLUSH PRIVILEGES;\""); err != nil { - return controllers.Error(ctx, http.StatusInternalServerError, out) - } - - return controllers.Success(ctx, nil) -} - -// DeleteDatabase 删除数据库 -func (r *Mysql57Controller) DeleteDatabase(ctx http.Context) http.Response { - validator, err := ctx.Request().Validate(map[string]string{ - "database": "required|min_len:1|max_len:255|regex:^[a-zA-Z][a-zA-Z0-9_]+$|not_in:information_schema,mysql,performance_schema,sys", - }) - if err != nil { - return controllers.Error(ctx, http.StatusUnprocessableEntity, err.Error()) - } - if validator.Fails() { - return controllers.Error(ctx, http.StatusUnprocessableEntity, validator.Errors().One()) - } - - rootPassword := r.setting.Get(models.SettingKeyMysqlRootPassword) - database := ctx.Request().Input("database") - if out, err := tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + rootPassword + " -e \"DROP DATABASE IF EXISTS " + database + ";\""); err != nil { - return controllers.Error(ctx, http.StatusInternalServerError, out) - } - - return controllers.Success(ctx, nil) -} - -// BackupList 获取备份列表 -func (r *Mysql57Controller) BackupList(ctx http.Context) http.Response { - backupList, err := r.backup.MysqlList() - if err != nil { - return controllers.Error(ctx, http.StatusInternalServerError, err.Error()) - } - - page := ctx.Request().QueryInt("page", 1) - limit := ctx.Request().QueryInt("limit", 10) - startIndex := (page - 1) * limit - endIndex := page * limit - if startIndex > len(backupList) { - return controllers.Success(ctx, http.Json{ - "total": 0, - "items": []internal.BackupFile{}, - }) - } - if endIndex > len(backupList) { - endIndex = len(backupList) - } - pagedBackupList := backupList[startIndex:endIndex] - if pagedBackupList == nil { - pagedBackupList = []internal.BackupFile{} - } - - return controllers.Success(ctx, http.Json{ - "total": len(backupList), - "items": pagedBackupList, - }) -} - -// UploadBackup 上传备份 -func (r *Mysql57Controller) UploadBackup(ctx http.Context) http.Response { - file, err := ctx.Request().File("file") - if err != nil { - return controllers.Error(ctx, http.StatusUnprocessableEntity, "上传文件失败") - } - - backupPath := r.setting.Get(models.SettingKeyBackupPath) + "/mysql" - if !tools.Exists(backupPath) { - if err = tools.Mkdir(backupPath, 0644); err != nil { - return nil - } - } - - name := file.GetClientOriginalName() - _, err = file.StoreAs(backupPath, name) - if err != nil { - return controllers.Error(ctx, http.StatusUnprocessableEntity, "上传文件失败") - } - - return controllers.Success(ctx, nil) -} - -// CreateBackup 创建备份 -func (r *Mysql57Controller) CreateBackup(ctx http.Context) http.Response { - validator, err := ctx.Request().Validate(map[string]string{ - "database": "required|min_len:1|max_len:255|regex:^[a-zA-Z][a-zA-Z0-9_]+$|not_in:information_schema,mysql,performance_schema,sys", - }) - if err != nil { - return controllers.Error(ctx, http.StatusUnprocessableEntity, err.Error()) - } - if validator.Fails() { - return controllers.Error(ctx, http.StatusUnprocessableEntity, validator.Errors().One()) - } - - database := ctx.Request().Input("database") - err = r.backup.MysqlBackup(database) - if err != nil { - return controllers.Error(ctx, http.StatusInternalServerError, err.Error()) - } - - return controllers.Success(ctx, nil) -} - -// DeleteBackup 删除备份 -func (r *Mysql57Controller) DeleteBackup(ctx http.Context) http.Response { - validator, err := ctx.Request().Validate(map[string]string{ - "name": "required|min_len:1|max_len:255", - }) - if err != nil { - return controllers.Error(ctx, http.StatusUnprocessableEntity, err.Error()) - } - if validator.Fails() { - return controllers.Error(ctx, http.StatusUnprocessableEntity, validator.Errors().One()) - } - - backupPath := r.setting.Get(models.SettingKeyBackupPath) + "/mysql" - fileName := ctx.Request().Input("name") - if err := tools.Remove(backupPath + "/" + fileName); err != nil { - return controllers.Error(ctx, http.StatusInternalServerError, err.Error()) - } - - return controllers.Success(ctx, nil) -} - -// RestoreBackup 还原备份 -func (r *Mysql57Controller) RestoreBackup(ctx http.Context) http.Response { - validator, err := ctx.Request().Validate(map[string]string{ - "backup": "required|min_len:1|max_len:255", - "database": "required|min_len:1|max_len:255|regex:^[a-zA-Z][a-zA-Z0-9_]+$|not_in:information_schema,mysql,performance_schema,sys", - }) - if err != nil { - return controllers.Error(ctx, http.StatusUnprocessableEntity, err.Error()) - } - if validator.Fails() { - return controllers.Error(ctx, http.StatusUnprocessableEntity, validator.Errors().One()) - } - - err = r.backup.MysqlRestore(ctx.Request().Input("database"), ctx.Request().Input("backup")) - if err != nil { - return controllers.Error(ctx, http.StatusInternalServerError, err.Error()) - } - - return controllers.Success(ctx, nil) -} - -// UserList 用户列表 -func (r *Mysql57Controller) UserList(ctx http.Context) http.Response { - type user struct { - User string `json:"user"` - Host string `json:"host"` - Grants []string `json:"grants"` - } - - rootPassword := r.setting.Get(models.SettingKeyMysqlRootPassword) - db, err := sql.Open("mysql", "root:"+rootPassword+"@unix(/tmp/mysql.sock)/") - if err != nil { - return controllers.Error(ctx, http.StatusInternalServerError, err.Error()) - } - defer db.Close() - - rows, err := db.Query("SELECT user, host FROM mysql.user") - if err != nil { - return controllers.Error(ctx, http.StatusInternalServerError, err.Error()) - } - defer rows.Close() - - var userGrants []user - - for rows.Next() { - var u user - err := rows.Scan(&u.User, &u.Host) - if err != nil { - continue - } - - // 查询用户权限 - grantsRows, err := db.Query(fmt.Sprintf("SHOW GRANTS FOR '%s'@'%s'", u.User, u.Host)) - if err != nil { - continue - } - defer grantsRows.Close() - - for grantsRows.Next() { - var grant string - err := grantsRows.Scan(&grant) - if err != nil { - continue - } - - u.Grants = append(u.Grants, grant) - } - - if err := grantsRows.Err(); err != nil { - continue - } - - userGrants = append(userGrants, u) - } - - if err := rows.Err(); err != nil { - return controllers.Error(ctx, http.StatusInternalServerError, "获取用户列表失败") - } - - page := ctx.Request().QueryInt("page", 1) - limit := ctx.Request().QueryInt("limit", 10) - startIndex := (page - 1) * limit - endIndex := page * limit - if startIndex > len(userGrants) { - return controllers.Success(ctx, http.Json{ - "total": 0, - "items": []user{}, - }) - } - if endIndex > len(userGrants) { - endIndex = len(userGrants) - } - pagedUserGrants := userGrants[startIndex:endIndex] - - return controllers.Success(ctx, http.Json{ - "total": len(userGrants), - "items": pagedUserGrants, - }) -} - -// AddUser 添加用户 -func (r *Mysql57Controller) AddUser(ctx http.Context) http.Response { - validator, err := ctx.Request().Validate(map[string]string{ - "database": "required|min_len:1|max_len:255|regex:^[a-zA-Z][a-zA-Z0-9_]+$", - "user": "required|min_len:1|max_len:255|regex:^[a-zA-Z][a-zA-Z0-9_]+$", - "password": "required|min_len:8|max_len:255", - }) - if err != nil { - return controllers.Error(ctx, http.StatusUnprocessableEntity, err.Error()) - } - if validator.Fails() { - return controllers.Error(ctx, http.StatusUnprocessableEntity, validator.Errors().One()) - } - - rootPassword := r.setting.Get(models.SettingKeyMysqlRootPassword) - user := ctx.Request().Input("user") - password := ctx.Request().Input("password") - database := ctx.Request().Input("database") - if out, err := tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + rootPassword + " -e \"CREATE USER '" + user + "'@'localhost' IDENTIFIED BY '" + password + ";'\""); err != nil { - return controllers.Error(ctx, http.StatusInternalServerError, out) - } - if out, err := tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + rootPassword + " -e \"GRANT ALL PRIVILEGES ON " + database + ".* TO '" + user + "'@'localhost';\""); err != nil { - return controllers.Error(ctx, http.StatusInternalServerError, out) - } - if out, err := tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + rootPassword + " -e \"FLUSH PRIVILEGES;\""); err != nil { - return controllers.Error(ctx, http.StatusInternalServerError, out) - } - - return controllers.Success(ctx, nil) -} - -// DeleteUser 删除用户 -func (r *Mysql57Controller) DeleteUser(ctx http.Context) http.Response { - validator, err := ctx.Request().Validate(map[string]string{ - "user": "required|min_len:1|max_len:255|regex:^[a-zA-Z][a-zA-Z0-9_]+$", - }) - if err != nil { - return controllers.Error(ctx, http.StatusUnprocessableEntity, err.Error()) - } - if validator.Fails() { - return controllers.Error(ctx, http.StatusUnprocessableEntity, validator.Errors().One()) - } - - rootPassword := r.setting.Get(models.SettingKeyMysqlRootPassword) - user := ctx.Request().Input("user") - if out, err := tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + rootPassword + " -e \"DROP USER '" + user + "'@'localhost';\""); err != nil { - return controllers.Error(ctx, http.StatusInternalServerError, out) - } - - return controllers.Success(ctx, nil) -} - -// SetUserPassword 设置用户密码 -func (r *Mysql57Controller) SetUserPassword(ctx http.Context) http.Response { - validator, err := ctx.Request().Validate(map[string]string{ - "user": "required|min_len:1|max_len:255|regex:^[a-zA-Z][a-zA-Z0-9_]+$", - "password": "required|min_len:8|max_len:255", - }) - if err != nil { - return controllers.Error(ctx, http.StatusUnprocessableEntity, err.Error()) - } - if validator.Fails() { - return controllers.Error(ctx, http.StatusUnprocessableEntity, validator.Errors().One()) - } - - rootPassword := r.setting.Get(models.SettingKeyMysqlRootPassword) - user := ctx.Request().Input("user") - password := ctx.Request().Input("password") - if out, err := tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + rootPassword + " -e \"ALTER USER '" + user + "'@'localhost' IDENTIFIED BY '" + password + "';\""); err != nil { - return controllers.Error(ctx, http.StatusInternalServerError, out) - } - if out, err := tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + rootPassword + " -e \"FLUSH PRIVILEGES;\""); err != nil { - return controllers.Error(ctx, http.StatusInternalServerError, out) - } - - return controllers.Success(ctx, nil) -} - -// SetUserPrivileges 设置用户权限 -func (r *Mysql57Controller) SetUserPrivileges(ctx http.Context) http.Response { - validator, err := ctx.Request().Validate(map[string]string{ - "user": "required|min_len:1|max_len:255|regex:^[a-zA-Z][a-zA-Z0-9_]+$", - "database": "required|min_len:1|max_len:255", - }) - if err != nil { - return controllers.Error(ctx, http.StatusUnprocessableEntity, err.Error()) - } - if validator.Fails() { - return controllers.Error(ctx, http.StatusUnprocessableEntity, validator.Errors().One()) - } - - rootPassword := r.setting.Get(models.SettingKeyMysqlRootPassword) - user := ctx.Request().Input("user") - database := ctx.Request().Input("database") - if out, err := tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + rootPassword + " -e \"REVOKE ALL PRIVILEGES ON *.* FROM '" + user + "'@'localhost';\""); err != nil { - return controllers.Error(ctx, http.StatusInternalServerError, out) - } - if out, err := tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + rootPassword + " -e \"GRANT ALL PRIVILEGES ON " + database + ".* TO '" + user + "'@'localhost';\""); err != nil { - return controllers.Error(ctx, http.StatusInternalServerError, out) - } - if out, err := tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + rootPassword + " -e \"FLUSH PRIVILEGES;\""); err != nil { - return controllers.Error(ctx, http.StatusInternalServerError, out) - } - - return controllers.Success(ctx, nil) -} diff --git a/app/http/controllers/plugins/mysql80_controller.go b/app/http/controllers/plugins/mysql_controller.go similarity index 91% rename from app/http/controllers/plugins/mysql80_controller.go rename to app/http/controllers/plugins/mysql_controller.go index 09444d8d..3630a184 100644 --- a/app/http/controllers/plugins/mysql80_controller.go +++ b/app/http/controllers/plugins/mysql_controller.go @@ -15,20 +15,20 @@ import ( "panel/pkg/tools" ) -type Mysql80Controller struct { +type MySQLController struct { setting internal.Setting backup internal.Backup } -func NewMysql80Controller() *Mysql80Controller { - return &Mysql80Controller{ +func NewMySQLController() *MySQLController { + return &MySQLController{ setting: services.NewSettingImpl(), backup: services.NewBackupImpl(), } } // Status 获取运行状态 -func (r *Mysql80Controller) Status(ctx http.Context) http.Response { +func (r *MySQLController) Status(ctx http.Context) http.Response { status, err := tools.ServiceStatus("mysqld") if err != nil { return controllers.Error(ctx, http.StatusInternalServerError, "获取MySQL状态失败") @@ -38,7 +38,7 @@ func (r *Mysql80Controller) Status(ctx http.Context) http.Response { } // Reload 重载配置 -func (r *Mysql80Controller) Reload(ctx http.Context) http.Response { +func (r *MySQLController) Reload(ctx http.Context) http.Response { if err := tools.ServiceReload("mysqld"); err != nil { return controllers.Error(ctx, http.StatusInternalServerError, "重载MySQL配置失败") } @@ -47,7 +47,7 @@ func (r *Mysql80Controller) Reload(ctx http.Context) http.Response { } // Restart 重启服务 -func (r *Mysql80Controller) Restart(ctx http.Context) http.Response { +func (r *MySQLController) Restart(ctx http.Context) http.Response { if err := tools.ServiceRestart("mysqld"); err != nil { return controllers.Error(ctx, http.StatusInternalServerError, "重启MySQL服务失败") } @@ -56,7 +56,7 @@ func (r *Mysql80Controller) Restart(ctx http.Context) http.Response { } // Start 启动服务 -func (r *Mysql80Controller) Start(ctx http.Context) http.Response { +func (r *MySQLController) Start(ctx http.Context) http.Response { if err := tools.ServiceStart("mysqld"); err != nil { return controllers.Error(ctx, http.StatusInternalServerError, "启动MySQL服务失败") } @@ -65,7 +65,7 @@ func (r *Mysql80Controller) Start(ctx http.Context) http.Response { } // Stop 停止服务 -func (r *Mysql80Controller) Stop(ctx http.Context) http.Response { +func (r *MySQLController) Stop(ctx http.Context) http.Response { if err := tools.ServiceStop("mysqld"); err != nil { return controllers.Error(ctx, http.StatusInternalServerError, "停止MySQL服务失败") } @@ -74,7 +74,7 @@ func (r *Mysql80Controller) Stop(ctx http.Context) http.Response { } // GetConfig 获取配置 -func (r *Mysql80Controller) GetConfig(ctx http.Context) http.Response { +func (r *MySQLController) GetConfig(ctx http.Context) http.Response { config, err := tools.Read("/www/server/mysql/conf/my.cnf") if err != nil { return controllers.Error(ctx, http.StatusInternalServerError, "获取MySQL配置失败") @@ -84,7 +84,7 @@ func (r *Mysql80Controller) GetConfig(ctx http.Context) http.Response { } // SaveConfig 保存配置 -func (r *Mysql80Controller) SaveConfig(ctx http.Context) http.Response { +func (r *MySQLController) SaveConfig(ctx http.Context) http.Response { config := ctx.Request().Input("config") if len(config) == 0 { return controllers.Error(ctx, http.StatusUnprocessableEntity, "配置不能为空") @@ -98,7 +98,7 @@ func (r *Mysql80Controller) SaveConfig(ctx http.Context) http.Response { } // Load 获取负载 -func (r *Mysql80Controller) Load(ctx http.Context) http.Response { +func (r *MySQLController) Load(ctx http.Context) http.Response { rootPassword := r.setting.Get(models.SettingKeyMysqlRootPassword) if len(rootPassword) == 0 { return controllers.Error(ctx, http.StatusUnprocessableEntity, "MySQL root密码为空") @@ -168,7 +168,7 @@ func (r *Mysql80Controller) Load(ctx http.Context) http.Response { } // ErrorLog 获取错误日志 -func (r *Mysql80Controller) ErrorLog(ctx http.Context) http.Response { +func (r *MySQLController) ErrorLog(ctx http.Context) http.Response { log, err := tools.Exec("tail -n 100 /www/server/mysql/mysql-error.log") if err != nil { return controllers.Error(ctx, http.StatusInternalServerError, log) @@ -178,7 +178,7 @@ func (r *Mysql80Controller) ErrorLog(ctx http.Context) http.Response { } // ClearErrorLog 清空错误日志 -func (r *Mysql80Controller) ClearErrorLog(ctx http.Context) http.Response { +func (r *MySQLController) ClearErrorLog(ctx http.Context) http.Response { if out, err := tools.Exec("echo '' > /www/server/mysql/mysql-error.log"); err != nil { return controllers.Error(ctx, http.StatusInternalServerError, out) } @@ -187,7 +187,7 @@ func (r *Mysql80Controller) ClearErrorLog(ctx http.Context) http.Response { } // SlowLog 获取慢查询日志 -func (r *Mysql80Controller) SlowLog(ctx http.Context) http.Response { +func (r *MySQLController) SlowLog(ctx http.Context) http.Response { log, err := tools.Exec("tail -n 100 /www/server/mysql/mysql-slow.log") if err != nil { return controllers.Error(ctx, http.StatusInternalServerError, log) @@ -197,7 +197,7 @@ func (r *Mysql80Controller) SlowLog(ctx http.Context) http.Response { } // ClearSlowLog 清空慢查询日志 -func (r *Mysql80Controller) ClearSlowLog(ctx http.Context) http.Response { +func (r *MySQLController) ClearSlowLog(ctx http.Context) http.Response { if out, err := tools.Exec("echo '' > /www/server/mysql/mysql-slow.log"); err != nil { return controllers.Error(ctx, http.StatusInternalServerError, out) } @@ -205,7 +205,7 @@ func (r *Mysql80Controller) ClearSlowLog(ctx http.Context) http.Response { } // GetRootPassword 获取root密码 -func (r *Mysql80Controller) GetRootPassword(ctx http.Context) http.Response { +func (r *MySQLController) GetRootPassword(ctx http.Context) http.Response { rootPassword := r.setting.Get(models.SettingKeyMysqlRootPassword) if len(rootPassword) == 0 { return controllers.Error(ctx, http.StatusUnprocessableEntity, "MySQL root密码为空") @@ -215,7 +215,7 @@ func (r *Mysql80Controller) GetRootPassword(ctx http.Context) http.Response { } // SetRootPassword 设置root密码 -func (r *Mysql80Controller) SetRootPassword(ctx http.Context) http.Response { +func (r *MySQLController) SetRootPassword(ctx http.Context) http.Response { status, err := tools.ServiceStatus("mysqld") if err != nil { return controllers.Error(ctx, http.StatusInternalServerError, "获取MySQL状态失败") @@ -253,7 +253,7 @@ func (r *Mysql80Controller) SetRootPassword(ctx http.Context) http.Response { } // DatabaseList 获取数据库列表 -func (r *Mysql80Controller) DatabaseList(ctx http.Context) http.Response { +func (r *MySQLController) DatabaseList(ctx http.Context) http.Response { rootPassword := r.setting.Get(models.SettingKeyMysqlRootPassword) type database struct { Name string `json:"name"` @@ -308,7 +308,7 @@ func (r *Mysql80Controller) DatabaseList(ctx http.Context) http.Response { } // AddDatabase 添加数据库 -func (r *Mysql80Controller) AddDatabase(ctx http.Context) http.Response { +func (r *MySQLController) AddDatabase(ctx http.Context) http.Response { validator, err := ctx.Request().Validate(map[string]string{ "database": "required|min_len:1|max_len:255|regex:^[a-zA-Z][a-zA-Z0-9_]+$", "user": "required|min_len:1|max_len:255|regex:^[a-zA-Z][a-zA-Z0-9_]+$", @@ -343,7 +343,7 @@ func (r *Mysql80Controller) AddDatabase(ctx http.Context) http.Response { } // DeleteDatabase 删除数据库 -func (r *Mysql80Controller) DeleteDatabase(ctx http.Context) http.Response { +func (r *MySQLController) DeleteDatabase(ctx http.Context) http.Response { validator, err := ctx.Request().Validate(map[string]string{ "database": "required|min_len:1|max_len:255|regex:^[a-zA-Z][a-zA-Z0-9_]+$|not_in:information_schema,mysql,performance_schema,sys", }) @@ -364,7 +364,7 @@ func (r *Mysql80Controller) DeleteDatabase(ctx http.Context) http.Response { } // BackupList 获取备份列表 -func (r *Mysql80Controller) BackupList(ctx http.Context) http.Response { +func (r *MySQLController) BackupList(ctx http.Context) http.Response { backupList, err := r.backup.MysqlList() if err != nil { return controllers.Error(ctx, http.StatusInternalServerError, err.Error()) @@ -395,7 +395,7 @@ func (r *Mysql80Controller) BackupList(ctx http.Context) http.Response { } // UploadBackup 上传备份 -func (r *Mysql80Controller) UploadBackup(ctx http.Context) http.Response { +func (r *MySQLController) UploadBackup(ctx http.Context) http.Response { file, err := ctx.Request().File("file") if err != nil { return controllers.Error(ctx, http.StatusUnprocessableEntity, "上传文件失败") @@ -418,7 +418,7 @@ func (r *Mysql80Controller) UploadBackup(ctx http.Context) http.Response { } // CreateBackup 创建备份 -func (r *Mysql80Controller) CreateBackup(ctx http.Context) http.Response { +func (r *MySQLController) CreateBackup(ctx http.Context) http.Response { validator, err := ctx.Request().Validate(map[string]string{ "database": "required|min_len:1|max_len:255|regex:^[a-zA-Z][a-zA-Z0-9_]+$|not_in:information_schema,mysql,performance_schema,sys", }) @@ -439,7 +439,7 @@ func (r *Mysql80Controller) CreateBackup(ctx http.Context) http.Response { } // DeleteBackup 删除备份 -func (r *Mysql80Controller) DeleteBackup(ctx http.Context) http.Response { +func (r *MySQLController) DeleteBackup(ctx http.Context) http.Response { validator, err := ctx.Request().Validate(map[string]string{ "name": "required|min_len:1|max_len:255", }) @@ -460,7 +460,7 @@ func (r *Mysql80Controller) DeleteBackup(ctx http.Context) http.Response { } // RestoreBackup 还原备份 -func (r *Mysql80Controller) RestoreBackup(ctx http.Context) http.Response { +func (r *MySQLController) RestoreBackup(ctx http.Context) http.Response { validator, err := ctx.Request().Validate(map[string]string{ "backup": "required|min_len:1|max_len:255", "database": "required|min_len:1|max_len:255|regex:^[a-zA-Z][a-zA-Z0-9_]+$|not_in:information_schema,mysql,performance_schema,sys", @@ -481,7 +481,7 @@ func (r *Mysql80Controller) RestoreBackup(ctx http.Context) http.Response { } // UserList 用户列表 -func (r *Mysql80Controller) UserList(ctx http.Context) http.Response { +func (r *MySQLController) UserList(ctx http.Context) http.Response { type user struct { User string `json:"user"` Host string `json:"host"` @@ -560,7 +560,7 @@ func (r *Mysql80Controller) UserList(ctx http.Context) http.Response { } // AddUser 添加用户 -func (r *Mysql80Controller) AddUser(ctx http.Context) http.Response { +func (r *MySQLController) AddUser(ctx http.Context) http.Response { validator, err := ctx.Request().Validate(map[string]string{ "database": "required|min_len:1|max_len:255|regex:^[a-zA-Z][a-zA-Z0-9_]+$", "user": "required|min_len:1|max_len:255|regex:^[a-zA-Z][a-zA-Z0-9_]+$", @@ -591,7 +591,7 @@ func (r *Mysql80Controller) AddUser(ctx http.Context) http.Response { } // DeleteUser 删除用户 -func (r *Mysql80Controller) DeleteUser(ctx http.Context) http.Response { +func (r *MySQLController) DeleteUser(ctx http.Context) http.Response { validator, err := ctx.Request().Validate(map[string]string{ "user": "required|min_len:1|max_len:255|regex:^[a-zA-Z][a-zA-Z0-9_]+$", }) @@ -612,7 +612,7 @@ func (r *Mysql80Controller) DeleteUser(ctx http.Context) http.Response { } // SetUserPassword 设置用户密码 -func (r *Mysql80Controller) SetUserPassword(ctx http.Context) http.Response { +func (r *MySQLController) SetUserPassword(ctx http.Context) http.Response { validator, err := ctx.Request().Validate(map[string]string{ "user": "required|min_len:1|max_len:255|regex:^[a-zA-Z][a-zA-Z0-9_]+$", "password": "required|min_len:8|max_len:255", @@ -638,7 +638,7 @@ func (r *Mysql80Controller) SetUserPassword(ctx http.Context) http.Response { } // SetUserPrivileges 设置用户权限 -func (r *Mysql80Controller) SetUserPrivileges(ctx http.Context) http.Response { +func (r *MySQLController) SetUserPrivileges(ctx http.Context) http.Response { validator, err := ctx.Request().Validate(map[string]string{ "user": "required|min_len:1|max_len:255|regex:^[a-zA-Z][a-zA-Z0-9_]+$", "database": "required|min_len:1|max_len:255", diff --git a/internal/plugin_list.go b/internal/plugin_list.go index 421c72aa..172da494 100644 --- a/internal/plugin_list.go +++ b/internal/plugin_list.go @@ -19,7 +19,7 @@ var PluginMySQL57 = PanelPlugin{ Slug: "mysql57", Version: "5.7.44", Requires: []string{}, - Excludes: []string{"mysql80"}, + Excludes: []string{"mysql80", "mysql84"}, Install: `bash /www/panel/scripts/mysql/install.sh 57`, Uninstall: `bash /www/panel/scripts/mysql/uninstall.sh 57`, Update: `bash /www/panel/scripts/mysql/update.sh 57`, @@ -29,19 +29,31 @@ var PluginMySQL80 = PanelPlugin{ Name: "MySQL-8.0", Description: "MySQL 是最流行的关系型数据库管理系统之一,Oracle 旗下产品。(建议内存 > 2G 安装)", Slug: "mysql80", - Version: "8.0.36", + Version: "8.0.37", Requires: []string{}, - Excludes: []string{"mysql57"}, + Excludes: []string{"mysql57", "mysql84"}, Install: `bash /www/panel/scripts/mysql/install.sh 80`, Uninstall: `bash /www/panel/scripts/mysql/uninstall.sh 80`, Update: `bash /www/panel/scripts/mysql/update.sh 80`, } +var PluginMySQL84 = PanelPlugin{ + Name: "MySQL-8.4", + Description: "MySQL 是最流行的关系型数据库管理系统之一,Oracle 旗下产品。(建议内存 > 2G 安装)", + Slug: "mysql84", + Version: "8.4.0", + Requires: []string{}, + Excludes: []string{"mysql57", "mysql80"}, + Install: `bash /www/panel/scripts/mysql/install.sh 84`, + Uninstall: `bash /www/panel/scripts/mysql/uninstall.sh 84`, + Update: `bash /www/panel/scripts/mysql/update.sh 84`, +} + var PluginPostgreSQL15 = PanelPlugin{ Name: "PostgreSQL-15", Description: "PostgreSQL 是世界上最先进的开源关系数据库,在类似 BSD 与 MIT 许可的 PostgreSQL 许可下发行。", Slug: "postgresql15", - Version: "15.6", + Version: "15.7", Requires: []string{}, Excludes: []string{"postgresql16"}, Install: `bash /www/panel/scripts/postgresql/install.sh 15`, @@ -53,7 +65,7 @@ var PluginPostgreSQL16 = PanelPlugin{ Name: "PostgreSQL-16", Description: "PostgreSQL 是世界上最先进的开源关系数据库,在类似 BSD 与 MIT 许可的 PostgreSQL 许可下发行。", Slug: "postgresql16", - Version: "16.2", + Version: "16.3", Requires: []string{}, Excludes: []string{"postgresql15"}, Install: `bash /www/panel/scripts/postgresql/install.sh 16`, @@ -89,7 +101,7 @@ var PluginPHP81 = PanelPlugin{ Name: "PHP-8.1", Description: "PHP 是一种创建动态交互性站点的强有力的服务器端脚本语言。", Slug: "php81", - Version: "8.1.27", + Version: "8.1.28", Requires: []string{}, Excludes: []string{}, Install: `bash /www/panel/scripts/php/install.sh 81`, @@ -101,7 +113,7 @@ var PluginPHP82 = PanelPlugin{ Name: "PHP-8.2", Description: "PHP 是一种创建动态交互性站点的强有力的服务器端脚本语言。", Slug: "php82", - Version: "8.2.16", + Version: "8.2.19", Requires: []string{}, Excludes: []string{}, Install: `bash /www/panel/scripts/php/install.sh 82`, @@ -113,7 +125,7 @@ var PluginPHP83 = PanelPlugin{ Name: "PHP-8.3", Description: "PHP 是一种创建动态交互性站点的强有力的服务器端脚本语言。", Slug: "php83", - Version: "8.3.3", + Version: "8.3.7", Requires: []string{}, Excludes: []string{}, Install: `bash /www/panel/scripts/php/install.sh 83`, @@ -197,7 +209,7 @@ var PluginFail2ban = PanelPlugin{ Name: "Fail2ban", Description: "Fail2ban 扫描系统日志文件并从中找出多次尝试失败的IP地址,将该IP地址加入防火墙的拒绝访问列表中。", Slug: "fail2ban", - Version: "1.0.0", + Version: "1.0.2", Requires: []string{}, Excludes: []string{}, Install: `bash /www/panel/scripts/fail2ban/install.sh`, diff --git a/internal/services/plugin.go b/internal/services/plugin.go index ce67e522..4ab46817 100644 --- a/internal/services/plugin.go +++ b/internal/services/plugin.go @@ -36,6 +36,7 @@ func (r *PluginImpl) All() []internal.PanelPlugin { internal.PluginOpenResty, internal.PluginMySQL57, internal.PluginMySQL80, + internal.PluginMySQL84, internal.PluginPostgreSQL15, internal.PluginPostgreSQL16, internal.PluginPHP74, diff --git a/routes/plugin.go b/routes/plugin.go index 71268258..929f5403 100644 --- a/routes/plugin.go +++ b/routes/plugin.go @@ -25,64 +25,94 @@ func Plugin() { route.Post("clearErrorLog", openRestyController.ClearErrorLog) }) r.Prefix("mysql57").Group(func(route route.Router) { - mysql57Controller := plugins.NewMysql57Controller() - route.Get("status", mysql57Controller.Status) - route.Post("reload", mysql57Controller.Reload) - route.Post("start", mysql57Controller.Start) - route.Post("stop", mysql57Controller.Stop) - route.Post("restart", mysql57Controller.Restart) - route.Get("load", mysql57Controller.Load) - route.Get("config", mysql57Controller.GetConfig) - route.Post("config", mysql57Controller.SaveConfig) - route.Get("errorLog", mysql57Controller.ErrorLog) - route.Post("clearErrorLog", mysql57Controller.ClearErrorLog) - route.Get("slowLog", mysql57Controller.SlowLog) - route.Post("clearSlowLog", mysql57Controller.ClearSlowLog) - route.Get("rootPassword", mysql57Controller.GetRootPassword) - route.Post("rootPassword", mysql57Controller.SetRootPassword) - route.Get("databases", mysql57Controller.DatabaseList) - route.Post("databases", mysql57Controller.AddDatabase) - route.Delete("databases", mysql57Controller.DeleteDatabase) - route.Get("backups", mysql57Controller.BackupList) - route.Post("backups", mysql57Controller.CreateBackup) - route.Put("backups", mysql57Controller.UploadBackup) - route.Delete("backups", mysql57Controller.DeleteBackup) - route.Post("backups/restore", mysql57Controller.RestoreBackup) - route.Get("users", mysql57Controller.UserList) - route.Post("users", mysql57Controller.AddUser) - route.Delete("users", mysql57Controller.DeleteUser) - route.Post("users/password", mysql57Controller.SetUserPassword) - route.Post("users/privileges", mysql57Controller.SetUserPrivileges) + mySQLController := plugins.NewMySQLController() + route.Get("status", mySQLController.Status) + route.Post("reload", mySQLController.Reload) + route.Post("start", mySQLController.Start) + route.Post("stop", mySQLController.Stop) + route.Post("restart", mySQLController.Restart) + route.Get("load", mySQLController.Load) + route.Get("config", mySQLController.GetConfig) + route.Post("config", mySQLController.SaveConfig) + route.Get("errorLog", mySQLController.ErrorLog) + route.Post("clearErrorLog", mySQLController.ClearErrorLog) + route.Get("slowLog", mySQLController.SlowLog) + route.Post("clearSlowLog", mySQLController.ClearSlowLog) + route.Get("rootPassword", mySQLController.GetRootPassword) + route.Post("rootPassword", mySQLController.SetRootPassword) + route.Get("databases", mySQLController.DatabaseList) + route.Post("databases", mySQLController.AddDatabase) + route.Delete("databases", mySQLController.DeleteDatabase) + route.Get("backups", mySQLController.BackupList) + route.Post("backups", mySQLController.CreateBackup) + route.Put("backups", mySQLController.UploadBackup) + route.Delete("backups", mySQLController.DeleteBackup) + route.Post("backups/restore", mySQLController.RestoreBackup) + route.Get("users", mySQLController.UserList) + route.Post("users", mySQLController.AddUser) + route.Delete("users", mySQLController.DeleteUser) + route.Post("users/password", mySQLController.SetUserPassword) + route.Post("users/privileges", mySQLController.SetUserPrivileges) }) r.Prefix("mysql80").Group(func(route route.Router) { - mysql80Controller := plugins.NewMysql80Controller() - route.Get("status", mysql80Controller.Status) - route.Post("reload", mysql80Controller.Reload) - route.Post("start", mysql80Controller.Start) - route.Post("stop", mysql80Controller.Stop) - route.Post("restart", mysql80Controller.Restart) - route.Get("load", mysql80Controller.Load) - route.Get("config", mysql80Controller.GetConfig) - route.Post("config", mysql80Controller.SaveConfig) - route.Get("errorLog", mysql80Controller.ErrorLog) - route.Post("clearErrorLog", mysql80Controller.ClearErrorLog) - route.Get("slowLog", mysql80Controller.SlowLog) - route.Post("clearSlowLog", mysql80Controller.ClearSlowLog) - route.Get("rootPassword", mysql80Controller.GetRootPassword) - route.Post("rootPassword", mysql80Controller.SetRootPassword) - route.Get("databases", mysql80Controller.DatabaseList) - route.Post("databases", mysql80Controller.AddDatabase) - route.Delete("databases", mysql80Controller.DeleteDatabase) - route.Get("backups", mysql80Controller.BackupList) - route.Post("backups", mysql80Controller.CreateBackup) - route.Put("backups", mysql80Controller.UploadBackup) - route.Delete("backups", mysql80Controller.DeleteBackup) - route.Post("backups/restore", mysql80Controller.RestoreBackup) - route.Get("users", mysql80Controller.UserList) - route.Post("users", mysql80Controller.AddUser) - route.Delete("users", mysql80Controller.DeleteUser) - route.Post("users/password", mysql80Controller.SetUserPassword) - route.Post("users/privileges", mysql80Controller.SetUserPrivileges) + mySQLController := plugins.NewMySQLController() + route.Get("status", mySQLController.Status) + route.Post("reload", mySQLController.Reload) + route.Post("start", mySQLController.Start) + route.Post("stop", mySQLController.Stop) + route.Post("restart", mySQLController.Restart) + route.Get("load", mySQLController.Load) + route.Get("config", mySQLController.GetConfig) + route.Post("config", mySQLController.SaveConfig) + route.Get("errorLog", mySQLController.ErrorLog) + route.Post("clearErrorLog", mySQLController.ClearErrorLog) + route.Get("slowLog", mySQLController.SlowLog) + route.Post("clearSlowLog", mySQLController.ClearSlowLog) + route.Get("rootPassword", mySQLController.GetRootPassword) + route.Post("rootPassword", mySQLController.SetRootPassword) + route.Get("databases", mySQLController.DatabaseList) + route.Post("databases", mySQLController.AddDatabase) + route.Delete("databases", mySQLController.DeleteDatabase) + route.Get("backups", mySQLController.BackupList) + route.Post("backups", mySQLController.CreateBackup) + route.Put("backups", mySQLController.UploadBackup) + route.Delete("backups", mySQLController.DeleteBackup) + route.Post("backups/restore", mySQLController.RestoreBackup) + route.Get("users", mySQLController.UserList) + route.Post("users", mySQLController.AddUser) + route.Delete("users", mySQLController.DeleteUser) + route.Post("users/password", mySQLController.SetUserPassword) + route.Post("users/privileges", mySQLController.SetUserPrivileges) + }) + r.Prefix("mysql84").Group(func(route route.Router) { + mySQLController := plugins.NewMySQLController() + route.Get("status", mySQLController.Status) + route.Post("reload", mySQLController.Reload) + route.Post("start", mySQLController.Start) + route.Post("stop", mySQLController.Stop) + route.Post("restart", mySQLController.Restart) + route.Get("load", mySQLController.Load) + route.Get("config", mySQLController.GetConfig) + route.Post("config", mySQLController.SaveConfig) + route.Get("errorLog", mySQLController.ErrorLog) + route.Post("clearErrorLog", mySQLController.ClearErrorLog) + route.Get("slowLog", mySQLController.SlowLog) + route.Post("clearSlowLog", mySQLController.ClearSlowLog) + route.Get("rootPassword", mySQLController.GetRootPassword) + route.Post("rootPassword", mySQLController.SetRootPassword) + route.Get("databases", mySQLController.DatabaseList) + route.Post("databases", mySQLController.AddDatabase) + route.Delete("databases", mySQLController.DeleteDatabase) + route.Get("backups", mySQLController.BackupList) + route.Post("backups", mySQLController.CreateBackup) + route.Put("backups", mySQLController.UploadBackup) + route.Delete("backups", mySQLController.DeleteBackup) + route.Post("backups/restore", mySQLController.RestoreBackup) + route.Get("users", mySQLController.UserList) + route.Post("users", mySQLController.AddUser) + route.Delete("users", mySQLController.DeleteUser) + route.Post("users/password", mySQLController.SetUserPassword) + route.Post("users/privileges", mySQLController.SetUserPrivileges) }) r.Prefix("postgresql15").Group(func(route route.Router) { postgresql15Controller := plugins.NewPostgresql15Controller()