2
0
mirror of https://github.com/acepanel/panel.git synced 2026-02-04 16:10:59 +08:00

feat: MySQL 8.4 支持

This commit is contained in:
耗子
2024-05-16 00:18:01 +08:00
parent 06bf1b0604
commit b82c644d81
5 changed files with 138 additions and 762 deletions

View File

@@ -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)
}

View File

@@ -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",

View File

@@ -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`,

View File

@@ -36,6 +36,7 @@ func (r *PluginImpl) All() []internal.PanelPlugin {
internal.PluginOpenResty,
internal.PluginMySQL57,
internal.PluginMySQL80,
internal.PluginMySQL84,
internal.PluginPostgreSQL15,
internal.PluginPostgreSQL16,
internal.PluginPHP74,

View File

@@ -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()