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

     1  // Copyright 2023 The Gitea Authors. All rights reserved.
     2  // SPDX-License-Identifier: MIT
     3  
     4  package repo
     5  
     6  import (
     7  	"net/http"
     8  
     9  	issues_model "code.gitea.io/gitea/models/issues"
    10  	"code.gitea.io/gitea/modules/context"
    11  	api "code.gitea.io/gitea/modules/structs"
    12  	"code.gitea.io/gitea/services/convert"
    13  )
    14  
    15  // PinIssue pins a issue
    16  func PinIssue(ctx *context.APIContext) {
    17  	// swagger:operation POST /repos/{owner}/{repo}/issues/{index}/pin issue pinIssue
    18  	// ---
    19  	// summary: Pin an Issue
    20  	// parameters:
    21  	// - name: owner
    22  	//   in: path
    23  	//   description: owner of the repo
    24  	//   type: string
    25  	//   required: true
    26  	// - name: repo
    27  	//   in: path
    28  	//   description: name of the repo
    29  	//   type: string
    30  	//   required: true
    31  	// - name: index
    32  	//   in: path
    33  	//   description: index of issue to pin
    34  	//   type: integer
    35  	//   format: int64
    36  	//   required: true
    37  	// responses:
    38  	//   "204":
    39  	//     "$ref": "#/responses/empty"
    40  	//   "403":
    41  	//     "$ref": "#/responses/forbidden"
    42  	//   "404":
    43  	//     "$ref": "#/responses/notFound"
    44  	issue, err := issues_model.GetIssueByIndex(ctx, ctx.Repo.Repository.ID, ctx.ParamsInt64(":index"))
    45  	if err != nil {
    46  		if issues_model.IsErrIssueNotExist(err) {
    47  			ctx.NotFound()
    48  		} else if issues_model.IsErrIssueMaxPinReached(err) {
    49  			ctx.Error(http.StatusBadRequest, "MaxPinReached", err)
    50  		} else {
    51  			ctx.Error(http.StatusInternalServerError, "GetIssueByIndex", err)
    52  		}
    53  		return
    54  	}
    55  
    56  	// If we don't do this, it will crash when trying to add the pin event to the comment history
    57  	err = issue.LoadRepo(ctx)
    58  	if err != nil {
    59  		ctx.Error(http.StatusInternalServerError, "LoadRepo", err)
    60  		return
    61  	}
    62  
    63  	err = issue.Pin(ctx, ctx.Doer)
    64  	if err != nil {
    65  		ctx.Error(http.StatusInternalServerError, "PinIssue", err)
    66  		return
    67  	}
    68  
    69  	ctx.Status(http.StatusNoContent)
    70  }
    71  
    72  // UnpinIssue unpins a Issue
    73  func UnpinIssue(ctx *context.APIContext) {
    74  	// swagger:operation DELETE /repos/{owner}/{repo}/issues/{index}/pin issue unpinIssue
    75  	// ---
    76  	// summary: Unpin an Issue
    77  	// parameters:
    78  	// - name: owner
    79  	//   in: path
    80  	//   description: owner of the repo
    81  	//   type: string
    82  	//   required: true
    83  	// - name: repo
    84  	//   in: path
    85  	//   description: name of the repo
    86  	//   type: string
    87  	//   required: true
    88  	// - name: index
    89  	//   in: path
    90  	//   description: index of issue to unpin
    91  	//   type: integer
    92  	//   format: int64
    93  	//   required: true
    94  	// responses:
    95  	//   "204":
    96  	//     "$ref": "#/responses/empty"
    97  	//   "403":
    98  	//     "$ref": "#/responses/forbidden"
    99  	//   "404":
   100  	//     "$ref": "#/responses/notFound"
   101  	issue, err := issues_model.GetIssueByIndex(ctx, ctx.Repo.Repository.ID, ctx.ParamsInt64(":index"))
   102  	if err != nil {
   103  		if issues_model.IsErrIssueNotExist(err) {
   104  			ctx.NotFound()
   105  		} else {
   106  			ctx.Error(http.StatusInternalServerError, "GetIssueByIndex", err)
   107  		}
   108  		return
   109  	}
   110  
   111  	// If we don't do this, it will crash when trying to add the unpin event to the comment history
   112  	err = issue.LoadRepo(ctx)
   113  	if err != nil {
   114  		ctx.Error(http.StatusInternalServerError, "LoadRepo", err)
   115  		return
   116  	}
   117  
   118  	err = issue.Unpin(ctx, ctx.Doer)
   119  	if err != nil {
   120  		ctx.Error(http.StatusInternalServerError, "UnpinIssue", err)
   121  		return
   122  	}
   123  
   124  	ctx.Status(http.StatusNoContent)
   125  }
   126  
   127  // MoveIssuePin moves a pinned Issue to a new Position
   128  func MoveIssuePin(ctx *context.APIContext) {
   129  	// swagger:operation PATCH /repos/{owner}/{repo}/issues/{index}/pin/{position} issue moveIssuePin
   130  	// ---
   131  	// summary: Moves the Pin to the given Position
   132  	// parameters:
   133  	// - name: owner
   134  	//   in: path
   135  	//   description: owner of the repo
   136  	//   type: string
   137  	//   required: true
   138  	// - name: repo
   139  	//   in: path
   140  	//   description: name of the repo
   141  	//   type: string
   142  	//   required: true
   143  	// - name: index
   144  	//   in: path
   145  	//   description: index of issue
   146  	//   type: integer
   147  	//   format: int64
   148  	//   required: true
   149  	// - name: position
   150  	//   in: path
   151  	//   description: the new position
   152  	//   type: integer
   153  	//   format: int64
   154  	//   required: true
   155  	// responses:
   156  	//   "204":
   157  	//     "$ref": "#/responses/empty"
   158  	//   "403":
   159  	//     "$ref": "#/responses/forbidden"
   160  	//   "404":
   161  	//     "$ref": "#/responses/notFound"
   162  	issue, err := issues_model.GetIssueByIndex(ctx, ctx.Repo.Repository.ID, ctx.ParamsInt64(":index"))
   163  	if err != nil {
   164  		if issues_model.IsErrIssueNotExist(err) {
   165  			ctx.NotFound()
   166  		} else {
   167  			ctx.Error(http.StatusInternalServerError, "GetIssueByIndex", err)
   168  		}
   169  		return
   170  	}
   171  
   172  	err = issue.MovePin(ctx, int(ctx.ParamsInt64(":position")))
   173  	if err != nil {
   174  		ctx.Error(http.StatusInternalServerError, "MovePin", err)
   175  		return
   176  	}
   177  
   178  	ctx.Status(http.StatusNoContent)
   179  }
   180  
   181  // ListPinnedIssues returns a list of all pinned Issues
   182  func ListPinnedIssues(ctx *context.APIContext) {
   183  	// swagger:operation GET /repos/{owner}/{repo}/issues/pinned repository repoListPinnedIssues
   184  	// ---
   185  	// summary: List a repo's pinned issues
   186  	// produces:
   187  	// - application/json
   188  	// parameters:
   189  	// - name: owner
   190  	//   in: path
   191  	//   description: owner of the repo
   192  	//   type: string
   193  	//   required: true
   194  	// - name: repo
   195  	//   in: path
   196  	//   description: name of the repo
   197  	//   type: string
   198  	//   required: true
   199  	// responses:
   200  	//   "200":
   201  	//     "$ref": "#/responses/IssueList"
   202  	//   "404":
   203  	//     "$ref": "#/responses/notFound"
   204  	issues, err := issues_model.GetPinnedIssues(ctx, ctx.Repo.Repository.ID, false)
   205  	if err != nil {
   206  		ctx.Error(http.StatusInternalServerError, "LoadPinnedIssues", err)
   207  		return
   208  	}
   209  
   210  	ctx.JSON(http.StatusOK, convert.ToAPIIssueList(ctx, issues))
   211  }
   212  
   213  // ListPinnedPullRequests returns a list of all pinned PRs
   214  func ListPinnedPullRequests(ctx *context.APIContext) {
   215  	// swagger:operation GET /repos/{owner}/{repo}/pulls/pinned repository repoListPinnedPullRequests
   216  	// ---
   217  	// summary: List a repo's pinned pull requests
   218  	// produces:
   219  	// - application/json
   220  	// parameters:
   221  	// - name: owner
   222  	//   in: path
   223  	//   description: owner of the repo
   224  	//   type: string
   225  	//   required: true
   226  	// - name: repo
   227  	//   in: path
   228  	//   description: name of the repo
   229  	//   type: string
   230  	//   required: true
   231  	// responses:
   232  	//   "200":
   233  	//     "$ref": "#/responses/PullRequestList"
   234  	//   "404":
   235  	//     "$ref": "#/responses/notFound"
   236  	issues, err := issues_model.GetPinnedIssues(ctx, ctx.Repo.Repository.ID, true)
   237  	if err != nil {
   238  		ctx.Error(http.StatusInternalServerError, "LoadPinnedPullRequests", err)
   239  		return
   240  	}
   241  
   242  	apiPrs := make([]*api.PullRequest, len(issues))
   243  	for i, currentIssue := range issues {
   244  		pr, err := currentIssue.GetPullRequest()
   245  		if err != nil {
   246  			ctx.Error(http.StatusInternalServerError, "GetPullRequest", err)
   247  			return
   248  		}
   249  
   250  		if err = pr.LoadIssue(ctx); err != nil {
   251  			ctx.Error(http.StatusInternalServerError, "LoadIssue", err)
   252  			return
   253  		}
   254  
   255  		if err = pr.LoadAttributes(ctx); err != nil {
   256  			ctx.Error(http.StatusInternalServerError, "LoadAttributes", err)
   257  			return
   258  		}
   259  
   260  		if err = pr.LoadBaseRepo(ctx); err != nil {
   261  			ctx.Error(http.StatusInternalServerError, "LoadBaseRepo", err)
   262  			return
   263  		}
   264  
   265  		if err = pr.LoadHeadRepo(ctx); err != nil {
   266  			ctx.Error(http.StatusInternalServerError, "LoadHeadRepo", err)
   267  			return
   268  		}
   269  
   270  		apiPrs[i] = convert.ToAPIPullRequest(ctx, pr, ctx.Doer)
   271  	}
   272  
   273  	ctx.JSON(http.StatusOK, &apiPrs)
   274  }
   275  
   276  // AreNewIssuePinsAllowed returns if new issues pins are allowed
   277  func AreNewIssuePinsAllowed(ctx *context.APIContext) {
   278  	// swagger:operation GET /repos/{owner}/{repo}/new_pin_allowed repository repoNewPinAllowed
   279  	// ---
   280  	// summary: Returns if new Issue Pins are allowed
   281  	// produces:
   282  	// - application/json
   283  	// parameters:
   284  	// - name: owner
   285  	//   in: path
   286  	//   description: owner of the repo
   287  	//   type: string
   288  	//   required: true
   289  	// - name: repo
   290  	//   in: path
   291  	//   description: name of the repo
   292  	//   type: string
   293  	//   required: true
   294  	// responses:
   295  	//   "200":
   296  	//     "$ref": "#/responses/RepoNewIssuePinsAllowed"
   297  	//   "404":
   298  	//     "$ref": "#/responses/notFound"
   299  	pinsAllowed := api.NewIssuePinsAllowed{}
   300  	var err error
   301  
   302  	pinsAllowed.Issues, err = issues_model.IsNewPinAllowed(ctx, ctx.Repo.Repository.ID, false)
   303  	if err != nil {
   304  		ctx.Error(http.StatusInternalServerError, "IsNewIssuePinAllowed", err)
   305  		return
   306  	}
   307  
   308  	pinsAllowed.PullRequests, err = issues_model.IsNewPinAllowed(ctx, ctx.Repo.Repository.ID, true)
   309  	if err != nil {
   310  		ctx.Error(http.StatusInternalServerError, "IsNewPullRequestPinAllowed", err)
   311  		return
   312  	}
   313  
   314  	ctx.JSON(http.StatusOK, pinsAllowed)
   315  }