code.gitea.io/gitea@v1.21.7/routers/api/v1/repo/teams.go (about)

     1  // Copyright 2020 The Gitea Authors. All rights reserved.
     2  // SPDX-License-Identifier: MIT
     3  
     4  package repo
     5  
     6  import (
     7  	"fmt"
     8  	"net/http"
     9  
    10  	"code.gitea.io/gitea/models/organization"
    11  	"code.gitea.io/gitea/modules/context"
    12  	"code.gitea.io/gitea/services/convert"
    13  	org_service "code.gitea.io/gitea/services/org"
    14  	repo_service "code.gitea.io/gitea/services/repository"
    15  )
    16  
    17  // ListTeams list a repository's teams
    18  func ListTeams(ctx *context.APIContext) {
    19  	// swagger:operation GET /repos/{owner}/{repo}/teams repository repoListTeams
    20  	// ---
    21  	// summary: List a repository's teams
    22  	// produces:
    23  	// - application/json
    24  	// parameters:
    25  	// - name: owner
    26  	//   in: path
    27  	//   description: owner of the repo
    28  	//   type: string
    29  	//   required: true
    30  	// - name: repo
    31  	//   in: path
    32  	//   description: name of the repo
    33  	//   type: string
    34  	//   required: true
    35  	// responses:
    36  	//   "200":
    37  	//     "$ref": "#/responses/TeamList"
    38  	//   "404":
    39  	//     "$ref": "#/responses/notFound"
    40  
    41  	if !ctx.Repo.Owner.IsOrganization() {
    42  		ctx.Error(http.StatusMethodNotAllowed, "noOrg", "repo is not owned by an organization")
    43  		return
    44  	}
    45  
    46  	teams, err := organization.GetRepoTeams(ctx, ctx.Repo.Repository)
    47  	if err != nil {
    48  		ctx.InternalServerError(err)
    49  		return
    50  	}
    51  
    52  	apiTeams, err := convert.ToTeams(ctx, teams, false)
    53  	if err != nil {
    54  		ctx.InternalServerError(err)
    55  		return
    56  	}
    57  
    58  	ctx.JSON(http.StatusOK, apiTeams)
    59  }
    60  
    61  // IsTeam check if a team is assigned to a repository
    62  func IsTeam(ctx *context.APIContext) {
    63  	// swagger:operation GET /repos/{owner}/{repo}/teams/{team} repository repoCheckTeam
    64  	// ---
    65  	// summary: Check if a team is assigned to a repository
    66  	// produces:
    67  	// - application/json
    68  	// parameters:
    69  	// - name: owner
    70  	//   in: path
    71  	//   description: owner of the repo
    72  	//   type: string
    73  	//   required: true
    74  	// - name: repo
    75  	//   in: path
    76  	//   description: name of the repo
    77  	//   type: string
    78  	//   required: true
    79  	// - name: team
    80  	//   in: path
    81  	//   description: team name
    82  	//   type: string
    83  	//   required: true
    84  	// responses:
    85  	//   "200":
    86  	//     "$ref": "#/responses/Team"
    87  	//   "404":
    88  	//     "$ref": "#/responses/notFound"
    89  	//   "405":
    90  	//     "$ref": "#/responses/error"
    91  
    92  	if !ctx.Repo.Owner.IsOrganization() {
    93  		ctx.Error(http.StatusMethodNotAllowed, "noOrg", "repo is not owned by an organization")
    94  		return
    95  	}
    96  
    97  	team := getTeamByParam(ctx)
    98  	if team == nil {
    99  		return
   100  	}
   101  
   102  	if repo_service.HasRepository(ctx, team, ctx.Repo.Repository.ID) {
   103  		apiTeam, err := convert.ToTeam(ctx, team)
   104  		if err != nil {
   105  			ctx.InternalServerError(err)
   106  			return
   107  		}
   108  		ctx.JSON(http.StatusOK, apiTeam)
   109  		return
   110  	}
   111  
   112  	ctx.NotFound()
   113  }
   114  
   115  // AddTeam add a team to a repository
   116  func AddTeam(ctx *context.APIContext) {
   117  	// swagger:operation PUT /repos/{owner}/{repo}/teams/{team} repository repoAddTeam
   118  	// ---
   119  	// summary: Add a team to a repository
   120  	// produces:
   121  	// - application/json
   122  	// parameters:
   123  	// - name: owner
   124  	//   in: path
   125  	//   description: owner of the repo
   126  	//   type: string
   127  	//   required: true
   128  	// - name: repo
   129  	//   in: path
   130  	//   description: name of the repo
   131  	//   type: string
   132  	//   required: true
   133  	// - name: team
   134  	//   in: path
   135  	//   description: team name
   136  	//   type: string
   137  	//   required: true
   138  	// responses:
   139  	//   "204":
   140  	//     "$ref": "#/responses/empty"
   141  	//   "422":
   142  	//     "$ref": "#/responses/validationError"
   143  	//   "405":
   144  	//     "$ref": "#/responses/error"
   145  	//   "404":
   146  	//     "$ref": "#/responses/notFound"
   147  
   148  	changeRepoTeam(ctx, true)
   149  }
   150  
   151  // DeleteTeam delete a team from a repository
   152  func DeleteTeam(ctx *context.APIContext) {
   153  	// swagger:operation DELETE /repos/{owner}/{repo}/teams/{team} repository repoDeleteTeam
   154  	// ---
   155  	// summary: Delete a team from a repository
   156  	// produces:
   157  	// - application/json
   158  	// parameters:
   159  	// - name: owner
   160  	//   in: path
   161  	//   description: owner of the repo
   162  	//   type: string
   163  	//   required: true
   164  	// - name: repo
   165  	//   in: path
   166  	//   description: name of the repo
   167  	//   type: string
   168  	//   required: true
   169  	// - name: team
   170  	//   in: path
   171  	//   description: team name
   172  	//   type: string
   173  	//   required: true
   174  	// responses:
   175  	//   "204":
   176  	//     "$ref": "#/responses/empty"
   177  	//   "422":
   178  	//     "$ref": "#/responses/validationError"
   179  	//   "405":
   180  	//     "$ref": "#/responses/error"
   181  	//   "404":
   182  	//     "$ref": "#/responses/notFound"
   183  
   184  	changeRepoTeam(ctx, false)
   185  }
   186  
   187  func changeRepoTeam(ctx *context.APIContext, add bool) {
   188  	if !ctx.Repo.Owner.IsOrganization() {
   189  		ctx.Error(http.StatusMethodNotAllowed, "noOrg", "repo is not owned by an organization")
   190  	}
   191  	if !ctx.Repo.Owner.RepoAdminChangeTeamAccess && !ctx.Repo.IsOwner() {
   192  		ctx.Error(http.StatusForbidden, "noAdmin", "user is nor repo admin nor owner")
   193  		return
   194  	}
   195  
   196  	team := getTeamByParam(ctx)
   197  	if team == nil {
   198  		return
   199  	}
   200  
   201  	repoHasTeam := repo_service.HasRepository(ctx, team, ctx.Repo.Repository.ID)
   202  	var err error
   203  	if add {
   204  		if repoHasTeam {
   205  			ctx.Error(http.StatusUnprocessableEntity, "alreadyAdded", fmt.Errorf("team '%s' is already added to repo", team.Name))
   206  			return
   207  		}
   208  		err = org_service.TeamAddRepository(ctx, team, ctx.Repo.Repository)
   209  	} else {
   210  		if !repoHasTeam {
   211  			ctx.Error(http.StatusUnprocessableEntity, "notAdded", fmt.Errorf("team '%s' was not added to repo", team.Name))
   212  			return
   213  		}
   214  		err = repo_service.RemoveRepositoryFromTeam(ctx, team, ctx.Repo.Repository.ID)
   215  	}
   216  	if err != nil {
   217  		ctx.InternalServerError(err)
   218  		return
   219  	}
   220  
   221  	ctx.Status(http.StatusNoContent)
   222  }
   223  
   224  func getTeamByParam(ctx *context.APIContext) *organization.Team {
   225  	team, err := organization.GetTeam(ctx, ctx.Repo.Owner.ID, ctx.Params(":team"))
   226  	if err != nil {
   227  		if organization.IsErrTeamNotExist(err) {
   228  			ctx.Error(http.StatusNotFound, "TeamNotExit", err)
   229  			return nil
   230  		}
   231  		ctx.InternalServerError(err)
   232  		return nil
   233  	}
   234  	return team
   235  }