code.gitea.io/gitea@v1.21.7/routers/api/v1/repo/issue_label.go (about) 1 // Copyright 2016 The Gogs Authors. All rights reserved. 2 // Copyright 2018 The Gitea Authors. All rights reserved. 3 // SPDX-License-Identifier: MIT 4 5 package repo 6 7 import ( 8 "net/http" 9 10 issues_model "code.gitea.io/gitea/models/issues" 11 "code.gitea.io/gitea/modules/context" 12 api "code.gitea.io/gitea/modules/structs" 13 "code.gitea.io/gitea/modules/web" 14 "code.gitea.io/gitea/services/convert" 15 issue_service "code.gitea.io/gitea/services/issue" 16 ) 17 18 // ListIssueLabels list all the labels of an issue 19 func ListIssueLabels(ctx *context.APIContext) { 20 // swagger:operation GET /repos/{owner}/{repo}/issues/{index}/labels issue issueGetLabels 21 // --- 22 // summary: Get an issue's labels 23 // produces: 24 // - application/json 25 // parameters: 26 // - name: owner 27 // in: path 28 // description: owner of the repo 29 // type: string 30 // required: true 31 // - name: repo 32 // in: path 33 // description: name of the repo 34 // type: string 35 // required: true 36 // - name: index 37 // in: path 38 // description: index of the issue 39 // type: integer 40 // format: int64 41 // required: true 42 // responses: 43 // "200": 44 // "$ref": "#/responses/LabelList" 45 // "404": 46 // "$ref": "#/responses/notFound" 47 48 issue, err := issues_model.GetIssueByIndex(ctx, ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) 49 if err != nil { 50 if issues_model.IsErrIssueNotExist(err) { 51 ctx.NotFound() 52 } else { 53 ctx.Error(http.StatusInternalServerError, "GetIssueByIndex", err) 54 } 55 return 56 } 57 58 if err := issue.LoadAttributes(ctx); err != nil { 59 ctx.Error(http.StatusInternalServerError, "LoadAttributes", err) 60 return 61 } 62 63 ctx.JSON(http.StatusOK, convert.ToLabelList(issue.Labels, ctx.Repo.Repository, ctx.Repo.Owner)) 64 } 65 66 // AddIssueLabels add labels for an issue 67 func AddIssueLabels(ctx *context.APIContext) { 68 // swagger:operation POST /repos/{owner}/{repo}/issues/{index}/labels issue issueAddLabel 69 // --- 70 // summary: Add a label to an issue 71 // consumes: 72 // - application/json 73 // produces: 74 // - application/json 75 // parameters: 76 // - name: owner 77 // in: path 78 // description: owner of the repo 79 // type: string 80 // required: true 81 // - name: repo 82 // in: path 83 // description: name of the repo 84 // type: string 85 // required: true 86 // - name: index 87 // in: path 88 // description: index of the issue 89 // type: integer 90 // format: int64 91 // required: true 92 // - name: body 93 // in: body 94 // schema: 95 // "$ref": "#/definitions/IssueLabelsOption" 96 // responses: 97 // "200": 98 // "$ref": "#/responses/LabelList" 99 // "403": 100 // "$ref": "#/responses/forbidden" 101 // "404": 102 // "$ref": "#/responses/notFound" 103 104 form := web.GetForm(ctx).(*api.IssueLabelsOption) 105 issue, labels, err := prepareForReplaceOrAdd(ctx, *form) 106 if err != nil { 107 return 108 } 109 110 if err = issue_service.AddLabels(ctx, issue, ctx.Doer, labels); err != nil { 111 ctx.Error(http.StatusInternalServerError, "AddLabels", err) 112 return 113 } 114 115 labels, err = issues_model.GetLabelsByIssueID(ctx, issue.ID) 116 if err != nil { 117 ctx.Error(http.StatusInternalServerError, "GetLabelsByIssueID", err) 118 return 119 } 120 121 ctx.JSON(http.StatusOK, convert.ToLabelList(labels, ctx.Repo.Repository, ctx.Repo.Owner)) 122 } 123 124 // DeleteIssueLabel delete a label for an issue 125 func DeleteIssueLabel(ctx *context.APIContext) { 126 // swagger:operation DELETE /repos/{owner}/{repo}/issues/{index}/labels/{id} issue issueRemoveLabel 127 // --- 128 // summary: Remove a label from an issue 129 // produces: 130 // - application/json 131 // parameters: 132 // - name: owner 133 // in: path 134 // description: owner of the repo 135 // type: string 136 // required: true 137 // - name: repo 138 // in: path 139 // description: name of the repo 140 // type: string 141 // required: true 142 // - name: index 143 // in: path 144 // description: index of the issue 145 // type: integer 146 // format: int64 147 // required: true 148 // - name: id 149 // in: path 150 // description: id of the label to remove 151 // type: integer 152 // format: int64 153 // required: true 154 // responses: 155 // "204": 156 // "$ref": "#/responses/empty" 157 // "403": 158 // "$ref": "#/responses/forbidden" 159 // "404": 160 // "$ref": "#/responses/notFound" 161 // "422": 162 // "$ref": "#/responses/validationError" 163 164 issue, err := issues_model.GetIssueByIndex(ctx, ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) 165 if err != nil { 166 if issues_model.IsErrIssueNotExist(err) { 167 ctx.NotFound() 168 } else { 169 ctx.Error(http.StatusInternalServerError, "GetIssueByIndex", err) 170 } 171 return 172 } 173 174 if !ctx.Repo.CanWriteIssuesOrPulls(issue.IsPull) { 175 ctx.Status(http.StatusForbidden) 176 return 177 } 178 179 label, err := issues_model.GetLabelByID(ctx, ctx.ParamsInt64(":id")) 180 if err != nil { 181 if issues_model.IsErrLabelNotExist(err) { 182 ctx.Error(http.StatusUnprocessableEntity, "", err) 183 } else { 184 ctx.Error(http.StatusInternalServerError, "GetLabelByID", err) 185 } 186 return 187 } 188 189 if err := issue_service.RemoveLabel(ctx, issue, ctx.Doer, label); err != nil { 190 ctx.Error(http.StatusInternalServerError, "DeleteIssueLabel", err) 191 return 192 } 193 194 ctx.Status(http.StatusNoContent) 195 } 196 197 // ReplaceIssueLabels replace labels for an issue 198 func ReplaceIssueLabels(ctx *context.APIContext) { 199 // swagger:operation PUT /repos/{owner}/{repo}/issues/{index}/labels issue issueReplaceLabels 200 // --- 201 // summary: Replace an issue's labels 202 // consumes: 203 // - application/json 204 // produces: 205 // - application/json 206 // parameters: 207 // - name: owner 208 // in: path 209 // description: owner of the repo 210 // type: string 211 // required: true 212 // - name: repo 213 // in: path 214 // description: name of the repo 215 // type: string 216 // required: true 217 // - name: index 218 // in: path 219 // description: index of the issue 220 // type: integer 221 // format: int64 222 // required: true 223 // - name: body 224 // in: body 225 // schema: 226 // "$ref": "#/definitions/IssueLabelsOption" 227 // responses: 228 // "200": 229 // "$ref": "#/responses/LabelList" 230 // "403": 231 // "$ref": "#/responses/forbidden" 232 // "404": 233 // "$ref": "#/responses/notFound" 234 form := web.GetForm(ctx).(*api.IssueLabelsOption) 235 issue, labels, err := prepareForReplaceOrAdd(ctx, *form) 236 if err != nil { 237 return 238 } 239 240 if err := issue_service.ReplaceLabels(ctx, issue, ctx.Doer, labels); err != nil { 241 ctx.Error(http.StatusInternalServerError, "ReplaceLabels", err) 242 return 243 } 244 245 labels, err = issues_model.GetLabelsByIssueID(ctx, issue.ID) 246 if err != nil { 247 ctx.Error(http.StatusInternalServerError, "GetLabelsByIssueID", err) 248 return 249 } 250 251 ctx.JSON(http.StatusOK, convert.ToLabelList(labels, ctx.Repo.Repository, ctx.Repo.Owner)) 252 } 253 254 // ClearIssueLabels delete all the labels for an issue 255 func ClearIssueLabels(ctx *context.APIContext) { 256 // swagger:operation DELETE /repos/{owner}/{repo}/issues/{index}/labels issue issueClearLabels 257 // --- 258 // summary: Remove all labels from an issue 259 // produces: 260 // - application/json 261 // parameters: 262 // - name: owner 263 // in: path 264 // description: owner of the repo 265 // type: string 266 // required: true 267 // - name: repo 268 // in: path 269 // description: name of the repo 270 // type: string 271 // required: true 272 // - name: index 273 // in: path 274 // description: index of the issue 275 // type: integer 276 // format: int64 277 // required: true 278 // responses: 279 // "204": 280 // "$ref": "#/responses/empty" 281 // "403": 282 // "$ref": "#/responses/forbidden" 283 // "404": 284 // "$ref": "#/responses/notFound" 285 286 issue, err := issues_model.GetIssueByIndex(ctx, ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) 287 if err != nil { 288 if issues_model.IsErrIssueNotExist(err) { 289 ctx.NotFound() 290 } else { 291 ctx.Error(http.StatusInternalServerError, "GetIssueByIndex", err) 292 } 293 return 294 } 295 296 if !ctx.Repo.CanWriteIssuesOrPulls(issue.IsPull) { 297 ctx.Status(http.StatusForbidden) 298 return 299 } 300 301 if err := issue_service.ClearLabels(ctx, issue, ctx.Doer); err != nil { 302 ctx.Error(http.StatusInternalServerError, "ClearLabels", err) 303 return 304 } 305 306 ctx.Status(http.StatusNoContent) 307 } 308 309 func prepareForReplaceOrAdd(ctx *context.APIContext, form api.IssueLabelsOption) (*issues_model.Issue, []*issues_model.Label, error) { 310 issue, err := issues_model.GetIssueByIndex(ctx, ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) 311 if err != nil { 312 if issues_model.IsErrIssueNotExist(err) { 313 ctx.NotFound() 314 } else { 315 ctx.Error(http.StatusInternalServerError, "GetIssueByIndex", err) 316 } 317 return nil, nil, err 318 } 319 320 labels, err := issues_model.GetLabelsByIDs(ctx, form.Labels, "id", "repo_id", "org_id", "name", "exclusive") 321 if err != nil { 322 ctx.Error(http.StatusInternalServerError, "GetLabelsByIDs", err) 323 return nil, nil, err 324 } 325 326 if !ctx.Repo.CanWriteIssuesOrPulls(issue.IsPull) { 327 ctx.Status(http.StatusForbidden) 328 return nil, nil, nil 329 } 330 331 return issue, labels, err 332 }