feat: Go后端补全所有缺失API接口,消除前端404报错
新增接口: - GET /instances/accessible — 查询页实例列表(按access_type筛选) - GET /instances/:id/databases — 数据库列表(placeholder) - GET /instances/:id/databases/:db/tables — 表列表(placeholder) - POST /instances/test-connection — 新实例连接测试 - CRUD /instance-groups — 完整实例组管理(创建/更新/删除/查询单个) - /instance-groups/:id/instances — 实例分配/移除 - /instance-groups/:id/users — 用户分配 - PUT /instance-groups/users/:userId/groups — 用户组更新 - GET/PUT /ldap-config — LDAP配置读写 - POST /ldap-config/test — LDAP连接测试(placeholder) - POST /ldap-config/ou-list — OU列表(placeholder) - POST /ldap-config/user-list — 用户列表(placeholder) - PUT /settings — 批量更新设置 - GET /settings/cleanup/preview — 清理预览 - POST /settings/cleanup/run — 执行清理 修复: - ListSettings 返回按group分组的dict(前端期望格式) - ListInstanceGroups 返回enriched数据(含实例/用户计数) - 前端所有页面0个404错误,查询页实例下拉框正常显示
This commit is contained in:
1 parent
26148d0ca7
commit
622923821b
5 files changed
+526
-4
No files matched your search
@@ -0,0 +1,98 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"sql-platform/internal/middleware"
|
||||
"sql-platform/internal/model"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// GET /api/v1/instances/accessible?access_type=readonly|write
|
||||
func AccessibleInstances(c *gin.Context) {
|
||||
userID, _, role := middleware.GetCurrentUser(c)
|
||||
accessType := c.DefaultQuery("access_type", "readonly")
|
||||
|
||||
var instances []model.Instance
|
||||
|
||||
if role == "admin" || role == "dba" {
|
||||
// admin/dba see all instances, filter by access_mode if needed
|
||||
query := model.DB.Order("id")
|
||||
if accessType == "readonly" {
|
||||
query = query.Where("access_mode IN ?", []string{"readwrite", "readonly"})
|
||||
} else {
|
||||
query = query.Where("access_mode IN ?", []string{"readwrite", "write"})
|
||||
}
|
||||
query.Find(&instances)
|
||||
} else {
|
||||
// developer/auditor: only instances in their groups
|
||||
var groupIDs []int
|
||||
model.DB.Model(&model.UserGroup{}).Where("user_id = ?", userID).Pluck("group_id", &groupIDs)
|
||||
if len(groupIDs) == 0 {
|
||||
c.JSON(http.StatusOK, []model.Instance{})
|
||||
return
|
||||
}
|
||||
var instanceIDs []int
|
||||
model.DB.Model(&model.InstanceGroupMember{}).
|
||||
Where("group_id IN ? AND access_type = ?", groupIDs, accessType).
|
||||
Pluck("instance_id", &instanceIDs)
|
||||
// also include readwrite
|
||||
if accessType == "readonly" {
|
||||
model.DB.Model(&model.InstanceGroupMember{}).
|
||||
Where("group_id IN ? AND access_type = ?", groupIDs, "readwrite").
|
||||
Pluck("instance_id", &instanceIDs)
|
||||
} else if accessType == "write" {
|
||||
model.DB.Model(&model.InstanceGroupMember{}).
|
||||
Where("group_id IN ? AND access_type = ?", groupIDs, "readwrite").
|
||||
Pluck("instance_id", &instanceIDs)
|
||||
}
|
||||
if len(instanceIDs) == 0 {
|
||||
c.JSON(http.StatusOK, []model.Instance{})
|
||||
return
|
||||
}
|
||||
model.DB.Where("id IN ?", instanceIDs).Order("id").Find(&instances)
|
||||
}
|
||||
|
||||
// mask passwords
|
||||
for i := range instances {
|
||||
instances[i].Password = "******"
|
||||
}
|
||||
c.JSON(http.StatusOK, instances)
|
||||
}
|
||||
|
||||
// GET /api/v1/instances/:id/databases
|
||||
func ListDatabases(c *gin.Context) {
|
||||
id := c.Param("id")
|
||||
var instance model.Instance
|
||||
if err := model.DB.First(&instance, id).Error; err != nil {
|
||||
c.JSON(http.StatusNotFound, gin.H{"detail": "Instance not found"})
|
||||
return
|
||||
}
|
||||
// TODO: actual database connection to list databases
|
||||
// Return placeholder for now
|
||||
c.JSON(http.StatusOK, []string{"information_schema"})
|
||||
}
|
||||
|
||||
// GET /api/v1/instances/:id/databases/:db/tables
|
||||
func ListTables(c *gin.Context) {
|
||||
id := c.Param("id")
|
||||
dbName := c.Param("db")
|
||||
var instance model.Instance
|
||||
if err := model.DB.First(&instance, id).Error; err != nil {
|
||||
c.JSON(http.StatusNotFound, gin.H{"detail": "Instance not found"})
|
||||
return
|
||||
}
|
||||
// TODO: actual database connection to list tables
|
||||
_ = dbName
|
||||
c.JSON(http.StatusOK, []interface{}{})
|
||||
}
|
||||
|
||||
// POST /api/v1/instances/test-connection (new instance, not saved yet)
|
||||
func TestNewConnection(c *gin.Context) {
|
||||
// TODO: actual connection test
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": true,
|
||||
"message": "Connection test passed (placeholder)",
|
||||
})
|
||||
}
|
||||
Reference in new issue
Block a user