202 lines
6.5 KiB
Go
202 lines
6.5 KiB
Go
package handler
|
|
|
|
import (
|
|
"net/http"
|
|
"strings"
|
|
"time"
|
|
|
|
"silk-server-go/internal/middleware"
|
|
"silk-server-go/internal/model"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
// RegisterOrganizationRoutes 注册组织和成员数据范围路由。
|
|
func RegisterOrganizationRoutes(rg *gin.RouterGroup, db *gorm.DB) {
|
|
perm := middleware.RequirePermission(db, "organization:manage")
|
|
rg.GET("/organizations", perm, listOrganizations(db))
|
|
rg.POST("/organizations", perm, createOrganization(db))
|
|
rg.PATCH("/organizations/:id", perm, updateOrganization(db))
|
|
rg.GET("/organizations/:id/members", perm, listOrganizationMembers(db))
|
|
rg.POST("/organizations/:id/members", perm, addOrganizationMember(db))
|
|
rg.DELETE("/organizations/:id/members/:userId", perm, removeOrganizationMember(db))
|
|
}
|
|
|
|
func listOrganizations(db *gorm.DB) gin.HandlerFunc {
|
|
return func(c *gin.Context) {
|
|
q := db.Model(&model.Organization{})
|
|
if !hasGlobalAccess(c) {
|
|
q = applyOrgScope(q, c, "organizations.id")
|
|
}
|
|
var list []model.Organization
|
|
q.Order("created_at DESC").Find(&list)
|
|
c.JSON(http.StatusOK, list)
|
|
}
|
|
}
|
|
|
|
func createOrganization(db *gorm.DB) gin.HandlerFunc {
|
|
return func(c *gin.Context) {
|
|
var body struct {
|
|
Name string `json:"name"`
|
|
Code string `json:"code"`
|
|
Description *string `json:"description"`
|
|
}
|
|
if err := c.ShouldBindJSON(&body); err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
if strings.TrimSpace(body.Name) == "" || strings.TrimSpace(body.Code) == "" {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "组织名称和编码不能为空"})
|
|
return
|
|
}
|
|
var count int64
|
|
db.Model(&model.Organization{}).Where("code = ?", body.Code).Count(&count)
|
|
if count > 0 {
|
|
c.JSON(http.StatusConflict, gin.H{"error": "组织编码已存在"})
|
|
return
|
|
}
|
|
org := model.Organization{Name: body.Name, Code: body.Code, Description: body.Description, Status: "active"}
|
|
if err := db.Create(&org).Error; err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "创建组织失败"})
|
|
return
|
|
}
|
|
c.JSON(http.StatusCreated, org)
|
|
}
|
|
}
|
|
|
|
func updateOrganization(db *gorm.DB) gin.HandlerFunc {
|
|
return func(c *gin.Context) {
|
|
id := c.Param("id")
|
|
var org model.Organization
|
|
if db.Where("id = ?", id).First(&org).Error != nil {
|
|
c.JSON(http.StatusNotFound, gin.H{"error": "organization not found"})
|
|
return
|
|
}
|
|
if !canAccessOrganization(db, c, id) {
|
|
c.JSON(http.StatusForbidden, gin.H{"error": "无权管理该组织"})
|
|
return
|
|
}
|
|
updates, err := bindUpdates(c)
|
|
if err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
if len(updates) > 0 {
|
|
if err := db.Model(&model.Organization{}).Where("id = ?", id).Updates(updates).Error; err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "更新组织失败"})
|
|
return
|
|
}
|
|
}
|
|
db.Where("id = ?", id).First(&org)
|
|
c.JSON(http.StatusOK, org)
|
|
}
|
|
}
|
|
|
|
func addOrganizationMember(db *gorm.DB) gin.HandlerFunc {
|
|
return func(c *gin.Context) {
|
|
orgID := c.Param("id")
|
|
var org model.Organization
|
|
if db.Where("id = ?", orgID).First(&org).Error != nil {
|
|
c.JSON(http.StatusNotFound, gin.H{"error": "organization not found"})
|
|
return
|
|
}
|
|
if !canAccessOrganization(db, c, orgID) {
|
|
c.JSON(http.StatusForbidden, gin.H{"error": "无权管理该组织"})
|
|
return
|
|
}
|
|
var body struct {
|
|
UserID string `json:"userId"`
|
|
Role string `json:"role"`
|
|
}
|
|
if err := c.ShouldBindJSON(&body); err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
if !isUUID(body.UserID) {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "userId 不是合法的 UUID"})
|
|
return
|
|
}
|
|
var user model.User
|
|
if db.Where("id = ?", body.UserID).First(&user).Error != nil {
|
|
c.JSON(http.StatusNotFound, gin.H{"error": "user not found"})
|
|
return
|
|
}
|
|
role := body.Role
|
|
if role == "" {
|
|
role = "member"
|
|
}
|
|
if role != "member" && role != "admin" {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "组织角色仅支持 member/admin"})
|
|
return
|
|
}
|
|
var count int64
|
|
db.Model(&model.OrganizationMember{}).
|
|
Where("organization_id = ? AND user_id = ?", orgID, body.UserID).
|
|
Count(&count)
|
|
if count > 0 {
|
|
c.JSON(http.StatusConflict, gin.H{"error": "用户已在该组织"})
|
|
return
|
|
}
|
|
member := model.OrganizationMember{OrganizationID: orgID, UserID: body.UserID, Role: role}
|
|
if err := db.Create(&member).Error; err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "添加成员失败"})
|
|
return
|
|
}
|
|
c.JSON(http.StatusCreated, member)
|
|
}
|
|
}
|
|
|
|
func listOrganizationMembers(db *gorm.DB) gin.HandlerFunc {
|
|
return func(c *gin.Context) {
|
|
orgID := c.Param("id")
|
|
var org model.Organization
|
|
if db.Where("id = ?", orgID).First(&org).Error != nil {
|
|
c.JSON(http.StatusNotFound, gin.H{"error": "organization not found"})
|
|
return
|
|
}
|
|
if !canAccessOrganization(db, c, orgID) {
|
|
c.JSON(http.StatusForbidden, gin.H{"error": "无权查看该组织成员"})
|
|
return
|
|
}
|
|
var rows []struct {
|
|
ID string `gorm:"column:id" json:"id"`
|
|
OrganizationID string `gorm:"column:organization_id" json:"organizationId"`
|
|
UserID string `gorm:"column:user_id" json:"userId"`
|
|
Role string `gorm:"column:role" json:"role"`
|
|
CreatedAt time.Time `gorm:"column:created_at" json:"createdAt"`
|
|
Username string `gorm:"column:username" json:"username"`
|
|
Email string `gorm:"column:email" json:"email"`
|
|
FullName *string `gorm:"column:full_name" json:"fullName,omitempty"`
|
|
}
|
|
if err := db.Table("organization_members om").
|
|
Select("om.id, om.organization_id, om.user_id, om.role, om.created_at, u.username, u.email, u.full_name").
|
|
Joins("JOIN users u ON u.id = om.user_id").
|
|
Where("om.organization_id = ?", orgID).
|
|
Order("om.created_at DESC").
|
|
Scan(&rows).Error; err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "查询组织成员失败"})
|
|
return
|
|
}
|
|
c.JSON(http.StatusOK, rows)
|
|
}
|
|
}
|
|
|
|
func removeOrganizationMember(db *gorm.DB) gin.HandlerFunc {
|
|
return func(c *gin.Context) {
|
|
orgID := c.Param("id")
|
|
userID := c.Param("userId")
|
|
var member model.OrganizationMember
|
|
if db.Where("organization_id = ? AND user_id = ?", orgID, userID).First(&member).Error != nil {
|
|
c.JSON(http.StatusNotFound, gin.H{"error": "organization member not found"})
|
|
return
|
|
}
|
|
if !canAccessOrganization(db, c, orgID) {
|
|
c.JSON(http.StatusForbidden, gin.H{"error": "无权管理该组织"})
|
|
return
|
|
}
|
|
db.Where("id = ?", member.ID).Delete(&model.OrganizationMember{})
|
|
c.JSON(http.StatusOK, gin.H{"organizationId": orgID, "userId": userID})
|
|
}
|
|
}
|