Enhance team retrieval functionality and improve user team handling

- Updated GetTeamsByMember method to include role information and owner status for each team member.
- Refactored GinTeamList to utilize the new getUserTeams function, simplifying team retrieval logic and removing pagination.
- Introduced getUserTeams and getUserTeamsCount functions to encapsulate team membership logic, improving code organization and clarity.
- Removed deprecated team retrieval logic from user/team.go, streamlining the codebase.
This commit is contained in:
Max 2025-10-11 10:54:51 +08:00
parent 6abcf79dd7
commit afa5b2d3f2
4 changed files with 69 additions and 91 deletions

View file

@ -251,12 +251,12 @@ func (u *DefaultUser) GetTeamsByOwner(ctx context.Context, ownerID string) ([]ma
return u.GetTeams(ctx, param)
}
// GetTeamsByMember retrieves teams by member_id
// GetTeamsByMember retrieves teams by member_id (includes role information and owner status)
func (u *DefaultUser) GetTeamsByMember(ctx context.Context, memberID string) ([]maps.MapStr, error) {
// Set default select fields if not provided
// Query member records to get team_id and role_id
param := model.QueryParam{
Select: []interface{}{"team_id", "user_id", "member_type"},
Select: []interface{}{"team_id", "user_id", "member_type", "role_id"},
Wheres: []model.QueryWhere{
{Column: "user_id", Value: memberID},
{Column: "member_type", Value: "user"},
@ -264,10 +264,6 @@ func (u *DefaultUser) GetTeamsByMember(ctx context.Context, memberID string) ([]
},
}
if param.Select == nil {
param.Select = u.memberFields
}
m := model.Select(u.memberModel)
members, err := m.Get(param)
if err != nil {
@ -278,10 +274,17 @@ func (u *DefaultUser) GetTeamsByMember(ctx context.Context, memberID string) ([]
return []maps.MapStr{}, nil
}
// Get team ids
// Build team_id to role_id mapping
teamRoleMap := make(map[string]string)
teamIDs := []string{}
for _, member := range members {
teamIDs = append(teamIDs, member["team_id"].(string))
teamID := member["team_id"].(string)
roleID := ""
if role, ok := member["role_id"]; ok && role != nil {
roleID = fmt.Sprintf("%v", role)
}
teamRoleMap[teamID] = roleID
teamIDs = append(teamIDs, teamID)
}
// Get teams
@ -295,6 +298,21 @@ func (u *DefaultUser) GetTeamsByMember(ctx context.Context, memberID string) ([]
return nil, fmt.Errorf(ErrFailedToGetTeam, err)
}
// Append role_id and is_owner to each team
for i := range teams {
teamID := teams[i]["team_id"].(string)
if roleID, exists := teamRoleMap[teamID]; exists {
teams[i]["role_id"] = roleID
}
// Check if user is the owner of this team
ownerID := ""
if owner, ok := teams[i]["owner_id"]; ok && owner != nil {
ownerID = fmt.Sprintf("%v", owner)
}
teams[i]["is_owner"] = (ownerID == memberID)
}
return teams, nil
}

View file

@ -216,7 +216,7 @@ func LoginByUserID(userid string, ip string) (*LoginResponse, error) {
}
// Count User Teams
numTeams, err := countUserTeams(ctx, userid)
numTeams, err := getUserTeamsCount(ctx, userid)
if err != nil {
return nil, err
}

View file

@ -1,7 +1,6 @@
package user
import (
"context"
"fmt"
"net"
"net/http"
@ -14,7 +13,6 @@ import (
"github.com/google/uuid"
"github.com/yaoapp/gou/session"
"github.com/yaoapp/kun/log"
"github.com/yaoapp/kun/maps"
"github.com/yaoapp/yao/openapi/oauth"
"github.com/yaoapp/yao/openapi/response"
"github.com/yaoapp/yao/openapi/utils"
@ -460,24 +458,6 @@ func getUserInfo(providerID, state string) (string, error) {
return value.(string), nil
}
// getUserTeams gets the user teams
func getUserTeams(ctx context.Context, userID string) ([]maps.MapStr, error) {
userProvider, err := oauth.OAuth.GetUserProvider()
if err != nil {
return nil, err
}
return userProvider.GetTeamsByMember(ctx, userID)
}
// countUserTeams counts the number of teams a user is a member of
func countUserTeams(ctx context.Context, userID string) (int64, error) {
userProvider, err := oauth.OAuth.GetUserProvider()
if err != nil {
return 0, err
}
return userProvider.CountTeamsByMember(ctx, userID)
}
// removeUserInfo removes the user info from cache
func removeUserInfo(providerID, state string) error {
key := userInfoKey(providerID, state)

View file

@ -4,7 +4,6 @@ import (
"context"
"fmt"
"net/http"
"strconv"
"strings"
"time"
@ -45,7 +44,7 @@ func GinTeamConfig(c *gin.Context) {
response.RespondWithSuccess(c, http.StatusOK, config)
}
// GinTeamList handles GET /teams - Get user teams
// GinTeamList handles GET /teams - Get user teams (all teams where user is a member)
func GinTeamList(c *gin.Context) {
// Get authorized user info
authInfo := oauth.GetAuthorizedInfo(c)
@ -58,63 +57,8 @@ func GinTeamList(c *gin.Context) {
return
}
// Parse pagination parameters
page := 1
pagesize := 20
if p := c.Query("page"); p != "" {
if parsed, err := strconv.Atoi(p); err == nil && parsed > 0 {
page = parsed
}
}
if ps := c.Query("pagesize"); ps != "" {
if parsed, err := strconv.Atoi(ps); err == nil && parsed > 0 && parsed <= 100 {
pagesize = parsed
}
}
// Get user provider instance
provider, err := getUserProvider()
if err != nil {
log.Error("Failed to get user provider: %v", err)
errorResp := &response.ErrorResponse{
Code: response.ErrServerError.Code,
ErrorDescription: "Failed to initialize user provider",
}
response.RespondWithError(c, response.StatusInternalServerError, errorResp)
return
}
// Build query parameters
param := model.QueryParam{
Wheres: []model.QueryWhere{
{Column: "owner_id", Value: authInfo.UserID},
},
Orders: []model.QueryOrder{
{Column: "created_at", Option: "desc"},
},
}
// Add status filter if provided
if status := c.Query("status"); status != "" {
param.Wheres = append(param.Wheres, model.QueryWhere{
Column: "status",
Value: status,
})
}
// Add name search if provided
if name := c.Query("name"); name != "" {
param.Wheres = append(param.Wheres, model.QueryWhere{
Column: "name",
Value: "%" + name + "%",
OP: "like",
})
}
// Get paginated teams
result, err := provider.PaginateTeams(c.Request.Context(), param, page, pagesize)
// Call business logic to get user teams with roles
teams, err := getUserTeams(c.Request.Context(), authInfo.UserID)
if err != nil {
log.Error("Failed to get user teams: %v", err)
errorResp := &response.ErrorResponse{
@ -125,8 +69,8 @@ func GinTeamList(c *gin.Context) {
return
}
// Return the paginated result directly (consistent with other modules)
response.RespondWithSuccess(c, http.StatusOK, result)
// Return teams list directly (no pagination)
response.RespondWithSuccess(c, http.StatusOK, teams)
}
// GinTeamGet handles GET /teams/:id - Get user team details
@ -839,3 +783,39 @@ func mapToTeamDetailResponse(data maps.MapStr) TeamDetailResponse {
return team
}
// Business Logic Functions for Team Membership
// getUserTeams gets all teams where the user is a member (includes role information)
func getUserTeams(ctx context.Context, userID string) ([]maps.MapStr, error) {
// Get user provider instance
provider, err := getUserProvider()
if err != nil {
return nil, fmt.Errorf("failed to get user provider: %w", err)
}
// Get teams with role information
teams, err := provider.GetTeamsByMember(ctx, userID)
if err != nil {
return nil, fmt.Errorf("failed to retrieve user teams: %w", err)
}
return teams, nil
}
// getUserTeamsCount counts the number of teams a user is a member of
func getUserTeamsCount(ctx context.Context, userID string) (int64, error) {
// Get user provider instance
provider, err := getUserProvider()
if err != nil {
return 0, fmt.Errorf("failed to get user provider: %w", err)
}
// Count teams
count, err := provider.CountTeamsByMember(ctx, userID)
if err != nil {
return 0, fmt.Errorf("failed to count user teams: %w", err)
}
return count, nil
}