Files
quyun-v2/backend/app/http/tenant/tenant_user_admin.go

184 lines
5.0 KiB
Go

package tenant
import (
"strings"
"quyun/v2/app/errorx"
"quyun/v2/app/http/tenant/dto"
"quyun/v2/app/requests"
"quyun/v2/app/services"
"quyun/v2/database/models"
"quyun/v2/pkg/consts"
"github.com/gofiber/fiber/v3"
log "github.com/sirupsen/logrus"
"go.ipao.vip/gen"
)
// tenantUserAdmin provides tenant-admin member management endpoints.
//
// @provider
type tenantUserAdmin struct{}
// adminJoinUser
//
// @Summary 添加租户成员(租户管理)
// @Tags Tenant
// @Accept json
// @Produce json
// @Param tenantCode path string true "Tenant Code"
// @Param userID path int64 true "UserID"
// @Success 200 {object} dto.AdminTenantUserJoinResponse
//
// @Router /t/:tenantCode/v1/admin/users/:userID/join [post]
// @Bind tenant local key(tenant)
// @Bind tenantUser local key(tenant_user)
// @Bind userID path
func (*tenantUserAdmin) adminJoinUser(
ctx fiber.Ctx,
tenant *models.Tenant,
tenantUser *models.TenantUser,
userID int64,
) (*dto.AdminTenantUserJoinResponse, error) {
if err := requireTenantAdmin(tenantUser); err != nil {
return nil, err
}
if userID <= 0 {
return nil, errorx.ErrInvalidParameter.WithMsg("user_id must be > 0")
}
log.WithFields(log.Fields{
"tenant_id": tenant.ID,
"operator_user_id": tenantUser.UserID,
"target_user_id": userID,
"operator_is_admin": true,
}).Info("tenant.admin.users.join")
// 关键逻辑:以 TenantUser 为准创建成员关系;服务层保证幂等(已存在则不重复创建)。
if err := services.Tenant.AddUser(ctx.Context(), tenant.ID, userID); err != nil {
return nil, err
}
m, err := services.Tenant.FindTenantUser(ctx.Context(), tenant.ID, userID)
if err != nil {
return nil, err
}
return &dto.AdminTenantUserJoinResponse{TenantUser: m}, nil
}
// adminSetUserRole
//
// @Summary 设置成员角色(租户管理)
// @Tags Tenant
// @Accept json
// @Produce json
// @Param tenantCode path string true "Tenant Code"
// @Param userID path int64 true "UserID"
// @Param form body dto.AdminTenantUserRoleUpdateForm true "Form"
// @Success 200 {object} dto.AdminTenantUserJoinResponse
//
// @Router /t/:tenantCode/v1/admin/users/:userID/role [patch]
// @Bind tenant local key(tenant)
// @Bind tenantUser local key(tenant_user)
// @Bind userID path
// @Bind form body
func (*tenantUserAdmin) adminSetUserRole(
ctx fiber.Ctx,
tenant *models.Tenant,
tenantUser *models.TenantUser,
userID int64,
form *dto.AdminTenantUserRoleUpdateForm,
) (*dto.AdminTenantUserJoinResponse, error) {
if err := requireTenantAdmin(tenantUser); err != nil {
return nil, err
}
if userID <= 0 || form == nil {
return nil, errorx.ErrInvalidParameter
}
roleStr := strings.TrimSpace(form.Role)
if roleStr == "" {
return nil, errorx.ErrInvalidParameter.WithMsg("role is required")
}
var role consts.TenantUserRole
switch roleStr {
case string(consts.TenantUserRoleMember):
role = consts.TenantUserRoleMember
case string(consts.TenantUserRoleTenantAdmin):
role = consts.TenantUserRoleTenantAdmin
default:
return nil, errorx.ErrInvalidParameter.WithMsg("invalid role")
}
log.WithFields(log.Fields{
"tenant_id": tenant.ID,
"operator_user_id": tenantUser.UserID,
"target_user_id": userID,
"role": role,
}).Info("tenant.admin.users.set_role")
if err := services.Tenant.SetUserRole(ctx.Context(), tenant.ID, userID, role); err != nil {
return nil, err
}
m, err := services.Tenant.FindTenantUser(ctx.Context(), tenant.ID, userID)
if err != nil {
return nil, err
}
return &dto.AdminTenantUserJoinResponse{TenantUser: m}, nil
}
// adminTenantUsers
//
// @Summary 成员列表(租户管理)
// @Tags Tenant
// @Accept json
// @Produce json
// @Param tenantCode path string true "Tenant Code"
// @Param filter query dto.AdminTenantUserListFilter true "Filter"
// @Success 200 {object} requests.Pager{items=models.TenantUser}
//
// @Router /t/:tenantCode/v1/admin/users [get]
// @Bind tenant local key(tenant)
// @Bind tenantUser local key(tenant_user)
// @Bind filter query
func (*tenantUserAdmin) adminTenantUsers(
ctx fiber.Ctx,
tenant *models.Tenant,
tenantUser *models.TenantUser,
filter *dto.AdminTenantUserListFilter,
) (*requests.Pager, error) {
if err := requireTenantAdmin(tenantUser); err != nil {
return nil, err
}
if filter == nil {
filter = &dto.AdminTenantUserListFilter{}
}
log.WithFields(log.Fields{
"tenant_id": tenant.ID,
"user_id": tenantUser.UserID,
"query_uid": filter.UserID,
}).Info("tenant.admin.users.list")
filter.Pagination.Format()
tbl, query := models.TenantUserQuery.QueryContext(ctx.Context())
conds := []gen.Condition{tbl.TenantID.Eq(tenant.ID)}
if filter.UserID != nil && *filter.UserID > 0 {
conds = append(conds, tbl.UserID.Eq(*filter.UserID))
}
items, total, err := query.Where(conds...).Order(tbl.ID.Desc()).FindByPage(int(filter.Offset()), int(filter.Limit))
if err != nil {
return nil, err
}
return &requests.Pager{
Pagination: filter.Pagination,
Total: total,
Items: items,
}, nil
}