mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2025-01-31 14:08:06 +08:00
feat: 同步用户时,移除创建用户逻辑 (#3442)
This commit is contained in:
parent
57f496fe12
commit
33484a9436
@ -41,6 +41,37 @@ func (b *BaseApi) CreateMysql(c *gin.Context) {
|
|||||||
helper.SuccessWithData(c, nil)
|
helper.SuccessWithData(c, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @Tags Database Mysql
|
||||||
|
// @Summary Bind user of mysql database
|
||||||
|
// @Description 绑定 mysql 数据库用户
|
||||||
|
// @Accept json
|
||||||
|
// @Param request body dto.BindUser true "request"
|
||||||
|
// @Success 200
|
||||||
|
// @Security ApiKeyAuth
|
||||||
|
// @Router /databases/bind [post]
|
||||||
|
// @x-panel-log {"bodyKeys":["database", "username"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"绑定 mysql 数据库名 [database] [username]","formatEN":"bind mysql database [database] [username]"}
|
||||||
|
func (b *BaseApi) BindUser(c *gin.Context) {
|
||||||
|
var req dto.BindUser
|
||||||
|
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(req.Password) != 0 {
|
||||||
|
password, err := base64.StdEncoding.DecodeString(req.Password)
|
||||||
|
if err != nil {
|
||||||
|
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
req.Password = string(password)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := mysqlService.BindUser(req); err != nil {
|
||||||
|
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
helper.SuccessWithData(c, nil)
|
||||||
|
}
|
||||||
|
|
||||||
// @Tags Database Mysql
|
// @Tags Database Mysql
|
||||||
// @Summary Update mysql database description
|
// @Summary Update mysql database description
|
||||||
// @Description 更新 mysql 数据库库描述信息
|
// @Description 更新 mysql 数据库库描述信息
|
||||||
|
@ -43,6 +43,14 @@ type MysqlDBCreate struct {
|
|||||||
Description string `json:"description"`
|
Description string `json:"description"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type BindUser struct {
|
||||||
|
Database string `json:"database" validate:"required"`
|
||||||
|
DB string `json:"db" validate:"required"`
|
||||||
|
Username string `json:"username" validate:"required"`
|
||||||
|
Password string `json:"password" validate:"required"`
|
||||||
|
Permission string `json:"permission" validate:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
type MysqlLoadDB struct {
|
type MysqlLoadDB struct {
|
||||||
From string `json:"from" validate:"required,oneof=local remote"`
|
From string `json:"from" validate:"required,oneof=local remote"`
|
||||||
Type string `json:"type" validate:"required,oneof=mysql mariadb"`
|
Type string `json:"type" validate:"required,oneof=mysql mariadb"`
|
||||||
|
@ -35,6 +35,7 @@ type IMysqlService interface {
|
|||||||
SearchWithPage(search dto.MysqlDBSearch) (int64, interface{}, error)
|
SearchWithPage(search dto.MysqlDBSearch) (int64, interface{}, error)
|
||||||
ListDBOption() ([]dto.MysqlOption, error)
|
ListDBOption() ([]dto.MysqlOption, error)
|
||||||
Create(ctx context.Context, req dto.MysqlDBCreate) (*model.DatabaseMysql, error)
|
Create(ctx context.Context, req dto.MysqlDBCreate) (*model.DatabaseMysql, error)
|
||||||
|
BindUser(req dto.BindUser) error
|
||||||
LoadFromRemote(req dto.MysqlLoadDB) error
|
LoadFromRemote(req dto.MysqlLoadDB) error
|
||||||
ChangeAccess(info dto.ChangeDBInfo) error
|
ChangeAccess(info dto.ChangeDBInfo) error
|
||||||
ChangePassword(info dto.ChangeDBInfo) error
|
ChangePassword(info dto.ChangeDBInfo) error
|
||||||
@ -144,6 +145,42 @@ func (u *MysqlService) Create(ctx context.Context, req dto.MysqlDBCreate) (*mode
|
|||||||
return &createItem, nil
|
return &createItem, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (u *MysqlService) BindUser(req dto.BindUser) error {
|
||||||
|
dbItem, err := mysqlRepo.Get(mysqlRepo.WithByMysqlName(req.Database), commonRepo.WithByName(req.DB))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
cli, version, err := LoadMysqlClientByFrom(req.Database)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer cli.Close()
|
||||||
|
|
||||||
|
if err := cli.CreateUser(client.CreateInfo{
|
||||||
|
Name: dbItem.Name,
|
||||||
|
Format: dbItem.Format,
|
||||||
|
Username: req.Username,
|
||||||
|
Password: req.Password,
|
||||||
|
Permission: req.Permission,
|
||||||
|
Version: version,
|
||||||
|
Timeout: 300,
|
||||||
|
}, false); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
pass, err := encrypt.StringEncrypt(req.Password)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("decrypt database db password failed, err: %v", err)
|
||||||
|
}
|
||||||
|
if err := mysqlRepo.Update(dbItem.ID, map[string]interface{}{
|
||||||
|
"username": req.Username,
|
||||||
|
"password": pass,
|
||||||
|
"permission": req.Permission,
|
||||||
|
}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (u *MysqlService) LoadFromRemote(req dto.MysqlLoadDB) error {
|
func (u *MysqlService) LoadFromRemote(req dto.MysqlLoadDB) error {
|
||||||
client, version, err := LoadMysqlClientByFrom(req.Database)
|
client, version, err := LoadMysqlClientByFrom(req.Database)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -17,6 +17,7 @@ func (s *DatabaseRouter) InitRouter(Router *gin.RouterGroup) {
|
|||||||
baseApi := v1.ApiGroupApp.BaseApi
|
baseApi := v1.ApiGroupApp.BaseApi
|
||||||
{
|
{
|
||||||
cmdRouter.POST("", baseApi.CreateMysql)
|
cmdRouter.POST("", baseApi.CreateMysql)
|
||||||
|
cmdRouter.POST("/bind", baseApi.BindUser)
|
||||||
cmdRouter.POST("load", baseApi.LoadDBFromRemote)
|
cmdRouter.POST("load", baseApi.LoadDBFromRemote)
|
||||||
cmdRouter.POST("/change/access", baseApi.ChangeMysqlAccess)
|
cmdRouter.POST("/change/access", baseApi.ChangeMysqlAccess)
|
||||||
cmdRouter.POST("/change/password", baseApi.ChangeMysqlPassword)
|
cmdRouter.POST("/change/password", baseApi.ChangeMysqlPassword)
|
||||||
|
@ -14,6 +14,7 @@ import (
|
|||||||
|
|
||||||
type MysqlClient interface {
|
type MysqlClient interface {
|
||||||
Create(info client.CreateInfo) error
|
Create(info client.CreateInfo) error
|
||||||
|
CreateUser(info client.CreateInfo, withDeleteDB bool) error
|
||||||
Delete(info client.DeleteInfo) error
|
Delete(info client.DeleteInfo) error
|
||||||
|
|
||||||
ChangePassword(info client.PasswordChangeInfo) error
|
ChangePassword(info client.PasswordChangeInfo) error
|
||||||
|
@ -4,9 +4,7 @@ import (
|
|||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
"errors"
|
"errors"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/1Panel-dev/1Panel/backend/utils/common"
|
|
||||||
"github.com/go-sql-driver/mysql"
|
"github.com/go-sql-driver/mysql"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -103,28 +101,6 @@ var formatMap = map[string]string{
|
|||||||
"big5": "big5_chinese_ci",
|
"big5": "big5_chinese_ci",
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadNameByDB(name, version string) string {
|
|
||||||
nameItem := common.ConvertToPinyin(name)
|
|
||||||
if strings.HasPrefix(version, "5.6") {
|
|
||||||
if len(nameItem) <= 16 {
|
|
||||||
return nameItem
|
|
||||||
}
|
|
||||||
return strings.TrimSuffix(nameItem[:10], "_") + "_" + common.RandStr(5)
|
|
||||||
}
|
|
||||||
if len(nameItem) <= 32 {
|
|
||||||
return nameItem
|
|
||||||
}
|
|
||||||
return strings.TrimSuffix(nameItem[:25], "_") + "_" + common.RandStr(5)
|
|
||||||
}
|
|
||||||
|
|
||||||
func randomPassword(user string) string {
|
|
||||||
passwdItem := user
|
|
||||||
if len(user) > 6 {
|
|
||||||
passwdItem = user[:6]
|
|
||||||
}
|
|
||||||
return passwdItem + "@" + common.RandStrAndNum(8)
|
|
||||||
}
|
|
||||||
|
|
||||||
func VerifyPeerCertFunc(pool *x509.CertPool) func([][]byte, [][]*x509.Certificate) error {
|
func VerifyPeerCertFunc(pool *x509.CertPool) func([][]byte, [][]*x509.Certificate) error {
|
||||||
return func(rawCerts [][]byte, _ [][]*x509.Certificate) error {
|
return func(rawCerts [][]byte, _ [][]*x509.Certificate) error {
|
||||||
if len(rawCerts) == 0 {
|
if len(rawCerts) == 0 {
|
||||||
|
@ -307,19 +307,6 @@ func (r *Local) SyncDB(version string) ([]SyncDBInfo, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(dataItem.Username) == 0 {
|
if len(dataItem.Username) == 0 {
|
||||||
dataItem.Username = loadNameByDB(parts[0], version)
|
|
||||||
dataItem.Password = randomPassword(dataItem.Username)
|
|
||||||
if err := r.CreateUser(CreateInfo{
|
|
||||||
Name: parts[0],
|
|
||||||
Format: parts[1],
|
|
||||||
Version: version,
|
|
||||||
Username: dataItem.Username,
|
|
||||||
Password: dataItem.Password,
|
|
||||||
Permission: "%",
|
|
||||||
Timeout: 300,
|
|
||||||
}, false); err != nil {
|
|
||||||
global.LOG.Errorf("sync from remote server failed, err: create user failed %v", err)
|
|
||||||
}
|
|
||||||
dataItem.Permission = "%"
|
dataItem.Permission = "%"
|
||||||
} else {
|
} else {
|
||||||
if isLocal {
|
if isLocal {
|
||||||
|
@ -333,19 +333,6 @@ func (r *Remote) SyncDB(version string) ([]SyncDBInfo, error) {
|
|||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
if len(dataItem.Username) == 0 {
|
if len(dataItem.Username) == 0 {
|
||||||
dataItem.Username = loadNameByDB(dbName, version)
|
|
||||||
dataItem.Password = randomPassword(dataItem.Username)
|
|
||||||
if err := r.CreateUser(CreateInfo{
|
|
||||||
Name: dbName,
|
|
||||||
Format: charsetName,
|
|
||||||
Version: version,
|
|
||||||
Username: dataItem.Username,
|
|
||||||
Password: dataItem.Password,
|
|
||||||
Permission: "%",
|
|
||||||
Timeout: 300,
|
|
||||||
}, false); err != nil {
|
|
||||||
return datas, fmt.Errorf("sync db from remote server failed, err: create user failed %v", err)
|
|
||||||
}
|
|
||||||
dataItem.Permission = "%"
|
dataItem.Permission = "%"
|
||||||
} else {
|
} else {
|
||||||
if isLocal {
|
if isLocal {
|
||||||
|
@ -3952,6 +3952,49 @@ const docTemplate = `{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/databases/bind": {
|
||||||
|
"post": {
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"ApiKeyAuth": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "绑定 mysql 数据库用户",
|
||||||
|
"consumes": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"Database Mysql"
|
||||||
|
],
|
||||||
|
"summary": "Bind user of mysql database",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"description": "request",
|
||||||
|
"name": "request",
|
||||||
|
"in": "body",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/dto.BindUser"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "OK"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"x-panel-log": {
|
||||||
|
"BeforeFunctions": [],
|
||||||
|
"bodyKeys": [
|
||||||
|
"database",
|
||||||
|
"username"
|
||||||
|
],
|
||||||
|
"formatEN": "bind mysql database [database] [username]",
|
||||||
|
"formatZH": "绑定 mysql 数据库名 [database] [username]",
|
||||||
|
"paramKeys": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/databases/change/access": {
|
"/databases/change/access": {
|
||||||
"post": {
|
"post": {
|
||||||
"security": [
|
"security": [
|
||||||
@ -10013,7 +10056,7 @@ const docTemplate = `{
|
|||||||
"bodyKeys": [
|
"bodyKeys": [
|
||||||
"version"
|
"version"
|
||||||
],
|
],
|
||||||
"formatEN": "upgrade service =\u003e [version]",
|
"formatEN": "upgrade system =\u003e [version]",
|
||||||
"formatZH": "更新系统 =\u003e [version]",
|
"formatZH": "更新系统 =\u003e [version]",
|
||||||
"paramKeys": []
|
"paramKeys": []
|
||||||
}
|
}
|
||||||
@ -13601,6 +13644,33 @@ const docTemplate = `{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"dto.BindUser": {
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"database",
|
||||||
|
"db",
|
||||||
|
"password",
|
||||||
|
"permission",
|
||||||
|
"username"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"database": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"db": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"password": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"permission": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"username": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"dto.CaptchaResponse": {
|
"dto.CaptchaResponse": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
@ -3945,6 +3945,49 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/databases/bind": {
|
||||||
|
"post": {
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"ApiKeyAuth": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "绑定 mysql 数据库用户",
|
||||||
|
"consumes": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"Database Mysql"
|
||||||
|
],
|
||||||
|
"summary": "Bind user of mysql database",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"description": "request",
|
||||||
|
"name": "request",
|
||||||
|
"in": "body",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/dto.BindUser"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "OK"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"x-panel-log": {
|
||||||
|
"BeforeFunctions": [],
|
||||||
|
"bodyKeys": [
|
||||||
|
"database",
|
||||||
|
"username"
|
||||||
|
],
|
||||||
|
"formatEN": "bind mysql database [database] [username]",
|
||||||
|
"formatZH": "绑定 mysql 数据库名 [database] [username]",
|
||||||
|
"paramKeys": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/databases/change/access": {
|
"/databases/change/access": {
|
||||||
"post": {
|
"post": {
|
||||||
"security": [
|
"security": [
|
||||||
@ -10006,7 +10049,7 @@
|
|||||||
"bodyKeys": [
|
"bodyKeys": [
|
||||||
"version"
|
"version"
|
||||||
],
|
],
|
||||||
"formatEN": "upgrade service =\u003e [version]",
|
"formatEN": "upgrade system =\u003e [version]",
|
||||||
"formatZH": "更新系统 =\u003e [version]",
|
"formatZH": "更新系统 =\u003e [version]",
|
||||||
"paramKeys": []
|
"paramKeys": []
|
||||||
}
|
}
|
||||||
@ -13594,6 +13637,33 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"dto.BindUser": {
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"database",
|
||||||
|
"db",
|
||||||
|
"password",
|
||||||
|
"permission",
|
||||||
|
"username"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"database": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"db": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"password": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"permission": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"username": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"dto.CaptchaResponse": {
|
"dto.CaptchaResponse": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
@ -137,6 +137,25 @@ definitions:
|
|||||||
- bindAddress
|
- bindAddress
|
||||||
- ipv6
|
- ipv6
|
||||||
type: object
|
type: object
|
||||||
|
dto.BindUser:
|
||||||
|
properties:
|
||||||
|
database:
|
||||||
|
type: string
|
||||||
|
db:
|
||||||
|
type: string
|
||||||
|
password:
|
||||||
|
type: string
|
||||||
|
permission:
|
||||||
|
type: string
|
||||||
|
username:
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
- database
|
||||||
|
- db
|
||||||
|
- password
|
||||||
|
- permission
|
||||||
|
- username
|
||||||
|
type: object
|
||||||
dto.CaptchaResponse:
|
dto.CaptchaResponse:
|
||||||
properties:
|
properties:
|
||||||
captchaID:
|
captchaID:
|
||||||
@ -7268,6 +7287,34 @@ paths:
|
|||||||
summary: Load mysql base info
|
summary: Load mysql base info
|
||||||
tags:
|
tags:
|
||||||
- Database Mysql
|
- Database Mysql
|
||||||
|
/databases/bind:
|
||||||
|
post:
|
||||||
|
consumes:
|
||||||
|
- application/json
|
||||||
|
description: 绑定 mysql 数据库用户
|
||||||
|
parameters:
|
||||||
|
- description: request
|
||||||
|
in: body
|
||||||
|
name: request
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/dto.BindUser'
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: OK
|
||||||
|
security:
|
||||||
|
- ApiKeyAuth: []
|
||||||
|
summary: Bind user of mysql database
|
||||||
|
tags:
|
||||||
|
- Database Mysql
|
||||||
|
x-panel-log:
|
||||||
|
BeforeFunctions: []
|
||||||
|
bodyKeys:
|
||||||
|
- database
|
||||||
|
- username
|
||||||
|
formatEN: bind mysql database [database] [username]
|
||||||
|
formatZH: 绑定 mysql 数据库名 [database] [username]
|
||||||
|
paramKeys: []
|
||||||
/databases/change/access:
|
/databases/change/access:
|
||||||
post:
|
post:
|
||||||
consumes:
|
consumes:
|
||||||
@ -11106,7 +11153,7 @@ paths:
|
|||||||
BeforeFunctions: []
|
BeforeFunctions: []
|
||||||
bodyKeys:
|
bodyKeys:
|
||||||
- version
|
- version
|
||||||
formatEN: upgrade service => [version]
|
formatEN: upgrade system => [version]
|
||||||
formatZH: 更新系统 => [version]
|
formatZH: 更新系统 => [version]
|
||||||
paramKeys: []
|
paramKeys: []
|
||||||
/toolbox/clean:
|
/toolbox/clean:
|
||||||
|
@ -48,6 +48,13 @@ export namespace Database {
|
|||||||
permission: string;
|
permission: string;
|
||||||
description: string;
|
description: string;
|
||||||
}
|
}
|
||||||
|
export interface BindUser {
|
||||||
|
database: string;
|
||||||
|
db: string;
|
||||||
|
username: string;
|
||||||
|
password: string;
|
||||||
|
permission: string;
|
||||||
|
}
|
||||||
export interface MysqlLoadDB {
|
export interface MysqlLoadDB {
|
||||||
from: string;
|
from: string;
|
||||||
type: string;
|
type: string;
|
||||||
|
@ -19,6 +19,13 @@ export const addMysqlDB = (params: Database.MysqlDBCreate) => {
|
|||||||
}
|
}
|
||||||
return http.post(`/databases`, request);
|
return http.post(`/databases`, request);
|
||||||
};
|
};
|
||||||
|
export const bindUser = (params: Database.BindUser) => {
|
||||||
|
let request = deepCopy(params) as Database.BindUser;
|
||||||
|
if (request.password) {
|
||||||
|
request.password = Base64.encode(request.password);
|
||||||
|
}
|
||||||
|
return http.post(`/databases/bind`, request);
|
||||||
|
};
|
||||||
export const loadDBFromRemote = (params: Database.MysqlLoadDB) => {
|
export const loadDBFromRemote = (params: Database.MysqlLoadDB) => {
|
||||||
return http.post(`/databases/load`, params);
|
return http.post(`/databases/load`, params);
|
||||||
};
|
};
|
||||||
|
@ -380,6 +380,7 @@ const message = {
|
|||||||
'This port is the exposed port of the container. You need to save the modification separately and restart the container!',
|
'This port is the exposed port of the container. You need to save the modification separately and restart the container!',
|
||||||
|
|
||||||
loadFromRemote: 'Load from server',
|
loadFromRemote: 'Load from server',
|
||||||
|
userBind: 'Bind User',
|
||||||
loadFromRemoteHelper:
|
loadFromRemoteHelper:
|
||||||
'This action will synchronize the database info on the server to 1Panel, do you want to continue?',
|
'This action will synchronize the database info on the server to 1Panel, do you want to continue?',
|
||||||
passwordHelper: 'Unable to retrieve, please modify',
|
passwordHelper: 'Unable to retrieve, please modify',
|
||||||
|
@ -373,6 +373,7 @@ const message = {
|
|||||||
confNotFound: '未能找到該應用配置文件,請在應用商店升級該應用至最新版本後重試!',
|
confNotFound: '未能找到該應用配置文件,請在應用商店升級該應用至最新版本後重試!',
|
||||||
|
|
||||||
loadFromRemote: '從服務器獲取',
|
loadFromRemote: '從服務器獲取',
|
||||||
|
userBind: '綁定使用者',
|
||||||
loadFromRemoteHelper: '此操作將同步服務器上數據庫信息到 1Panel,是否繼續?',
|
loadFromRemoteHelper: '此操作將同步服務器上數據庫信息到 1Panel,是否繼續?',
|
||||||
passwordHelper: '無法獲取密碼,請修改',
|
passwordHelper: '無法獲取密碼,請修改',
|
||||||
local: '本地',
|
local: '本地',
|
||||||
|
@ -373,6 +373,7 @@ const message = {
|
|||||||
confNotFound: '未能找到该应用配置文件,请在应用商店升级该应用至最新版本后重试!',
|
confNotFound: '未能找到该应用配置文件,请在应用商店升级该应用至最新版本后重试!',
|
||||||
|
|
||||||
loadFromRemote: '从服务器获取',
|
loadFromRemote: '从服务器获取',
|
||||||
|
userBind: '绑定用户',
|
||||||
loadFromRemoteHelper: '此操作将同步服务器上数据库信息到 1Panel,是否继续?',
|
loadFromRemoteHelper: '此操作将同步服务器上数据库信息到 1Panel,是否继续?',
|
||||||
passwordHelper: '无法获取密码,请修改',
|
passwordHelper: '无法获取密码,请修改',
|
||||||
local: '本地',
|
local: '本地',
|
||||||
|
139
frontend/src/views/database/mysql/bind/index.vue
Normal file
139
frontend/src/views/database/mysql/bind/index.vue
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<el-drawer v-model="bindVisible" :destroy-on-close="true" :close-on-click-modal="false" width="30%">
|
||||||
|
<template #header>
|
||||||
|
<DrawerHeader :header="$t('database.userBind')" :resource="form.mysqlName" :back="handleClose" />
|
||||||
|
</template>
|
||||||
|
<el-form v-loading="loading" ref="changeFormRef" :model="form" :rules="rules" label-position="top">
|
||||||
|
<el-row type="flex" justify="center">
|
||||||
|
<el-col :span="22">
|
||||||
|
<el-form-item :label="$t('commons.login.username')" prop="username">
|
||||||
|
<el-input v-model="form.username"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item :label="$t('commons.login.password')" prop="password">
|
||||||
|
<el-input type="password" clearable show-password v-model="form.password"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item :label="$t('database.permission')" prop="permission">
|
||||||
|
<el-select v-model="form.permission">
|
||||||
|
<el-option value="%" :label="$t('database.permissionAll')" />
|
||||||
|
<el-option
|
||||||
|
v-if="form.from !== 'local'"
|
||||||
|
value="localhost"
|
||||||
|
:label="$t('terminal.localhost')"
|
||||||
|
/>
|
||||||
|
<el-option value="ip" :label="$t('database.permissionForIP')" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item v-if="form.permission === 'ip'" prop="permissionIPs">
|
||||||
|
<el-input
|
||||||
|
clearable
|
||||||
|
:autosize="{ minRows: 2, maxRows: 5 }"
|
||||||
|
type="textarea"
|
||||||
|
v-model="form.permissionIPs"
|
||||||
|
/>
|
||||||
|
<span class="input-help">{{ $t('database.remoteHelper') }}</span>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</el-form>
|
||||||
|
<template #footer>
|
||||||
|
<span class="dialog-footer">
|
||||||
|
<el-button :disabled="loading" @click="bindVisible = false">
|
||||||
|
{{ $t('commons.button.cancel') }}
|
||||||
|
</el-button>
|
||||||
|
<el-button :disabled="loading" type="primary" @click="onSubmit(changeFormRef)">
|
||||||
|
{{ $t('commons.button.confirm') }}
|
||||||
|
</el-button>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-drawer>
|
||||||
|
|
||||||
|
<ConfirmDialog ref="confirmDialogRef" @confirm="onSubmit"></ConfirmDialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { reactive, ref } from 'vue';
|
||||||
|
import i18n from '@/lang';
|
||||||
|
import { ElForm } from 'element-plus';
|
||||||
|
import { bindUser } from '@/api/modules/database';
|
||||||
|
import DrawerHeader from '@/components/drawer-header/index.vue';
|
||||||
|
import { Rules } from '@/global/form-rules';
|
||||||
|
import { MsgSuccess } from '@/utils/message';
|
||||||
|
import { checkIp } from '@/utils/util';
|
||||||
|
|
||||||
|
const loading = ref();
|
||||||
|
const bindVisible = ref(false);
|
||||||
|
type FormInstance = InstanceType<typeof ElForm>;
|
||||||
|
const changeFormRef = ref<FormInstance>();
|
||||||
|
const form = reactive({
|
||||||
|
database: '',
|
||||||
|
mysqlName: '',
|
||||||
|
username: '',
|
||||||
|
password: '',
|
||||||
|
permission: '',
|
||||||
|
permissionIPs: '',
|
||||||
|
});
|
||||||
|
const confirmDialogRef = ref();
|
||||||
|
|
||||||
|
const rules = reactive({
|
||||||
|
username: [Rules.requiredInput, Rules.name],
|
||||||
|
password: [Rules.paramComplexity],
|
||||||
|
permission: [Rules.requiredSelect],
|
||||||
|
permissionIPs: [{ validator: checkIPs, trigger: 'blur', required: true }],
|
||||||
|
});
|
||||||
|
|
||||||
|
function checkIPs(rule: any, value: any, callback: any) {
|
||||||
|
let ips = form.permissionIPs.split(',');
|
||||||
|
for (const item of ips) {
|
||||||
|
if (checkIp(item)) {
|
||||||
|
return callback(new Error(i18n.global.t('commons.rule.ip')));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
|
||||||
|
interface DialogProps {
|
||||||
|
database: string;
|
||||||
|
mysqlName: string;
|
||||||
|
}
|
||||||
|
const acceptParams = (params: DialogProps): void => {
|
||||||
|
form.id = params.id;
|
||||||
|
form.database = params.database;
|
||||||
|
form.mysqlName = params.mysqlName;
|
||||||
|
bindVisible.value = true;
|
||||||
|
};
|
||||||
|
const emit = defineEmits<{ (e: 'search'): void }>();
|
||||||
|
|
||||||
|
const handleClose = () => {
|
||||||
|
bindVisible.value = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
const onSubmit = async (formEl: FormInstance | undefined) => {
|
||||||
|
if (!formEl) return;
|
||||||
|
formEl.validate(async (valid) => {
|
||||||
|
if (!valid) return;
|
||||||
|
let param = {
|
||||||
|
database: form.database,
|
||||||
|
db: form.mysqlName,
|
||||||
|
username: form.username,
|
||||||
|
password: form.password,
|
||||||
|
permission: form.permission === 'ip' ? form.permissionIPs : form.permission,
|
||||||
|
};
|
||||||
|
loading.value = true;
|
||||||
|
await bindUser(param)
|
||||||
|
.then(() => {
|
||||||
|
loading.value = false;
|
||||||
|
emit('search');
|
||||||
|
bindVisible.value = false;
|
||||||
|
MsgSuccess(i18n.global.t('commons.msg.operationSuccess'));
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
loading.value = false;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
acceptParams,
|
||||||
|
});
|
||||||
|
</script>
|
@ -124,10 +124,24 @@
|
|||||||
<template #main v-if="currentDB">
|
<template #main v-if="currentDB">
|
||||||
<ComplexTable :pagination-config="paginationConfig" @sort-change="search" @search="search" :data="data">
|
<ComplexTable :pagination-config="paginationConfig" @sort-change="search" @search="search" :data="data">
|
||||||
<el-table-column :label="$t('commons.table.name')" prop="name" sortable />
|
<el-table-column :label="$t('commons.table.name')" prop="name" sortable />
|
||||||
<el-table-column :label="$t('commons.login.username')" prop="username" />
|
<el-table-column :label="$t('commons.login.username')" prop="username">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<div class="flex items-center" v-if="row.username">
|
||||||
|
<span>
|
||||||
|
{{ row.username }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div v-else>
|
||||||
|
<el-button style="margin-left: -3px" type="primary" link @click="onBind(row)">
|
||||||
|
{{ $t('database.userBind') }}
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
<el-table-column :label="$t('commons.login.password')" prop="password">
|
<el-table-column :label="$t('commons.login.password')" prop="password">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<div class="flex items-center" v-if="row.password">
|
<span v-if="row.username === ''">-</span>
|
||||||
|
<div class="flex items-center" v-if="row.password && row.username">
|
||||||
<div class="star-center" v-if="!row.showPassword">
|
<div class="star-center" v-if="!row.showPassword">
|
||||||
<span>**********</span>
|
<span>**********</span>
|
||||||
</div>
|
</div>
|
||||||
@ -154,10 +168,10 @@
|
|||||||
<CopyButton :content="row.password" type="icon" />
|
<CopyButton :content="row.password" type="icon" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-else>
|
<div v-if="row.password === '' && row.username">
|
||||||
<el-link @click="onChangePassword(row)">
|
<el-button style="margin-left: -3px" link type="primary" @click="onChangePassword(row)">
|
||||||
<span style="font-size: 12px">{{ $t('database.passwordHelper') }}</span>
|
{{ $t('database.passwordHelper') }}
|
||||||
</el-link>
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
@ -221,6 +235,7 @@
|
|||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
|
||||||
|
<BindDialog ref="bindRef" @search="search" />
|
||||||
<PasswordDialog ref="passwordRef" @search="search" />
|
<PasswordDialog ref="passwordRef" @search="search" />
|
||||||
<RootPasswordDialog ref="connRef" />
|
<RootPasswordDialog ref="connRef" />
|
||||||
<UploadDialog ref="uploadRef" />
|
<UploadDialog ref="uploadRef" />
|
||||||
@ -235,6 +250,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
import BindDialog from '@/views/database/mysql/bind/index.vue';
|
||||||
import OperateDialog from '@/views/database/mysql/create/index.vue';
|
import OperateDialog from '@/views/database/mysql/create/index.vue';
|
||||||
import DeleteDialog from '@/views/database/mysql/delete/index.vue';
|
import DeleteDialog from '@/views/database/mysql/delete/index.vue';
|
||||||
import PasswordDialog from '@/views/database/mysql/password/index.vue';
|
import PasswordDialog from '@/views/database/mysql/password/index.vue';
|
||||||
@ -274,6 +290,7 @@ const dbOptionsRemote = ref<Array<Database.DatabaseOption>>([]);
|
|||||||
const currentDB = ref<Database.DatabaseOption>();
|
const currentDB = ref<Database.DatabaseOption>();
|
||||||
const currentDBName = ref();
|
const currentDBName = ref();
|
||||||
|
|
||||||
|
const bindRef = ref();
|
||||||
const checkRef = ref();
|
const checkRef = ref();
|
||||||
const deleteRef = ref();
|
const deleteRef = ref();
|
||||||
|
|
||||||
@ -508,6 +525,14 @@ const onDelete = async (row: Database.MysqlDBInfo) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const onBind = async (row: Database.MysqlDBInfo) => {
|
||||||
|
let param = {
|
||||||
|
database: currentDBName.value,
|
||||||
|
mysqlName: row.name,
|
||||||
|
};
|
||||||
|
bindRef.value.acceptParams(param);
|
||||||
|
};
|
||||||
|
|
||||||
const onChangePassword = async (row: Database.MysqlDBInfo) => {
|
const onChangePassword = async (row: Database.MysqlDBInfo) => {
|
||||||
let param = {
|
let param = {
|
||||||
id: row.id,
|
id: row.id,
|
||||||
@ -525,6 +550,9 @@ const onChangePassword = async (row: Database.MysqlDBInfo) => {
|
|||||||
const buttons = [
|
const buttons = [
|
||||||
{
|
{
|
||||||
label: i18n.global.t('database.changePassword'),
|
label: i18n.global.t('database.changePassword'),
|
||||||
|
disabled: (row: Database.MysqlDBInfo) => {
|
||||||
|
return !row.username;
|
||||||
|
},
|
||||||
click: (row: Database.MysqlDBInfo) => {
|
click: (row: Database.MysqlDBInfo) => {
|
||||||
onChangePassword(row);
|
onChangePassword(row);
|
||||||
},
|
},
|
||||||
|
Loading…
x
Reference in New Issue
Block a user