tenant: move admin member queries into service
This commit is contained in:
@@ -1,8 +1,11 @@
|
||||
package dto
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"quyun/v2/app/requests"
|
||||
"quyun/v2/database/models"
|
||||
"quyun/v2/pkg/consts"
|
||||
)
|
||||
|
||||
// AdminTenantUserJoinResponse 返回租户管理员添加成员后的结果。
|
||||
@@ -23,4 +26,25 @@ type AdminTenantUserListFilter struct {
|
||||
requests.Pagination `json:",inline" query:",inline"`
|
||||
// UserID 按用户ID过滤(可选)。
|
||||
UserID *int64 `json:"user_id,omitempty" query:"user_id"`
|
||||
// Role 按角色过滤(可选):member/tenant_admin。
|
||||
Role *consts.TenantUserRole `json:"role,omitempty" query:"role"`
|
||||
// Status 按成员状态过滤(可选):pending_verify/verified/banned。
|
||||
Status *consts.UserStatus `json:"status,omitempty" query:"status"`
|
||||
// Username 按用户名模糊查询(可选,支持包含匹配)。
|
||||
Username *string `json:"username,omitempty" query:"username"`
|
||||
}
|
||||
|
||||
// AdminTenantUserItem 为租户成员列表项(包含成员关系与用户基础信息)。
|
||||
type AdminTenantUserItem struct {
|
||||
// TenantUser 租户成员关系记录。
|
||||
TenantUser *models.TenantUser `json:"tenant_user,omitempty"`
|
||||
// User 用户基础信息(用于展示 username 等)。
|
||||
User *models.User `json:"user,omitempty"`
|
||||
}
|
||||
|
||||
func (f *AdminTenantUserListFilter) UsernameTrimmed() string {
|
||||
if f == nil || f.Username == nil {
|
||||
return ""
|
||||
}
|
||||
return strings.TrimSpace(*f.Username)
|
||||
}
|
||||
|
||||
@@ -186,6 +186,13 @@ func (r *Routes) Register(router fiber.Router) {
|
||||
PathParam[int64]("orderID"),
|
||||
))
|
||||
// Register routes for controller: tenantUserAdmin
|
||||
r.log.Debugf("Registering route: Delete /t/:tenantCode/v1/admin/users/:userID -> tenantUserAdmin.adminRemoveUser")
|
||||
router.Delete("/t/:tenantCode/v1/admin/users/:userID"[len(r.Path()):], Func3(
|
||||
r.tenantUserAdmin.adminRemoveUser,
|
||||
Local[*models.Tenant]("tenant"),
|
||||
Local[*models.TenantUser]("tenant_user"),
|
||||
PathParam[int64]("userID"),
|
||||
))
|
||||
r.log.Debugf("Registering route: Get /t/:tenantCode/v1/admin/users -> tenantUserAdmin.adminTenantUsers")
|
||||
router.Get("/t/:tenantCode/v1/admin/users"[len(r.Path()):], DataFunc3(
|
||||
r.tenantUserAdmin.adminTenantUsers,
|
||||
|
||||
@@ -12,7 +12,6 @@ import (
|
||||
|
||||
"github.com/gofiber/fiber/v3"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"go.ipao.vip/gen"
|
||||
)
|
||||
|
||||
// tenantUserAdmin provides tenant-admin member management endpoints.
|
||||
@@ -20,6 +19,44 @@ import (
|
||||
// @provider
|
||||
type tenantUserAdmin struct{}
|
||||
|
||||
// adminRemoveUser
|
||||
//
|
||||
// @Summary 移除租户成员(租户管理)
|
||||
// @Tags Tenant
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param tenantCode path string true "Tenant Code"
|
||||
// @Param userID path int64 true "UserID"
|
||||
// @Success 200 {object} requests.Pager
|
||||
//
|
||||
// @Router /t/:tenantCode/v1/admin/users/:userID [delete]
|
||||
// @Bind tenant local key(tenant)
|
||||
// @Bind tenantUser local key(tenant_user)
|
||||
// @Bind userID path
|
||||
func (*tenantUserAdmin) adminRemoveUser(
|
||||
ctx fiber.Ctx,
|
||||
tenant *models.Tenant,
|
||||
tenantUser *models.TenantUser,
|
||||
userID int64,
|
||||
) error {
|
||||
if err := requireTenantAdmin(tenantUser); err != nil {
|
||||
return err
|
||||
}
|
||||
if userID <= 0 {
|
||||
return 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.remove")
|
||||
|
||||
// 关键语义:删除成员接口幂等化;目标用户不属于租户时也返回成功,便于后台重试与批量操作。
|
||||
return services.Tenant.RemoveUser(ctx.Context(), tenant.ID, userID)
|
||||
}
|
||||
|
||||
// adminJoinUser
|
||||
//
|
||||
// @Summary 添加租户成员(租户管理)
|
||||
@@ -137,7 +174,7 @@ func (*tenantUserAdmin) adminSetUserRole(
|
||||
// @Produce json
|
||||
// @Param tenantCode path string true "Tenant Code"
|
||||
// @Param filter query dto.AdminTenantUserListFilter true "Filter"
|
||||
// @Success 200 {object} requests.Pager{items=models.TenantUser}
|
||||
// @Success 200 {object} requests.Pager{items=dto.AdminTenantUserItem}
|
||||
//
|
||||
// @Router /t/:tenantCode/v1/admin/users [get]
|
||||
// @Bind tenant local key(tenant)
|
||||
@@ -152,32 +189,16 @@ func (*tenantUserAdmin) adminTenantUsers(
|
||||
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,
|
||||
"role": filter.Role,
|
||||
"status": filter.Status,
|
||||
"username": filter.UsernameTrimmed(),
|
||||
}).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
|
||||
// 按 llm.txt 约束:HTTP 层不允许直接查询数据库,全部交由 services 层处理。
|
||||
return services.Tenant.AdminTenantUsersPage(ctx.Context(), tenant.ID, filter)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user