diff options
author | 6543 <6543@obermui.de> | 2019-12-27 21:30:58 +0100 |
---|---|---|
committer | zeripath <art27@cantab.net> | 2019-12-27 20:30:58 +0000 |
commit | f2d03cda96eb5febbf9801f6b6cf5daa37220bc9 (patch) | |
tree | 8906922ca58d47634ec2b6237f00a87389dd8316 /routers/api/v1 | |
parent | 0bcf644da4c3d21fad3ce8f33ccc26f8110568d6 (diff) | |
download | gitea-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.go | 7 | ||||
-rw-r--r-- | routers/api/v1/repo/issue_tracked_time.go | 247 |
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()) } |