系统管理基本搞定
This commit is contained in:
@@ -0,0 +1,615 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"regexp"
|
||||
"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
|
||||
}
|
||||
|
||||
func jsonErr(c *beego.Controller, httpStatus, bizCode int, msg string) {
|
||||
c.Ctx.Output.SetStatus(httpStatus)
|
||||
c.Data["json"] = map[string]interface{}{"code": bizCode, "msg": msg}
|
||||
_ = c.ServeJSON()
|
||||
}
|
||||
|
||||
// ===== 主域名池 =====
|
||||
|
||||
// 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()
|
||||
}
|
||||
|
||||
type domainPoolPayload struct {
|
||||
ID uint64 `json:"id"`
|
||||
MainDomain string `json:"main_domain"`
|
||||
Status int8 `json:"status"`
|
||||
}
|
||||
|
||||
// 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()
|
||||
}
|
||||
|
||||
var subDomainRe = regexp.MustCompile(`^[a-zA-Z0-9][a-zA-Z0-9-]{0,61}[a-zA-Z0-9]$`)
|
||||
|
||||
// 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
|
||||
@@ -0,0 +1,351 @@
|
||||
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"
|
||||
)
|
||||
|
||||
// PlatformOperationLogController 操作日志(yz_system_operation_log)
|
||||
type PlatformOperationLogController struct {
|
||||
beego.Controller
|
||||
}
|
||||
|
||||
func (c *PlatformOperationLogController) platformClaims() (*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
|
||||
}
|
||||
|
||||
func (c *PlatformOperationLogController) jsonErr(httpStatus, bizCode int, msg string) {
|
||||
c.Ctx.Output.SetStatus(httpStatus)
|
||||
c.Data["json"] = map[string]interface{}{"code": bizCode, "msg": msg}
|
||||
_ = c.ServeJSON()
|
||||
}
|
||||
|
||||
// List GET /platform/operationLogs?page=1&pageSize=20&keyword=&module=&action=&status=&startTime=&endTime=
|
||||
func (c *PlatformOperationLogController) List() {
|
||||
if _, err := c.platformClaims(); err != nil {
|
||||
c.jsonErr(401, 401, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
page, _ := c.GetInt("page", 1)
|
||||
pageSize, _ := c.GetInt("pageSize", 20)
|
||||
if page < 1 {
|
||||
page = 1
|
||||
}
|
||||
if pageSize < 1 {
|
||||
pageSize = 20
|
||||
}
|
||||
if pageSize > 200 {
|
||||
pageSize = 200
|
||||
}
|
||||
|
||||
keyword := strings.TrimSpace(c.GetString("keyword"))
|
||||
module := strings.TrimSpace(c.GetString("module"))
|
||||
action := strings.TrimSpace(c.GetString("action"))
|
||||
statusStr := strings.TrimSpace(c.GetString("status"))
|
||||
startTimeStr := strings.TrimSpace(c.GetString("startTime"))
|
||||
endTimeStr := strings.TrimSpace(c.GetString("endTime"))
|
||||
|
||||
qs := models.Orm.QueryTable(new(models.SystemOperationLog)).Filter("delete_time__isnull", true)
|
||||
|
||||
// 条件拼装
|
||||
cond := orm.NewCondition()
|
||||
needCond := false
|
||||
|
||||
if module != "" {
|
||||
cond = cond.And("module", module)
|
||||
needCond = true
|
||||
}
|
||||
if action != "" {
|
||||
cond = cond.And("action", action)
|
||||
needCond = true
|
||||
}
|
||||
if statusStr != "" {
|
||||
if st, err := strconv.Atoi(statusStr); err == nil {
|
||||
cond = cond.And("status", st)
|
||||
needCond = true
|
||||
}
|
||||
}
|
||||
if keyword != "" {
|
||||
kw := orm.NewCondition().
|
||||
Or("module__icontains", keyword).
|
||||
Or("action__icontains", keyword).
|
||||
Or("method__icontains", keyword).
|
||||
Or("url__icontains", keyword).
|
||||
Or("ip__icontains", keyword).
|
||||
Or("user_agent__icontains", keyword)
|
||||
if uid, err := strconv.ParseUint(keyword, 10, 64); err == nil && uid > 0 {
|
||||
kw = kw.Or("user_id", uid)
|
||||
}
|
||||
cond = cond.AndCond(kw)
|
||||
needCond = true
|
||||
}
|
||||
if t, err := parseTimeFlexible(startTimeStr); err == nil && !t.IsZero() {
|
||||
cond = cond.And("create_time__gte", t)
|
||||
needCond = true
|
||||
}
|
||||
if t, err := parseTimeFlexible(endTimeStr); err == nil && !t.IsZero() {
|
||||
cond = cond.And("create_time__lte", t)
|
||||
needCond = true
|
||||
}
|
||||
|
||||
if needCond {
|
||||
qs = qs.SetCond(cond)
|
||||
}
|
||||
|
||||
total, err := qs.Count()
|
||||
if err != nil {
|
||||
c.jsonErr(500, 500, "获取操作日志失败: "+err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
var rows []models.SystemOperationLog
|
||||
_, err = qs.OrderBy("-id").Limit(pageSize, (page-1)*pageSize).All(&rows)
|
||||
if err != nil {
|
||||
c.jsonErr(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,
|
||||
"tid": rows[i].Tid,
|
||||
"user_id": rows[i].UserID,
|
||||
"module": rows[i].Module,
|
||||
"action": rows[i].Action,
|
||||
"method": rows[i].Method,
|
||||
"url": rows[i].URL,
|
||||
"ip": rows[i].IP,
|
||||
"user_agent": rows[i].UserAgent,
|
||||
"request_data": rows[i].RequestData,
|
||||
"response_data": rows[i].ResponseData,
|
||||
"status": rows[i].Status,
|
||||
"error_message": rows[i].ErrorMessage,
|
||||
"execution_time": rows[i].ExecutionTime,
|
||||
"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()
|
||||
}
|
||||
|
||||
// Detail GET /platform/operationLogs/:id
|
||||
func (c *PlatformOperationLogController) Detail() {
|
||||
if _, err := c.platformClaims(); err != nil {
|
||||
c.jsonErr(401, 401, err.Error())
|
||||
return
|
||||
}
|
||||
idStr := c.Ctx.Input.Param(":id")
|
||||
id, err := strconv.ParseUint(idStr, 10, 64)
|
||||
if err != nil || id == 0 {
|
||||
c.jsonErr(400, 400, "无效ID")
|
||||
return
|
||||
}
|
||||
var row models.SystemOperationLog
|
||||
err = models.Orm.QueryTable(new(models.SystemOperationLog)).
|
||||
Filter("id", id).
|
||||
Filter("delete_time__isnull", true).
|
||||
One(&row)
|
||||
if err != nil {
|
||||
c.jsonErr(404, 404, "记录不存在")
|
||||
return
|
||||
}
|
||||
out := map[string]interface{}{
|
||||
"id": row.ID,
|
||||
"tid": row.Tid,
|
||||
"user_id": row.UserID,
|
||||
"module": row.Module,
|
||||
"action": row.Action,
|
||||
"method": row.Method,
|
||||
"url": row.URL,
|
||||
"ip": row.IP,
|
||||
"user_agent": row.UserAgent,
|
||||
"request_data": row.RequestData,
|
||||
"response_data": row.ResponseData,
|
||||
"status": row.Status,
|
||||
"error_message": row.ErrorMessage,
|
||||
"execution_time": row.ExecutionTime,
|
||||
"create_time": row.CreateTime.Format("2006-01-02 15:04:05"),
|
||||
}
|
||||
c.Data["json"] = map[string]interface{}{"code": 200, "msg": "success", "data": out}
|
||||
_ = c.ServeJSON()
|
||||
}
|
||||
|
||||
// Delete DELETE /platform/operationLogs/:id
|
||||
func (c *PlatformOperationLogController) Delete() {
|
||||
if _, err := c.platformClaims(); err != nil {
|
||||
c.jsonErr(401, 401, err.Error())
|
||||
return
|
||||
}
|
||||
idStr := c.Ctx.Input.Param(":id")
|
||||
id, err := strconv.ParseUint(idStr, 10, 64)
|
||||
if err != nil || id == 0 {
|
||||
c.jsonErr(400, 400, "无效ID")
|
||||
return
|
||||
}
|
||||
now := time.Now()
|
||||
n, err := models.Orm.QueryTable(new(models.SystemOperationLog)).
|
||||
Filter("id", id).
|
||||
Filter("delete_time__isnull", true).
|
||||
Update(map[string]interface{}{"delete_time": now})
|
||||
if err != nil {
|
||||
c.jsonErr(500, 500, "删除失败: "+err.Error())
|
||||
return
|
||||
}
|
||||
if n == 0 {
|
||||
c.jsonErr(404, 404, "记录不存在")
|
||||
return
|
||||
}
|
||||
c.Data["json"] = map[string]interface{}{"code": 200, "msg": "删除成功"}
|
||||
_ = c.ServeJSON()
|
||||
}
|
||||
|
||||
type batchDeletePayload struct {
|
||||
IDs []uint64 `json:"ids"`
|
||||
}
|
||||
|
||||
// BatchDelete POST /platform/operationLogs/batchDelete
|
||||
func (c *PlatformOperationLogController) BatchDelete() {
|
||||
if _, err := c.platformClaims(); err != nil {
|
||||
c.jsonErr(401, 401, err.Error())
|
||||
return
|
||||
}
|
||||
raw, err := io.ReadAll(c.Ctx.Request.Body)
|
||||
if err != nil {
|
||||
c.jsonErr(400, 400, "参数错误")
|
||||
return
|
||||
}
|
||||
var p batchDeletePayload
|
||||
if err := json.Unmarshal(raw, &p); err != nil {
|
||||
c.jsonErr(400, 400, "参数错误")
|
||||
return
|
||||
}
|
||||
if len(p.IDs) == 0 {
|
||||
c.jsonErr(400, 400, "请选择要删除的日志")
|
||||
return
|
||||
}
|
||||
now := time.Now()
|
||||
_, err = models.Orm.QueryTable(new(models.SystemOperationLog)).
|
||||
Filter("id__in", p.IDs).
|
||||
Filter("delete_time__isnull", true).
|
||||
Update(map[string]interface{}{"delete_time": now})
|
||||
if err != nil {
|
||||
c.jsonErr(500, 500, "批量删除失败: "+err.Error())
|
||||
return
|
||||
}
|
||||
c.Data["json"] = map[string]interface{}{"code": 200, "msg": "批量删除成功"}
|
||||
_ = c.ServeJSON()
|
||||
}
|
||||
|
||||
// Statistics GET /platform/operationLogs/statistics
|
||||
// 供前端筛选项:modules/actions
|
||||
func (c *PlatformOperationLogController) Statistics() {
|
||||
if _, err := c.platformClaims(); err != nil {
|
||||
c.jsonErr(401, 401, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
var moduleRows []models.SystemOperationLog
|
||||
_, _ = models.Orm.QueryTable(new(models.SystemOperationLog)).
|
||||
Filter("delete_time__isnull", true).
|
||||
Filter("module__isnull", false).
|
||||
Limit(1000).
|
||||
All(&moduleRows, "Module")
|
||||
modSet := map[string]struct{}{}
|
||||
for i := range moduleRows {
|
||||
m := strings.TrimSpace(moduleRows[i].Module)
|
||||
if m != "" {
|
||||
modSet[m] = struct{}{}
|
||||
}
|
||||
}
|
||||
modules := make([]string, 0, len(modSet))
|
||||
for k := range modSet {
|
||||
modules = append(modules, k)
|
||||
}
|
||||
|
||||
var actionRows []models.SystemOperationLog
|
||||
_, _ = models.Orm.QueryTable(new(models.SystemOperationLog)).
|
||||
Filter("delete_time__isnull", true).
|
||||
Filter("action__isnull", false).
|
||||
Limit(1000).
|
||||
All(&actionRows, "Action")
|
||||
actSet := map[string]struct{}{}
|
||||
for i := range actionRows {
|
||||
a := strings.TrimSpace(actionRows[i].Action)
|
||||
if a != "" {
|
||||
actSet[a] = struct{}{}
|
||||
}
|
||||
}
|
||||
actions := make([]string, 0, len(actSet))
|
||||
for k := range actSet {
|
||||
actions = append(actions, k)
|
||||
}
|
||||
|
||||
c.Data["json"] = map[string]interface{}{
|
||||
"code": 200,
|
||||
"msg": "success",
|
||||
"data": map[string]interface{}{
|
||||
"modules": modules,
|
||||
"actions": actions,
|
||||
},
|
||||
}
|
||||
_ = c.ServeJSON()
|
||||
}
|
||||
|
||||
func parseTimeFlexible(s string) (time.Time, error) {
|
||||
s = strings.TrimSpace(s)
|
||||
if s == "" {
|
||||
return time.Time{}, fmt.Errorf("empty")
|
||||
}
|
||||
layouts := []string{
|
||||
"2006-01-02 15:04:05",
|
||||
"2006-01-02 15:04",
|
||||
"2006-01-02",
|
||||
time.RFC3339,
|
||||
}
|
||||
for _, ly := range layouts {
|
||||
if t, err := time.ParseInLocation(ly, s, time.Local); err == nil {
|
||||
return t, nil
|
||||
}
|
||||
}
|
||||
return time.Time{}, fmt.Errorf("invalid time")
|
||||
}
|
||||
Reference in New Issue
Block a user