// Copyright 2026 The Gitea Authors. All rights reserved. // SPDX-License-Identifier: MIT package org import ( "net/http" "code.gitea.io/gitea/models/organization" user_model "code.gitea.io/gitea/models/user" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/services/context" "code.gitea.io/gitea/services/convert" org_service "code.gitea.io/gitea/services/org" ) // GetOverview returns the organization overview for the profile page func GetOverview(ctx *context.APIContext) { // swagger:operation GET /orgs/{org}/overview organization orgGetOverview // --- // summary: Get organization overview // produces: // - application/json // parameters: // - name: org // in: path // description: name of the organization // type: string // required: true // responses: // "200": // "$ref": "#/responses/OrgOverview" // "404": // "$ref": "#/responses/notFound" org := ctx.Org.Organization // Get pinned repos pinnedRepos, err := org_service.GetOrgPinnedReposWithDetails(ctx, org.ID) if err != nil { ctx.APIErrorInternal(err) return } // Get pinned groups pinnedGroups, err := organization.GetOrgPinnedGroups(ctx, org.ID) if err != nil { ctx.APIErrorInternal(err) return } // Get public members (limit to 12 for overview) publicMembers, totalMembers, err := organization.GetPublicOrgMembers(ctx, org.ID, 12) if err != nil { ctx.APIErrorInternal(err) return } // Get stats stats, err := org_service.GetOrgOverviewStats(ctx, org.ID) if err != nil { ctx.APIErrorInternal(err) return } // Build API response apiPinnedRepos := make([]*api.OrgPinnedRepo, 0, len(pinnedRepos)) for _, p := range pinnedRepos { if p.Repo == nil { continue } apiPinnedRepos = append(apiPinnedRepos, convertOrgPinnedRepo(ctx, p)) } apiPinnedGroups := make([]*api.OrgPinnedGroup, len(pinnedGroups)) for i, g := range pinnedGroups { apiPinnedGroups[i] = convertOrgPinnedGroup(g) } apiPublicMembers := make([]*api.OrgPublicMember, len(publicMembers)) for i, m := range publicMembers { apiPublicMembers[i] = &api.OrgPublicMember{ User: convert.ToUser(ctx, m.User, ctx.Doer), Role: m.Role, } } overview := &api.OrgOverview{ Organization: convert.ToOrganization(ctx, org), PinnedRepos: apiPinnedRepos, PinnedGroups: apiPinnedGroups, PublicMembers: apiPublicMembers, TotalMembers: totalMembers, Stats: &api.OrgOverviewStats{ MemberCount: stats.MemberCount, RepoCount: stats.RepoCount, PublicRepoCount: stats.PublicRepoCount, TeamCount: stats.TeamCount, }, } ctx.JSON(http.StatusOK, overview) } // ListPublicMembersWithRoles returns the public members of an organization with their roles func ListPublicMembersWithRoles(ctx *context.APIContext) { // swagger:operation GET /orgs/{org}/public_members/roles organization orgListPublicMembersWithRoles // --- // summary: List an organization's public members with their roles // produces: // - application/json // parameters: // - name: org // in: path // description: name of the organization // type: string // required: true // - name: page // in: query // description: page number of results to return (1-based) // type: integer // - name: limit // in: query // description: page size of results // type: integer // responses: // "200": // "$ref": "#/responses/OrgPublicMemberList" // "404": // "$ref": "#/responses/notFound" // Get all public members (no limit) publicMembers, total, err := organization.GetPublicOrgMembers(ctx, ctx.Org.Organization.ID, 0) if err != nil { ctx.APIErrorInternal(err) return } apiPublicMembers := make([]*api.OrgPublicMember, len(publicMembers)) for i, m := range publicMembers { apiPublicMembers[i] = &api.OrgPublicMember{ User: convert.ToUser(ctx, m.User, ctx.Doer), Role: m.Role, } } ctx.SetTotalCountHeader(total) ctx.JSON(http.StatusOK, apiPublicMembers) } // SetPublicMembership sets the public visibility of a member func SetPublicMembership(ctx *context.APIContext) { // swagger:operation PUT /orgs/{org}/public_members/{username} organization orgSetPublicMembership // --- // summary: Set public membership visibility for a user // produces: // - application/json // parameters: // - name: org // in: path // description: name of the organization // type: string // required: true // - name: username // in: path // description: username of the user // type: string // required: true // responses: // "204": // "$ref": "#/responses/empty" // "403": // "$ref": "#/responses/forbidden" // "404": // "$ref": "#/responses/notFound" username := ctx.PathParam("username") // Users can only change their own visibility if ctx.Doer.Name != username { isOwner, err := organization.IsOrganizationOwner(ctx, ctx.Org.Organization.ID, ctx.Doer.ID) if err != nil { ctx.APIErrorInternal(err) return } if !isOwner { ctx.APIError(http.StatusForbidden, "You can only change your own public membership visibility") return } } // Get the user user, err := user_model.GetUserByName(ctx, username) if err != nil { if user_model.IsErrUserNotExist(err) { ctx.APIErrorNotFound("GetUserByName", err) return } ctx.APIErrorInternal(err) return } // Verify user is a member isMember, err := organization.IsOrganizationMember(ctx, ctx.Org.Organization.ID, user.ID) if err != nil { ctx.APIErrorInternal(err) return } if !isMember { ctx.APIErrorNotFound() return } if err := organization.SetMemberPublicVisibility(ctx, ctx.Org.Organization.ID, user.ID, true); err != nil { ctx.APIErrorInternal(err) return } ctx.Status(http.StatusNoContent) } // RemovePublicMembership removes the public visibility of a member func RemovePublicMembership(ctx *context.APIContext) { // swagger:operation DELETE /orgs/{org}/public_members/{username} organization orgRemovePublicMembership // --- // summary: Remove public membership visibility for a user // produces: // - application/json // parameters: // - name: org // in: path // description: name of the organization // type: string // required: true // - name: username // in: path // description: username of the user // type: string // required: true // responses: // "204": // "$ref": "#/responses/empty" // "403": // "$ref": "#/responses/forbidden" // "404": // "$ref": "#/responses/notFound" username := ctx.PathParam("username") // Users can only change their own visibility if ctx.Doer.Name != username { isOwner, err := organization.IsOrganizationOwner(ctx, ctx.Org.Organization.ID, ctx.Doer.ID) if err != nil { ctx.APIErrorInternal(err) return } if !isOwner { ctx.APIError(http.StatusForbidden, "You can only change your own public membership visibility") return } } // Get the user user, err := user_model.GetUserByName(ctx, username) if err != nil { if user_model.IsErrUserNotExist(err) { ctx.APIErrorNotFound("GetUserByName", err) return } ctx.APIErrorInternal(err) return } // Verify user is a member isMember, err := organization.IsOrganizationMember(ctx, ctx.Org.Organization.ID, user.ID) if err != nil { ctx.APIErrorInternal(err) return } if !isMember { ctx.APIErrorNotFound() return } if err := organization.SetMemberPublicVisibility(ctx, ctx.Org.Organization.ID, user.ID, false); err != nil { ctx.APIErrorInternal(err) return } ctx.Status(http.StatusNoContent) }