summaryrefslogtreecommitdiffstats
path: root/routers/api/v1
diff options
context:
space:
mode:
author6543 <6543@obermui.de>2019-12-27 21:30:58 +0100
committerzeripath <art27@cantab.net>2019-12-27 20:30:58 +0000
commitf2d03cda96eb5febbf9801f6b6cf5daa37220bc9 (patch)
tree8906922ca58d47634ec2b6237f00a87389dd8316 /routers/api/v1
parent0bcf644da4c3d21fad3ce8f33ccc26f8110568d6 (diff)
downloadgitea-f2d03cda96eb5febbf9801f6b6cf5daa37220bc9.tar.gz
gitea-f2d03cda96eb5febbf9801f6b6cf5daa37220bc9.zip
[API] Extend times API (#9200)
Extensively extend the times API. close #8833; close #8513; close #8559
Diffstat (limited to 'routers/api/v1')
-rw-r--r--routers/api/v1/api.go7
-rw-r--r--routers/api/v1/repo/issue_tracked_time.go247
2 files changed, 222 insertions, 32 deletions
diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go
index c2f019eb41..0bb5320b16 100644
--- a/routers/api/v1/api.go
+++ b/routers/api/v1/api.go
@@ -687,8 +687,11 @@ func RegisterRoutes(m *macaron.Macaron) {
m.Delete("/:id", reqToken(), repo.DeleteIssueLabel)
})
m.Group("/times", func() {
- m.Combo("").Get(repo.ListTrackedTimes).
- Post(reqToken(), bind(api.AddTimeOption{}), repo.AddTime)
+ m.Combo("", reqToken()).
+ Get(repo.ListTrackedTimes).
+ Post(bind(api.AddTimeOption{}), repo.AddTime).
+ Delete(repo.ResetIssueTime)
+ m.Delete("/:id", reqToken(), repo.DeleteTime)
})
m.Combo("/deadline").Post(reqToken(), bind(api.EditDeadlineOption{}), repo.UpdateIssueDeadline)
m.Group("/stopwatch", func() {
diff --git a/routers/api/v1/repo/issue_tracked_time.go b/routers/api/v1/repo/issue_tracked_time.go
index 0d3ca5c177..80830e2fe6 100644
--- a/routers/api/v1/repo/issue_tracked_time.go
+++ b/routers/api/v1/repo/issue_tracked_time.go
@@ -6,23 +6,16 @@ package repo
import (
"net/http"
+ "time"
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/context"
api "code.gitea.io/gitea/modules/structs"
)
-func trackedTimesToAPIFormat(trackedTimes []*models.TrackedTime) []*api.TrackedTime {
- apiTrackedTimes := make([]*api.TrackedTime, len(trackedTimes))
- for i, trackedTime := range trackedTimes {
- apiTrackedTimes[i] = trackedTime.APIFormat()
- }
- return apiTrackedTimes
-}
-
// ListTrackedTimes list all the tracked times of an issue
func ListTrackedTimes(ctx *context.APIContext) {
- // swagger:operation GET /repos/{owner}/{repo}/issues/{id}/times issue issueTrackedTimes
+ // swagger:operation GET /repos/{owner}/{repo}/issues/{index}/times issue issueTrackedTimes
// ---
// summary: List an issue's tracked times
// produces:
@@ -38,7 +31,7 @@ func ListTrackedTimes(ctx *context.APIContext) {
// description: name of the repo
// type: string
// required: true
- // - name: id
+ // - name: index
// in: path
// description: index of the issue
// type: integer
@@ -64,20 +57,32 @@ func ListTrackedTimes(ctx *context.APIContext) {
return
}
- trackedTimes, err := models.GetTrackedTimes(models.FindTrackedTimesOptions{IssueID: issue.ID})
+ opts := models.FindTrackedTimesOptions{
+ RepositoryID: ctx.Repo.Repository.ID,
+ IssueID: issue.ID,
+ }
+
+ if !ctx.IsUserRepoAdmin() && !ctx.User.IsAdmin {
+ opts.UserID = ctx.User.ID
+ }
+
+ trackedTimes, err := models.GetTrackedTimes(opts)
if err != nil {
- ctx.Error(http.StatusInternalServerError, "GetTrackedTimesByIssue", err)
+ ctx.Error(http.StatusInternalServerError, "GetTrackedTimes", err)
+ return
+ }
+ if err = trackedTimes.LoadAttributes(); err != nil {
+ ctx.Error(http.StatusInternalServerError, "LoadAttributes", err)
return
}
- apiTrackedTimes := trackedTimesToAPIFormat(trackedTimes)
- ctx.JSON(http.StatusOK, &apiTrackedTimes)
+ ctx.JSON(http.StatusOK, trackedTimes.APIFormat())
}
-// AddTime adds time manual to the given issue
+// AddTime add time manual to the given issue
func AddTime(ctx *context.APIContext, form api.AddTimeOption) {
- // swagger:operation Post /repos/{owner}/{repo}/issues/{id}/times issue issueAddTime
+ // swagger:operation Post /repos/{owner}/{repo}/issues/{index}/times issue issueAddTime
// ---
- // summary: Add a tracked time to a issue
+ // summary: Add tracked time to a issue
// consumes:
// - application/json
// produces:
@@ -93,9 +98,9 @@ func AddTime(ctx *context.APIContext, form api.AddTimeOption) {
// description: name of the repo
// type: string
// required: true
- // - name: id
+ // - name: index
// in: path
- // description: index of the issue to add tracked time to
+ // description: index of the issue
// type: integer
// format: int64
// required: true
@@ -129,14 +134,179 @@ func AddTime(ctx *context.APIContext, form api.AddTimeOption) {
ctx.Status(http.StatusForbidden)
return
}
- trackedTime, err := models.AddTime(ctx.User, issue, form.Time)
+
+ user := ctx.User
+ if form.User != "" {
+ if (ctx.IsUserRepoAdmin() && ctx.User.Name != form.User) || ctx.User.IsAdmin {
+ //allow only RepoAdmin, Admin and User to add time
+ user, err = models.GetUserByName(form.User)
+ if err != nil {
+ ctx.Error(500, "GetUserByName", err)
+ }
+ }
+ }
+
+ created := time.Time{}
+ if !form.Created.IsZero() {
+ created = form.Created
+ }
+
+ trackedTime, err := models.AddTime(user, issue, form.Time, created)
if err != nil {
ctx.Error(http.StatusInternalServerError, "AddTime", err)
return
}
+ if err = trackedTime.LoadAttributes(); err != nil {
+ ctx.Error(http.StatusInternalServerError, "LoadAttributes", err)
+ return
+ }
ctx.JSON(http.StatusOK, trackedTime.APIFormat())
}
+// ResetIssueTime reset time manual to the given issue
+func ResetIssueTime(ctx *context.APIContext) {
+ // swagger:operation Delete /repos/{owner}/{repo}/issues/{index}/times issue issueResetTime
+ // ---
+ // summary: Reset a tracked time of an issue
+ // consumes:
+ // - application/json
+ // produces:
+ // - application/json
+ // parameters:
+ // - name: owner
+ // in: path
+ // description: owner of the repo
+ // type: string
+ // required: true
+ // - name: repo
+ // in: path
+ // description: name of the repo
+ // type: string
+ // required: true
+ // - name: index
+ // in: path
+ // description: index of the issue to add tracked time to
+ // type: integer
+ // format: int64
+ // required: true
+ // responses:
+ // "204":
+ // "$ref": "#/responses/empty"
+ // "400":
+ // "$ref": "#/responses/error"
+ // "403":
+ // "$ref": "#/responses/error"
+
+ issue, err := models.GetIssueByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index"))
+ if err != nil {
+ if models.IsErrIssueNotExist(err) {
+ ctx.NotFound(err)
+ } else {
+ ctx.Error(500, "GetIssueByIndex", err)
+ }
+ return
+ }
+
+ if !ctx.Repo.CanUseTimetracker(issue, ctx.User) {
+ if !ctx.Repo.Repository.IsTimetrackerEnabled() {
+ ctx.JSON(400, struct{ Message string }{Message: "time tracking disabled"})
+ return
+ }
+ ctx.Status(403)
+ return
+ }
+
+ err = models.DeleteIssueUserTimes(issue, ctx.User)
+ if err != nil {
+ if models.IsErrNotExist(err) {
+ ctx.Error(404, "DeleteIssueUserTimes", err)
+ } else {
+ ctx.Error(500, "DeleteIssueUserTimes", err)
+ }
+ return
+ }
+ ctx.Status(204)
+}
+
+// DeleteTime delete a specific time by id
+func DeleteTime(ctx *context.APIContext) {
+ // swagger:operation Delete /repos/{owner}/{repo}/issues/{index}/times/{id} issue issueDeleteTime
+ // ---
+ // summary: Delete specific tracked time
+ // consumes:
+ // - application/json
+ // produces:
+ // - application/json
+ // parameters:
+ // - name: owner
+ // in: path
+ // description: owner of the repo
+ // type: string
+ // required: true
+ // - name: repo
+ // in: path
+ // description: name of the repo
+ // type: string
+ // required: true
+ // - name: index
+ // in: path
+ // description: index of the issue
+ // type: integer
+ // format: int64
+ // required: true
+ // - name: id
+ // in: path
+ // description: id of time to delete
+ // type: integer
+ // format: int64
+ // required: true
+ // responses:
+ // "204":
+ // "$ref": "#/responses/empty"
+ // "400":
+ // "$ref": "#/responses/error"
+ // "403":
+ // "$ref": "#/responses/error"
+
+ issue, err := models.GetIssueByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index"))
+ if err != nil {
+ if models.IsErrIssueNotExist(err) {
+ ctx.NotFound(err)
+ } else {
+ ctx.Error(500, "GetIssueByIndex", err)
+ }
+ return
+ }
+
+ if !ctx.Repo.CanUseTimetracker(issue, ctx.User) {
+ if !ctx.Repo.Repository.IsTimetrackerEnabled() {
+ ctx.JSON(400, struct{ Message string }{Message: "time tracking disabled"})
+ return
+ }
+ ctx.Status(403)
+ return
+ }
+
+ time, err := models.GetTrackedTimeByID(ctx.ParamsInt64(":id"))
+ if err != nil {
+ ctx.Error(500, "GetTrackedTimeByID", err)
+ return
+ }
+
+ if !ctx.User.IsAdmin && time.UserID != ctx.User.ID {
+ //Only Admin and User itself can delete their time
+ ctx.Status(403)
+ return
+ }
+
+ err = models.DeleteTime(time)
+ if err != nil {
+ ctx.Error(500, "DeleteTime", err)
+ return
+ }
+ ctx.Status(204)
+}
+
// ListTrackedTimesByUser lists all tracked times of the user
func ListTrackedTimesByUser(ctx *context.APIContext) {
// swagger:operation GET /repos/{owner}/{repo}/times/{user} user userTrackedTimes
@@ -187,11 +357,14 @@ func ListTrackedTimesByUser(ctx *context.APIContext) {
UserID: user.ID,
RepositoryID: ctx.Repo.Repository.ID})
if err != nil {
- ctx.Error(http.StatusInternalServerError, "GetTrackedTimesByUser", err)
+ ctx.Error(http.StatusInternalServerError, "GetTrackedTimes", err)
return
}
- apiTrackedTimes := trackedTimesToAPIFormat(trackedTimes)
- ctx.JSON(http.StatusOK, &apiTrackedTimes)
+ if err = trackedTimes.LoadAttributes(); err != nil {
+ ctx.Error(http.StatusInternalServerError, "LoadAttributes", err)
+ return
+ }
+ ctx.JSON(http.StatusOK, trackedTimes.APIFormat())
}
// ListTrackedTimesByRepository lists all tracked times of the repository
@@ -222,14 +395,25 @@ func ListTrackedTimesByRepository(ctx *context.APIContext) {
ctx.Error(http.StatusBadRequest, "", "time tracking disabled")
return
}
- trackedTimes, err := models.GetTrackedTimes(models.FindTrackedTimesOptions{
- RepositoryID: ctx.Repo.Repository.ID})
+
+ opts := models.FindTrackedTimesOptions{
+ RepositoryID: ctx.Repo.Repository.ID,
+ }
+
+ if !ctx.IsUserRepoAdmin() && !ctx.User.IsAdmin {
+ opts.UserID = ctx.User.ID
+ }
+
+ trackedTimes, err := models.GetTrackedTimes(opts)
if err != nil {
- ctx.Error(http.StatusInternalServerError, "GetTrackedTimesByUser", err)
+ ctx.Error(http.StatusInternalServerError, "GetTrackedTimes", err)
return
}
- apiTrackedTimes := trackedTimesToAPIFormat(trackedTimes)
- ctx.JSON(http.StatusOK, &apiTrackedTimes)
+ if err = trackedTimes.LoadAttributes(); err != nil {
+ ctx.Error(http.StatusInternalServerError, "LoadAttributes", err)
+ return
+ }
+ ctx.JSON(http.StatusOK, trackedTimes.APIFormat())
}
// ListMyTrackedTimes lists all tracked times of the current user
@@ -248,6 +432,9 @@ func ListMyTrackedTimes(ctx *context.APIContext) {
ctx.Error(http.StatusInternalServerError, "GetTrackedTimesByUser", err)
return
}
- apiTrackedTimes := trackedTimesToAPIFormat(trackedTimes)
- ctx.JSON(http.StatusOK, &apiTrackedTimes)
+ if err = trackedTimes.LoadAttributes(); err != nil {
+ ctx.Error(http.StatusInternalServerError, "LoadAttributes", err)
+ return
+ }
+ ctx.JSON(http.StatusOK, trackedTimes.APIFormat())
}