Merge pull request #1227 from trheyi/main
Add current team retrieval endpoint and refactor team access checks
This commit is contained in:
commit
932a8d2c0e
2 changed files with 85 additions and 5 deletions
|
|
@ -49,7 +49,7 @@ func GinTeamConfig(c *gin.Context) {
|
||||||
// GinTeamList handles GET /teams - Get user teams (all teams where user is a member)
|
// GinTeamList handles GET /teams - Get user teams (all teams where user is a member)
|
||||||
func GinTeamList(c *gin.Context) {
|
func GinTeamList(c *gin.Context) {
|
||||||
// Get authorized user info
|
// Get authorized user info
|
||||||
authInfo := oauth.GetAuthorizedInfo(c)
|
authInfo := authorized.GetInfo(c)
|
||||||
if authInfo == nil || authInfo.UserID == "" {
|
if authInfo == nil || authInfo.UserID == "" {
|
||||||
errorResp := &response.ErrorResponse{
|
errorResp := &response.ErrorResponse{
|
||||||
Code: response.ErrInvalidClient.Code,
|
Code: response.ErrInvalidClient.Code,
|
||||||
|
|
@ -312,6 +312,61 @@ func GinTeamUpdate(c *gin.Context) {
|
||||||
response.RespondWithSuccess(c, http.StatusOK, team)
|
response.RespondWithSuccess(c, http.StatusOK, team)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GinTeamCurrent handles GET /teams/current - Get current team
|
||||||
|
func GinTeamCurrent(c *gin.Context) {
|
||||||
|
|
||||||
|
authInfo := authorized.GetInfo(c)
|
||||||
|
if authInfo == nil || authInfo.UserID == "" {
|
||||||
|
errorResp := &response.ErrorResponse{
|
||||||
|
Code: response.ErrInvalidClient.Code,
|
||||||
|
ErrorDescription: "User not authenticated",
|
||||||
|
}
|
||||||
|
response.RespondWithError(c, response.StatusUnauthorized, errorResp)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get current team
|
||||||
|
teamID := authInfo.TeamID
|
||||||
|
|
||||||
|
// If no team ID, get the user teams from provider first
|
||||||
|
if teamID == "" {
|
||||||
|
// Get user teams
|
||||||
|
teams, err := getOwnerTeams(c.Request.Context(), authInfo.UserID)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Failed to get owner teams: %v", err)
|
||||||
|
errorResp := &response.ErrorResponse{
|
||||||
|
Code: response.ErrServerError.Code,
|
||||||
|
ErrorDescription: "Failed to get owner teams",
|
||||||
|
}
|
||||||
|
response.RespondWithError(c, response.StatusInternalServerError, errorResp)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(teams) == 0 {
|
||||||
|
errorResp := &response.ErrorResponse{
|
||||||
|
Code: response.ErrInvalidRequest.Code,
|
||||||
|
ErrorDescription: "No owner team found for user",
|
||||||
|
}
|
||||||
|
response.RespondWithError(c, response.StatusNotFound, errorResp)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
teamID = teams[0]["team_id"].(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get team details
|
||||||
|
team, err := teamGet(c.Request.Context(), authInfo.UserID, teamID)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Failed to get team details: %v", err)
|
||||||
|
errorResp := &response.ErrorResponse{
|
||||||
|
Code: response.ErrServerError.Code,
|
||||||
|
ErrorDescription: "Failed to get team details",
|
||||||
|
}
|
||||||
|
response.RespondWithError(c, response.StatusInternalServerError, errorResp)
|
||||||
|
}
|
||||||
|
|
||||||
|
response.RespondWithSuccess(c, http.StatusOK, team)
|
||||||
|
}
|
||||||
|
|
||||||
// GinTeamSelection handles POST /teams/select - Select a team and issue tokens with team_id
|
// GinTeamSelection handles POST /teams/select - Select a team and issue tokens with team_id
|
||||||
func GinTeamSelection(c *gin.Context) {
|
func GinTeamSelection(c *gin.Context) {
|
||||||
// Get authorized user info
|
// Get authorized user info
|
||||||
|
|
@ -672,10 +727,14 @@ func teamGet(ctx context.Context, userID, teamID string) (maps.MapStrAny, error)
|
||||||
return nil, fmt.Errorf("failed to retrieve team details: %w", err)
|
return nil, fmt.Errorf("failed to retrieve team details: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if user owns this team
|
// Validate if user is a member of the team
|
||||||
ownerID := toString(teamData["owner_id"])
|
exists, err := provider.MemberExists(ctx, teamID, userID)
|
||||||
if ownerID != userID {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("access denied: user does not own this team")
|
return nil, fmt.Errorf("failed to retrieve team member record: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !exists {
|
||||||
|
return nil, fmt.Errorf("user is not a member of this team")
|
||||||
}
|
}
|
||||||
|
|
||||||
return teamData, nil
|
return teamData, nil
|
||||||
|
|
@ -922,6 +981,24 @@ func getUserTeams(ctx context.Context, userID string) ([]maps.MapStr, error) {
|
||||||
return teams, nil
|
return teams, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getOwnerTeams gets all teams where the user is the owner
|
||||||
|
func getOwnerTeams(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 owner team
|
||||||
|
teams, err := provider.GetTeamsByOwner(ctx, userID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to retrieve owner team: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the first team as the owner team
|
||||||
|
return teams, nil
|
||||||
|
}
|
||||||
|
|
||||||
// getUserTeamsCount counts the number of teams a user is a member of
|
// getUserTeamsCount counts the number of teams a user is a member of
|
||||||
func getUserTeamsCount(ctx context.Context, userID string) (int64, error) {
|
func getUserTeamsCount(ctx context.Context, userID string) (int64, error) {
|
||||||
// Get user provider instance
|
// Get user provider instance
|
||||||
|
|
|
||||||
|
|
@ -129,6 +129,9 @@ func attachTeam(group *gin.RouterGroup, oauth types.OAuth) {
|
||||||
team.PUT("/:id", GinTeamUpdate) // PUT /teams/:id - Update team
|
team.PUT("/:id", GinTeamUpdate) // PUT /teams/:id - Update team
|
||||||
team.DELETE("/:id", GinTeamDelete) // DELETE /teams/:id - Delete team
|
team.DELETE("/:id", GinTeamDelete) // DELETE /teams/:id - Delete team
|
||||||
|
|
||||||
|
// Get Current Team
|
||||||
|
team.GET("/current", GinTeamCurrent)
|
||||||
|
|
||||||
// Team Members - Nested resource endpoints
|
// Team Members - Nested resource endpoints
|
||||||
team.GET("/:id/members", GinMemberList) // GET /teams/:id/members - List team members
|
team.GET("/:id/members", GinMemberList) // GET /teams/:id/members - List team members
|
||||||
team.POST("/:id/members", GinMemberCreateDirect) // POST /teams/:id/members - Add team member
|
team.POST("/:id/members", GinMemberCreateDirect) // POST /teams/:id/members - Add team member
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue