Update team model and creation logic to support role management

- Added role_id field to the team model for specifying team owner roles.
- Enhanced team creation logic to set default role_id based on team configuration if not provided.
- Updated tests to reflect changes in team type and role handling, ensuring accurate assertions.
- Improved documentation for team configuration to clarify default role settings for team creators.
This commit is contained in:
Max 2025-10-20 17:00:33 +08:00
parent 0bd6bdcda3
commit b1db5505ea
5 changed files with 203 additions and 165 deletions

File diff suppressed because one or more lines are too long

View file

@ -86,7 +86,7 @@ func TestTeamBasicOperations(t *testing.T) {
OwnerID: ownerUserID, OwnerID: ownerUserID,
Status: "active", Status: "active",
Type: "corporation", Type: "corporation",
TypeID: "business", TypeID: "free",
Metadata: map[string]interface{}{"test": true, "uuid": testUUID}, Metadata: map[string]interface{}{"test": true, "uuid": testUUID},
} }
@ -126,6 +126,7 @@ func TestTeamBasicOperations(t *testing.T) {
assert.Equal(t, testTeam.Name, team["name"]) assert.Equal(t, testTeam.Name, team["name"])
assert.Equal(t, testTeam.DisplayName, team["display_name"]) assert.Equal(t, testTeam.DisplayName, team["display_name"])
assert.Equal(t, testTeam.OwnerID, team["owner_id"]) assert.Equal(t, testTeam.OwnerID, team["owner_id"])
assert.Equal(t, testTeam.TypeID, team["type_id"])
}) })
// Test GetTeamDetail // Test GetTeamDetail

View file

@ -692,9 +692,7 @@ func teamCreate(ctx context.Context, userID string, teamData maps.MapStrAny) (st
teamData["created_at"] = time.Now() teamData["created_at"] = time.Now()
teamData["updated_at"] = time.Now() teamData["updated_at"] = time.Now()
// Set default type_id from team config if not provided // Get team config for setting defaults
if _, hasType := teamData["type_id"]; !hasType {
// Try to get locale from team data
locale := "" locale := ""
if localeVal, ok := teamData["locale"].(string); ok && localeVal != "" { if localeVal, ok := teamData["locale"].(string); ok && localeVal != "" {
locale = strings.TrimSpace(strings.ToLower(localeVal)) locale = strings.TrimSpace(strings.ToLower(localeVal))
@ -714,12 +712,22 @@ func teamCreate(ctx context.Context, userID string, teamData maps.MapStrAny) (st
} }
} }
// Set default type_id from team config if not provided
if _, hasType := teamData["type_id"]; !hasType {
// Apply default type from config if available // Apply default type from config if available
if teamConfig != nil && teamConfig.Type != "" { if teamConfig != nil && teamConfig.Type != "" {
teamData["type_id"] = teamConfig.Type teamData["type_id"] = teamConfig.Type
} }
} }
// Set default role_id from team config if not provided
if _, hasRole := teamData["role_id"]; !hasRole {
// Apply default role from config if available
if teamConfig != nil && teamConfig.Role != "" {
teamData["role_id"] = teamConfig.Role
}
}
// Clean up: remove locale from team data as it's not stored in database // Clean up: remove locale from team data as it's not stored in database
delete(teamData, "locale") delete(teamData, "locale")
@ -729,12 +737,18 @@ func teamCreate(ctx context.Context, userID string, teamData maps.MapStrAny) (st
return "", fmt.Errorf("failed to create team: %w", err) return "", fmt.Errorf("failed to create team: %w", err)
} }
// Determine owner member role_id from team config
ownerRoleID := "owner" // fallback default
if teamConfig != nil && teamConfig.Role != "" {
ownerRoleID = teamConfig.Role
}
// Add the creator as an owner member of the team // Add the creator as an owner member of the team
ownerMemberData := maps.MapStrAny{ ownerMemberData := maps.MapStrAny{
"team_id": teamID, "team_id": teamID,
"user_id": userID, "user_id": userID,
"member_type": "user", "member_type": "user",
"role_id": "owner", "role_id": ownerRoleID,
"status": "active", "status": "active",
"joined_at": time.Now(), "joined_at": time.Now(),
"created_at": time.Now(), "created_at": time.Now(),

View file

@ -503,7 +503,8 @@ type CreateInvitationRequest struct {
type TeamConfig struct { type TeamConfig struct {
Roles []*TeamRole `json:"roles,omitempty"` Roles []*TeamRole `json:"roles,omitempty"`
Invite *InviteConfig `json:"invite,omitempty"` Invite *InviteConfig `json:"invite,omitempty"`
Type string `json:"type,omitempty"` // Default type for new teams Type string `json:"type,omitempty"` // Default subscription type for new teams
Role string `json:"role,omitempty"` // Default user role for team creator
} }
// TeamRole represents a team role configuration // TeamRole represents a team role configuration
@ -513,6 +514,7 @@ type TeamRole struct {
Description string `json:"description"` Description string `json:"description"`
Default bool `json:"default"` // Whether this role is the default role Default bool `json:"default"` // Whether this role is the default role
Hidden bool `json:"hidden"` // Whether this role is hidden from UI Hidden bool `json:"hidden"` // Whether this role is hidden from UI
IsOwner bool `json:"is_owner"` // Whether this role represents team owner (deprecated, use config.Role instead)
} }
// InviteConfig represents the invitation configuration // InviteConfig represents the invitation configuration

View file

@ -270,6 +270,15 @@
"index": true, "index": true,
"nullable": false "nullable": false
}, },
{
"name": "role_id",
"type": "string",
"label": "Role ID",
"comment": "Team owner role identifier (references role.role_id)",
"length": 50,
"nullable": true,
"index": true
},
{ {
"name": "type_id", "name": "type_id",
"type": "string", "type": "string",
@ -439,6 +448,12 @@
"columns": ["type_id", "status"], "columns": ["type_id", "status"],
"type": "index", "type": "index",
"comment": "Index on team type and status for limits and permissions" "comment": "Index on team type and status for limits and permissions"
},
{
"name": "idx_team_role_type",
"columns": ["role_id", "type_id"],
"type": "index",
"comment": "Index on team owner role and type for permission queries"
} }
], ],
"relations": { "relations": {
@ -448,6 +463,12 @@
"key": "owner_id", "key": "owner_id",
"foreign": "user_id" "foreign": "user_id"
}, },
"role": {
"type": "hasOne",
"model": "__yao.role",
"key": "role_id",
"foreign": "role_id"
},
"user_type": { "user_type": {
"type": "hasOne", "type": "hasOne",
"model": "__yao.user.type", "model": "__yao.user.type",