Files
yunzerwebsiteallinone/go/controllers/platform_domain.go
T
2026-06-24 10:04:03 +08:00

601 lines
17 KiB
Go

package controllers
import (
"encoding/json"
"fmt"
"io"
"strconv"
"strings"
"time"
"server/models"
"server/pkg/jwtutil"
"github.com/beego/beego/v2/client/orm"
beego "github.com/beego/beego/v2/server/web"
)
// PlatformDomainPoolController 主域名池管理
type PlatformDomainPoolController struct {
beego.Controller
}
// PlatformTenantDomainController 租户域名管理
type PlatformTenantDomainController struct {
beego.Controller
}
func requirePlatform(c *beego.Controller) (*jwtutil.Claims, error) {
auth := c.Ctx.Request.Header.Get("Authorization")
if auth == "" {
return nil, fmt.Errorf("未登录")
}
parts := strings.SplitN(auth, " ", 2)
if len(parts) != 2 || parts[0] != "Bearer" {
return nil, fmt.Errorf("认证信息格式错误")
}
claims, err := jwtutil.ParseToken(parts[1])
if err != nil {
return nil, fmt.Errorf("无效的token")
}
if claims.UserType != "platform" {
return nil, fmt.Errorf("无权访问")
}
return claims, nil
}
// ===== 主域名池 =====
// Index GET /platform/domain/pool/index?page=&pageSize=&main_domain=&status=
func (c *PlatformDomainPoolController) Index() {
if _, err := requirePlatform(&c.Controller); err != nil {
jsonErr(&c.Controller, 401, 401, err.Error())
return
}
page, _ := c.GetInt("page", 1)
pageSize, _ := c.GetInt("pageSize", 10)
if page < 1 {
page = 1
}
if pageSize < 1 {
pageSize = 10
}
if pageSize > 200 {
pageSize = 200
}
mainDomain := strings.TrimSpace(c.GetString("main_domain"))
statusStr := strings.TrimSpace(c.GetString("status"))
qs := models.Orm.QueryTable(new(models.SystemDomainPool)).Filter("delete_time__isnull", true)
if mainDomain != "" {
qs = qs.Filter("main_domain__icontains", mainDomain)
}
if statusStr != "" {
if st, err := strconv.Atoi(statusStr); err == nil {
qs = qs.Filter("status", st)
}
}
total, err := qs.Count()
if err != nil {
jsonErr(&c.Controller, 500, 500, "获取主域名池失败: "+err.Error())
return
}
var rows []models.SystemDomainPool
_, err = qs.OrderBy("-id").Limit(pageSize, (page-1)*pageSize).All(&rows)
if err != nil {
jsonErr(&c.Controller, 500, 500, "获取主域名池失败: "+err.Error())
return
}
list := make([]map[string]interface{}, 0, len(rows))
for i := range rows {
item := map[string]interface{}{
"id": rows[i].ID,
"main_domain": rows[i].MainDomain,
"status": rows[i].Status,
"create_time": rows[i].CreateTime.Format("2006-01-02 15:04:05"),
"update_time": "",
}
if rows[i].UpdateTime != nil {
item["update_time"] = rows[i].UpdateTime.Format("2006-01-02 15:04:05")
}
list = append(list, item)
}
c.Data["json"] = map[string]interface{}{
"code": 200,
"msg": "success",
"data": map[string]interface{}{
"list": list,
"total": total,
},
}
_ = c.ServeJSON()
}
// GetEnabledDomains GET /platform/domain/pool/getEnabledDomains
func (c *PlatformDomainPoolController) GetEnabledDomains() {
if _, err := requirePlatform(&c.Controller); err != nil {
jsonErr(&c.Controller, 401, 401, err.Error())
return
}
var rows []models.SystemDomainPool
_, err := models.Orm.QueryTable(new(models.SystemDomainPool)).
Filter("status", 1).
Filter("delete_time__isnull", true).
OrderBy("-id").
All(&rows)
if err != nil {
jsonErr(&c.Controller, 500, 500, "获取主域名失败: "+err.Error())
return
}
out := make([]map[string]interface{}, 0, len(rows))
for i := range rows {
out = append(out, map[string]interface{}{
"id": rows[i].ID,
"main_domain": rows[i].MainDomain,
"status": rows[i].Status,
})
}
c.Data["json"] = map[string]interface{}{"code": 200, "msg": "success", "data": out}
_ = c.ServeJSON()
}
// Create POST /platform/domain/pool/create
func (c *PlatformDomainPoolController) Create() {
if _, err := requirePlatform(&c.Controller); err != nil {
jsonErr(&c.Controller, 401, 401, err.Error())
return
}
raw, err := io.ReadAll(c.Ctx.Request.Body)
if err != nil {
jsonErr(&c.Controller, 400, 400, "参数错误")
return
}
var p domainPoolPayload
if err := json.Unmarshal(raw, &p); err != nil {
jsonErr(&c.Controller, 400, 400, "参数错误")
return
}
md := strings.TrimSpace(p.MainDomain)
if md == "" {
jsonErr(&c.Controller, 400, 400, "主域名不能为空")
return
}
if p.Status != 0 && p.Status != 1 {
p.Status = 1
}
// 简单去重
cnt, _ := models.Orm.QueryTable(new(models.SystemDomainPool)).
Filter("main_domain", md).
Filter("delete_time__isnull", true).
Count()
if cnt > 0 {
jsonErr(&c.Controller, 400, 400, "主域名已存在")
return
}
row := &models.SystemDomainPool{MainDomain: md, Status: p.Status}
if _, err := models.Orm.Insert(row); err != nil {
jsonErr(&c.Controller, 500, 500, "创建失败: "+err.Error())
return
}
c.Data["json"] = map[string]interface{}{"code": 200, "msg": "创建成功"}
_ = c.ServeJSON()
}
// Update POST /platform/domain/pool/update
func (c *PlatformDomainPoolController) Update() {
if _, err := requirePlatform(&c.Controller); err != nil {
jsonErr(&c.Controller, 401, 401, err.Error())
return
}
raw, err := io.ReadAll(c.Ctx.Request.Body)
if err != nil {
jsonErr(&c.Controller, 400, 400, "参数错误")
return
}
var p domainPoolPayload
if err := json.Unmarshal(raw, &p); err != nil {
jsonErr(&c.Controller, 400, 400, "参数错误")
return
}
if p.ID == 0 {
jsonErr(&c.Controller, 400, 400, "id 不能为空")
return
}
md := strings.TrimSpace(p.MainDomain)
if md == "" {
jsonErr(&c.Controller, 400, 400, "主域名不能为空")
return
}
if p.Status != 0 && p.Status != 1 {
p.Status = 1
}
now := time.Now()
n, err := models.Orm.QueryTable(new(models.SystemDomainPool)).
Filter("id", p.ID).
Filter("delete_time__isnull", true).
Update(map[string]interface{}{"main_domain": md, "status": p.Status, "update_time": now})
if err != nil {
jsonErr(&c.Controller, 500, 500, "更新失败: "+err.Error())
return
}
if n == 0 {
jsonErr(&c.Controller, 404, 404, "记录不存在")
return
}
c.Data["json"] = map[string]interface{}{"code": 200, "msg": "更新成功"}
_ = c.ServeJSON()
}
// Delete DELETE /platform/domain/pool/delete/:id
func (c *PlatformDomainPoolController) Delete() {
if _, err := requirePlatform(&c.Controller); err != nil {
jsonErr(&c.Controller, 401, 401, err.Error())
return
}
idStr := c.Ctx.Input.Param(":id")
id, err := strconv.ParseUint(idStr, 10, 64)
if err != nil || id == 0 {
jsonErr(&c.Controller, 400, 400, "无效ID")
return
}
now := time.Now()
n, err := models.Orm.QueryTable(new(models.SystemDomainPool)).
Filter("id", id).
Filter("delete_time__isnull", true).
Update(map[string]interface{}{"delete_time": now, "update_time": now})
if err != nil {
jsonErr(&c.Controller, 500, 500, "删除失败: "+err.Error())
return
}
if n == 0 {
jsonErr(&c.Controller, 404, 404, "记录不存在")
return
}
c.Data["json"] = map[string]interface{}{"code": 200, "msg": "删除成功"}
_ = c.ServeJSON()
}
// ToggleStatus POST /platform/domain/pool/toggleStatus body:{id}
func (c *PlatformDomainPoolController) ToggleStatus() {
if _, err := requirePlatform(&c.Controller); err != nil {
jsonErr(&c.Controller, 401, 401, err.Error())
return
}
raw, err := io.ReadAll(c.Ctx.Request.Body)
if err != nil {
jsonErr(&c.Controller, 400, 400, "参数错误")
return
}
var p struct {
ID uint64 `json:"id"`
}
if err := json.Unmarshal(raw, &p); err != nil || p.ID == 0 {
jsonErr(&c.Controller, 400, 400, "参数错误")
return
}
var row models.SystemDomainPool
if err := models.Orm.QueryTable(new(models.SystemDomainPool)).
Filter("id", p.ID).
Filter("delete_time__isnull", true).
One(&row); err != nil {
jsonErr(&c.Controller, 404, 404, "记录不存在")
return
}
newStatus := int8(1)
if row.Status == 1 {
newStatus = 0
}
now := time.Now()
_, err = models.Orm.QueryTable(new(models.SystemDomainPool)).
Filter("id", p.ID).
Update(map[string]interface{}{"status": newStatus, "update_time": now})
if err != nil {
jsonErr(&c.Controller, 500, 500, "切换失败: "+err.Error())
return
}
c.Data["json"] = map[string]interface{}{"code": 200, "msg": "success"}
_ = c.ServeJSON()
}
// ===== 租户域名 =====
// Index GET /platform/domain/tenant/index?page=&pageSize=&tid=&status=&sub_domain=
func (c *PlatformTenantDomainController) Index() {
if _, err := requirePlatform(&c.Controller); err != nil {
jsonErr(&c.Controller, 401, 401, err.Error())
return
}
page, _ := c.GetInt("page", 1)
pageSize, _ := c.GetInt("pageSize", 10)
if page < 1 {
page = 1
}
if pageSize < 1 {
pageSize = 10
}
if pageSize > 200 {
pageSize = 200
}
tid, _ := c.GetUint64("tid")
statusStr := strings.TrimSpace(c.GetString("status"))
subDomain := strings.TrimSpace(c.GetString("sub_domain"))
qs := models.Orm.QueryTable(new(models.SystemTenantDomain)).Filter("delete_time__isnull", true)
if tid > 0 {
qs = qs.Filter("tid", tid)
}
if statusStr != "" {
if st, err := strconv.Atoi(statusStr); err == nil {
qs = qs.Filter("status", st)
}
}
if subDomain != "" {
qs = qs.Filter("sub_domain__icontains", subDomain)
}
total, err := qs.Count()
if err != nil {
jsonErr(&c.Controller, 500, 500, "获取租户域名失败: "+err.Error())
return
}
var rows []models.SystemTenantDomain
_, err = qs.OrderBy("-id").Limit(pageSize, (page-1)*pageSize).All(&rows)
if err != nil {
jsonErr(&c.Controller, 500, 500, "获取租户域名失败: "+err.Error())
return
}
list := make([]models.SystemTenantDomain, 0, len(rows))
list = append(list, rows...)
c.Data["json"] = map[string]interface{}{
"code": 200,
"msg": "success",
"data": map[string]interface{}{"list": list, "total": total},
}
_ = c.ServeJSON()
}
// MyDomains GET /platform/domain/tenant/myDomains?tid=1
func (c *PlatformTenantDomainController) MyDomains() {
if _, err := requirePlatform(&c.Controller); err != nil {
jsonErr(&c.Controller, 401, 401, err.Error())
return
}
tid, _ := c.GetUint64("tid")
if tid == 0 {
jsonErr(&c.Controller, 400, 400, "租户ID不能为空")
return
}
var rows []models.SystemTenantDomain
_, err := models.Orm.QueryTable(new(models.SystemTenantDomain)).
Filter("tid", tid).
Filter("delete_time__isnull", true).
OrderBy("-id").
All(&rows)
if err != nil {
jsonErr(&c.Controller, 500, 500, "获取失败: "+err.Error())
return
}
c.Data["json"] = map[string]interface{}{"code": 200, "msg": "success", "data": rows}
_ = c.ServeJSON()
}
// Apply POST /platform/domain/tenant/apply body:{tid,sub_domain,main_domain}
func (c *PlatformTenantDomainController) Apply() {
if _, err := requirePlatform(&c.Controller); err != nil {
jsonErr(&c.Controller, 401, 401, err.Error())
return
}
raw, err := io.ReadAll(c.Ctx.Request.Body)
if err != nil {
jsonErr(&c.Controller, 400, 400, "参数错误")
return
}
var p struct {
Tid uint64 `json:"tid"`
SubDomain string `json:"sub_domain"`
MainDomain string `json:"main_domain"`
}
if err := json.Unmarshal(raw, &p); err != nil {
jsonErr(&c.Controller, 400, 400, "参数错误")
return
}
if p.Tid == 0 {
jsonErr(&c.Controller, 400, 400, "租户ID不能为空")
return
}
sub := strings.TrimSpace(p.SubDomain)
main := strings.TrimSpace(p.MainDomain)
if sub == "" {
jsonErr(&c.Controller, 400, 400, "二级域名前缀不能为空")
return
}
if main == "" {
jsonErr(&c.Controller, 400, 400, "请选择主域名")
return
}
if !subDomainRe.MatchString(sub) {
jsonErr(&c.Controller, 400, 400, "二级域名前缀格式不正确")
return
}
// 该租户是否已有域名
cnt, _ := models.Orm.QueryTable(new(models.SystemTenantDomain)).
Filter("tid", p.Tid).
Filter("delete_time__isnull", true).
Count()
if cnt > 0 {
jsonErr(&c.Controller, 400, 400, "该租户已有域名,请删除后再次申请")
return
}
// 主域名存在且启用
var pool models.SystemDomainPool
if err := models.Orm.QueryTable(new(models.SystemDomainPool)).
Filter("main_domain", main).
Filter("status", 1).
Filter("delete_time__isnull", true).
One(&pool); err != nil {
jsonErr(&c.Controller, 400, 400, "主域名不存在或已禁用")
return
}
// 二级域名是否已被使用(同主域名下)
used, _ := models.Orm.QueryTable(new(models.SystemTenantDomain)).
Filter("sub_domain", sub).
Filter("main_domain", main).
Filter("delete_time__isnull", true).
Count()
if used > 0 {
jsonErr(&c.Controller, 400, 400, "该二级域名已被使用")
return
}
full := sub + "." + main
now := time.Now()
tid := p.Tid
row := &models.SystemTenantDomain{
Tid: &tid,
SubDomain: &sub,
MainDomain: &main,
FullDomain: &full,
Status: 0,
CreateTime: now,
UpdateTime: &now,
}
id, err := models.Orm.Insert(row)
if err != nil {
jsonErr(&c.Controller, 500, 500, "申请失败: "+err.Error())
return
}
c.Data["json"] = map[string]interface{}{"code": 200, "msg": "申请提交成功,等待审核", "data": map[string]interface{}{"id": uint64(id)}}
_ = c.ServeJSON()
}
// Audit POST /platform/domain/tenant/audit body:{id,action} action=approve/reject
func (c *PlatformTenantDomainController) Audit() {
if _, err := requirePlatform(&c.Controller); err != nil {
jsonErr(&c.Controller, 401, 401, err.Error())
return
}
raw, err := io.ReadAll(c.Ctx.Request.Body)
if err != nil {
jsonErr(&c.Controller, 400, 400, "参数错误")
return
}
var p struct {
ID uint64 `json:"id"`
Action string `json:"action"`
}
if err := json.Unmarshal(raw, &p); err != nil || p.ID == 0 {
jsonErr(&c.Controller, 400, 400, "参数错误")
return
}
var row models.SystemTenantDomain
if err := models.Orm.QueryTable(new(models.SystemTenantDomain)).Filter("id", p.ID).One(&row); err != nil {
jsonErr(&c.Controller, 404, 404, "域名不存在")
return
}
if row.Status != 0 {
jsonErr(&c.Controller, 400, 400, "该域名已审核过了")
return
}
newStatus := 2
msg := "已拒绝"
if strings.ToLower(strings.TrimSpace(p.Action)) == "approve" {
newStatus = 1
msg = "审核通过"
}
now := time.Now()
_, err = models.Orm.QueryTable(new(models.SystemTenantDomain)).Filter("id", p.ID).Update(map[string]interface{}{
"status": newStatus,
"update_time": now,
})
if err != nil {
jsonErr(&c.Controller, 500, 500, "审核失败: "+err.Error())
return
}
c.Data["json"] = map[string]interface{}{"code": 200, "msg": msg}
_ = c.ServeJSON()
}
// ToggleStatus POST /platform/domain/tenant/toggleStatus body:{id}
func (c *PlatformTenantDomainController) ToggleStatus() {
if _, err := requirePlatform(&c.Controller); err != nil {
jsonErr(&c.Controller, 401, 401, err.Error())
return
}
raw, err := io.ReadAll(c.Ctx.Request.Body)
if err != nil {
jsonErr(&c.Controller, 400, 400, "参数错误")
return
}
var p struct {
ID uint64 `json:"id"`
}
if err := json.Unmarshal(raw, &p); err != nil || p.ID == 0 {
jsonErr(&c.Controller, 400, 400, "参数错误")
return
}
var row models.SystemTenantDomain
if err := models.Orm.QueryTable(new(models.SystemTenantDomain)).Filter("id", p.ID).One(&row); err != nil {
jsonErr(&c.Controller, 404, 404, "域名不存在")
return
}
if row.Status == 0 {
jsonErr(&c.Controller, 400, 400, "审核中不可操作")
return
}
newStatus := 2
if row.Status == 2 {
newStatus = 1
}
now := time.Now()
_, err = models.Orm.QueryTable(new(models.SystemTenantDomain)).Filter("id", p.ID).Update(map[string]interface{}{
"status": newStatus,
"update_time": now,
})
if err != nil {
jsonErr(&c.Controller, 500, 500, "操作失败: "+err.Error())
return
}
c.Data["json"] = map[string]interface{}{"code": 200, "msg": "success"}
_ = c.ServeJSON()
}
// Delete DELETE /platform/domain/tenant/delete/:id
func (c *PlatformTenantDomainController) Delete() {
if _, err := requirePlatform(&c.Controller); err != nil {
jsonErr(&c.Controller, 401, 401, err.Error())
return
}
idStr := c.Ctx.Input.Param(":id")
id, err := strconv.ParseUint(idStr, 10, 64)
if err != nil || id == 0 {
jsonErr(&c.Controller, 400, 400, "参数错误")
return
}
now := time.Now()
n, err := models.Orm.QueryTable(new(models.SystemTenantDomain)).
Filter("id", id).
Filter("delete_time__isnull", true).
Update(map[string]interface{}{"delete_time": now, "update_time": now})
if err != nil {
jsonErr(&c.Controller, 500, 500, "删除失败: "+err.Error())
return
}
if n == 0 {
jsonErr(&c.Controller, 404, 404, "域名不存在")
return
}
c.Data["json"] = map[string]interface{}{"code": 200, "msg": "删除成功"}
_ = c.ServeJSON()
}
// 用于复杂筛选时可扩展:当前保留 orm.Condition import,避免被 gofmt 删除
var _ = orm.NewCondition