Files
iqudo-top1/internal/member/handler.go
2026-08-08 22:58:35 +08:00

128 lines
5.0 KiB
Go

package member
import (
"net/http"
"strconv"
"git.iwork-ai.com/xdc/iqudo-top1/internal/audit"
"git.iwork-ai.com/xdc/iqudo-top1/internal/auth"
"git.iwork-ai.com/xdc/iqudo-top1/internal/model"
"git.iwork-ai.com/xdc/iqudo-top1/internal/response"
"github.com/gin-gonic/gin"
"golang.org/x/crypto/bcrypt"
"gorm.io/gorm"
)
type Handler struct{ db *gorm.DB }
func NewHandler(db *gorm.DB) *Handler { return &Handler{db: db} }
type MemberItem struct {
ID uint64 `json:"id"`
UserID uint64 `json:"user_id"`
Username string `json:"username"`
DisplayName string `json:"display_name"`
RoleCode string `json:"role_code"`
RoleName string `json:"role_name"`
Status string `json:"status"`
}
func (h *Handler) List(c *gin.Context) {
principal, _ := auth.PrincipalFromContext(c)
items := make([]MemberItem, 0)
err := h.db.Table("tenant_members tm").Select("tm.id, tm.user_id, u.username, u.display_name, r.code AS role_code, r.name AS role_name, tm.status").Joins("JOIN users u ON u.id = tm.user_id").Joins("JOIN roles r ON r.id = tm.role_id").Where("tm.tenant_id = ?", principal.TenantID).Order("tm.id").Scan(&items).Error
if err != nil {
response.Error(c, http.StatusInternalServerError, "QUERY_FAILED", "查询企业成员失败")
return
}
roles := make([]model.Role, 0)
if err := h.db.Where("tenant_id = ?", principal.TenantID).Order("id").Find(&roles).Error; err != nil {
response.Error(c, http.StatusInternalServerError, "QUERY_FAILED", "查询角色失败")
return
}
response.OK(c, gin.H{"items": items, "roles": roles, "total": len(items)})
}
func (h *Handler) Create(c *gin.Context) {
principal, _ := auth.PrincipalFromContext(c)
var input struct {
Username string `json:"username" binding:"required,min=2,max=64"`
Password string `json:"password" binding:"required,min=6,max=128"`
DisplayName string `json:"display_name" binding:"required,max=128"`
RoleCode string `json:"role_code" binding:"required,max=64"`
}
if err := c.ShouldBindJSON(&input); err != nil {
response.Error(c, http.StatusBadRequest, "INVALID_ARGUMENT", "成员信息不完整")
return
}
var role model.Role
if err := h.db.Where("tenant_id = ? AND code = ?", principal.TenantID, input.RoleCode).First(&role).Error; err != nil {
response.Error(c, http.StatusBadRequest, "INVALID_ROLE", "角色不存在")
return
}
hash, err := bcrypt.GenerateFromPassword([]byte(input.Password), bcrypt.DefaultCost)
if err != nil {
response.Error(c, http.StatusInternalServerError, "CREATE_FAILED", "创建成员失败")
return
}
var user model.User
var membership model.TenantMember
err = h.db.Transaction(func(tx *gorm.DB) error {
user = model.User{Username: input.Username, PasswordHash: string(hash), DisplayName: input.DisplayName, Status: "active"}
if err := tx.Create(&user).Error; err != nil {
return err
}
membership = model.TenantMember{TenantID: principal.TenantID, UserID: user.ID, RoleID: role.ID, Status: "active"}
return tx.Create(&membership).Error
})
if err != nil {
response.Error(c, http.StatusConflict, "MEMBER_EXISTS", "用户名已存在")
return
}
_ = audit.Record(h.db, principal, "create", "tenant_member", membership.ID, gin.H{"username": input.Username, "role_code": input.RoleCode})
response.Created(c, gin.H{"id": membership.ID, "user_id": user.ID})
}
func (h *Handler) Update(c *gin.Context) {
principal, _ := auth.PrincipalFromContext(c)
id, err := strconv.ParseUint(c.Param("id"), 10, 64)
if err != nil || id == 0 {
response.Error(c, http.StatusBadRequest, "INVALID_ID", "成员 ID 不正确")
return
}
var input struct {
RoleCode string `json:"role_code" binding:"required,max=64"`
Status string `json:"status" binding:"required,oneof=active disabled"`
}
if err := c.ShouldBindJSON(&input); err != nil {
response.Error(c, http.StatusBadRequest, "INVALID_ARGUMENT", "成员配置不正确")
return
}
var membership model.TenantMember
if err := h.db.Where("id = ? AND tenant_id = ?", id, principal.TenantID).First(&membership).Error; err != nil {
response.Error(c, http.StatusNotFound, "NOT_FOUND", "成员不存在")
return
}
if membership.UserID == principal.UserID {
response.Error(c, http.StatusConflict, "SELF_UPDATE_FORBIDDEN", "不能修改自己的角色或状态")
return
}
var role model.Role
if err := h.db.Where("tenant_id = ? AND code = ?", principal.TenantID, input.RoleCode).First(&role).Error; err != nil {
response.Error(c, http.StatusBadRequest, "INVALID_ROLE", "角色不存在")
return
}
err = h.db.Transaction(func(tx *gorm.DB) error {
if err := tx.Model(&membership).Updates(map[string]interface{}{"role_id": role.ID, "status": input.Status}).Error; err != nil {
return err
}
return tx.Model(&model.User{}).Where("id = ?", membership.UserID).Update("status", input.Status).Error
})
if err != nil {
response.Error(c, http.StatusInternalServerError, "UPDATE_FAILED", "更新成员失败")
return
}
_ = audit.Record(h.db, principal, "update", "tenant_member", id, input)
response.OK(c, gin.H{"id": id, "role_code": input.RoleCode, "status": input.Status})
}