// Copyright 2026 The Gitea Authors. All rights reserved. // SPDX-License-Identifier: MIT package organization import ( "context" "code.gitea.io/gitea/models/db" user_model "code.gitea.io/gitea/models/user" ) const ( // ProfileRepoName is the name of the special profile repository ProfileRepoName = ".profile" // ProfileReadmePath is the path to the profile README ProfileReadmePath = "README.md" // ProfileAssetsPath is the path to profile assets ProfileAssetsPath = "assets/" // ProfileStylePath is the path to custom CSS ProfileStylePath = "style.css" ) // PublicMember represents a public member of an organization for display type PublicMember struct { *user_model.User Role string // "Owner", "Admin", "Member" } // GetPublicOrgMembers returns public members of an organization func GetPublicOrgMembers(ctx context.Context, orgID int64, limit int) ([]*PublicMember, int64, error) { // Count total public members total, err := db.GetEngine(ctx). Where("org_id = ? AND is_public = ?", orgID, true). Count(new(OrgUser)) if err != nil { return nil, 0, err } // Get public org users orgUsers := make([]*OrgUser, 0, limit) sess := db.GetEngine(ctx). Where("org_id = ? AND is_public = ?", orgID, true) if limit > 0 { sess = sess.Limit(limit) } if err := sess.Find(&orgUsers); err != nil { return nil, 0, err } if len(orgUsers) == 0 { return []*PublicMember{}, total, nil } // Get user IDs userIDs := make([]int64, len(orgUsers)) for i, ou := range orgUsers { userIDs[i] = ou.UID } // Load users users, err := user_model.GetUsersByIDs(ctx, userIDs) if err != nil { return nil, 0, err } userMap := make(map[int64]*user_model.User) for _, u := range users { userMap[u.ID] = u } // Get owners team to determine roles org, err := GetOrgByID(ctx, orgID) if err != nil { return nil, 0, err } ownersTeam, err := org.GetOwnerTeam(ctx) if err != nil { return nil, 0, err } ownerIDs := make(map[int64]bool) if ownersTeam != nil { if err := ownersTeam.LoadMembers(ctx); err != nil { return nil, 0, err } for _, m := range ownersTeam.Members { ownerIDs[m.ID] = true } } // Build result with roles members := make([]*PublicMember, 0, len(orgUsers)) for _, ou := range orgUsers { user := userMap[ou.UID] if user == nil { continue } role := "Member" if ownerIDs[ou.UID] { role = "Owner" } else { // Check if admin (has admin access to any team) isAdmin, _ := IsOrganizationAdmin(ctx, orgID, ou.UID) if isAdmin { role = "Admin" } } members = append(members, &PublicMember{ User: user, Role: role, }) } return members, total, nil } // SetMemberPublicVisibility sets the public visibility of a member func SetMemberPublicVisibility(ctx context.Context, orgID, userID int64, isPublic bool) error { _, err := db.GetEngine(ctx). Where("org_id = ? AND uid = ?", orgID, userID). Cols("is_public"). Update(&OrgUser{IsPublic: isPublic}) return err } // GetMemberPublicVisibility gets the public visibility status of a member func GetMemberPublicVisibility(ctx context.Context, orgID, userID int64) (bool, error) { orgUser := new(OrgUser) has, err := db.GetEngine(ctx). Where("org_id = ? AND uid = ?", orgID, userID). Get(orgUser) if err != nil { return false, err } if !has { return false, nil } return orgUser.IsPublic, nil } // OrgOverviewStats represents statistics for the organization overview type OrgOverviewStats struct { MemberCount int64 RepoCount int64 PublicRepoCount int64 TeamCount int64 } // GetOrgMemberAndTeamCounts returns member and team counts for an organization func GetOrgMemberAndTeamCounts(ctx context.Context, orgID int64) (memberCount, teamCount int64, err error) { memberCount, err = db.GetEngine(ctx). Where("org_id = ?", orgID). Count(new(OrgUser)) if err != nil { return 0, 0, err } teamCount, err = db.GetEngine(ctx). Where("org_id = ?", orgID). Count(new(Team)) if err != nil { return 0, 0, err } return memberCount, teamCount, nil }