summaryrefslogtreecommitdiffstats
path: root/routers/api/v1
diff options
context:
space:
mode:
Diffstat (limited to 'routers/api/v1')
-rw-r--r--routers/api/v1/api.go8
-rw-r--r--routers/api/v1/repo/issue_tracked_time.go134
-rw-r--r--routers/api/v1/utils/utils.go33
3 files changed, 150 insertions, 25 deletions
diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go
index 3f766c7a74..9f18951893 100644
--- a/routers/api/v1/api.go
+++ b/routers/api/v1/api.go
@@ -654,7 +654,7 @@ func RegisterRoutes(m *macaron.Macaron) {
m.Group("/times", func() {
m.Combo("").Get(repo.ListTrackedTimesByRepository)
m.Combo("/:timetrackingusername").Get(repo.ListTrackedTimesByUser)
- }, mustEnableIssues)
+ }, mustEnableIssues, reqToken())
m.Group("/issues", func() {
m.Combo("").Get(repo.ListIssues).
Post(reqToken(), mustNotBeArchived, bind(api.CreateIssueOption{}), repo.CreateIssue)
@@ -688,12 +688,12 @@ func RegisterRoutes(m *macaron.Macaron) {
m.Delete("/:id", reqToken(), repo.DeleteIssueLabel)
})
m.Group("/times", func() {
- m.Combo("", reqToken()).
+ m.Combo("").
Get(repo.ListTrackedTimes).
Post(bind(api.AddTimeOption{}), repo.AddTime).
Delete(repo.ResetIssueTime)
- m.Delete("/:id", reqToken(), repo.DeleteTime)
- })
+ m.Delete("/:id", repo.DeleteTime)
+ }, reqToken())
m.Combo("/deadline").Post(reqToken(), bind(api.EditDeadlineOption{}), repo.UpdateIssueDeadline)
m.Group("/stopwatch", func() {
m.Post("/start", reqToken(), repo.StartIssueStopwatch)
diff --git a/routers/api/v1/repo/issue_tracked_time.go b/routers/api/v1/repo/issue_tracked_time.go
index 80830e2fe6..dd959192c9 100644
--- a/routers/api/v1/repo/issue_tracked_time.go
+++ b/routers/api/v1/repo/issue_tracked_time.go
@@ -5,12 +5,15 @@
package repo
import (
+ "fmt"
"net/http"
+ "strings"
"time"
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/context"
api "code.gitea.io/gitea/modules/structs"
+ "code.gitea.io/gitea/routers/api/v1/utils"
)
// ListTrackedTimes list all the tracked times of an issue
@@ -37,6 +40,16 @@ func ListTrackedTimes(ctx *context.APIContext) {
// type: integer
// format: int64
// required: true
+ // - name: since
+ // in: query
+ // description: Only show times updated after the given time. This is a timestamp in RFC 3339 format
+ // type: string
+ // format: date-time
+ // - name: before
+ // in: query
+ // description: Only show times updated before the given time. This is a timestamp in RFC 3339 format
+ // type: string
+ // format: date-time
// responses:
// "200":
// "$ref": "#/responses/TrackedTimeList"
@@ -62,6 +75,11 @@ func ListTrackedTimes(ctx *context.APIContext) {
IssueID: issue.ID,
}
+ if opts.CreatedBeforeUnix, opts.CreatedAfterUnix, err = utils.GetQueryBeforeSince(ctx); err != nil {
+ ctx.InternalServerError(err)
+ return
+ }
+
if !ctx.IsUserRepoAdmin() && !ctx.User.IsAdmin {
opts.UserID = ctx.User.ID
}
@@ -141,7 +159,7 @@ func AddTime(ctx *context.APIContext, form api.AddTimeOption) {
//allow only RepoAdmin, Admin and User to add time
user, err = models.GetUserByName(form.User)
if err != nil {
- ctx.Error(500, "GetUserByName", err)
+ ctx.Error(http.StatusInternalServerError, "GetUserByName", err)
}
}
}
@@ -195,33 +213,33 @@ func ResetIssueTime(ctx *context.APIContext) {
// "400":
// "$ref": "#/responses/error"
// "403":
- // "$ref": "#/responses/error"
+ // "$ref": "#/responses/forbidden"
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)
+ ctx.Error(http.StatusInternalServerError, "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"})
+ ctx.JSON(http.StatusBadRequest, struct{ Message string }{Message: "time tracking disabled"})
return
}
- ctx.Status(403)
+ ctx.Status(http.StatusForbidden)
return
}
err = models.DeleteIssueUserTimes(issue, ctx.User)
if err != nil {
if models.IsErrNotExist(err) {
- ctx.Error(404, "DeleteIssueUserTimes", err)
+ ctx.Error(http.StatusNotFound, "DeleteIssueUserTimes", err)
} else {
- ctx.Error(500, "DeleteIssueUserTimes", err)
+ ctx.Error(http.StatusInternalServerError, "DeleteIssueUserTimes", err)
}
return
}
@@ -266,52 +284,53 @@ func DeleteTime(ctx *context.APIContext) {
// "400":
// "$ref": "#/responses/error"
// "403":
- // "$ref": "#/responses/error"
+ // "$ref": "#/responses/forbidden"
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)
+ ctx.Error(http.StatusInternalServerError, "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"})
+ ctx.JSON(http.StatusBadRequest, struct{ Message string }{Message: "time tracking disabled"})
return
}
- ctx.Status(403)
+ ctx.Status(http.StatusForbidden)
return
}
time, err := models.GetTrackedTimeByID(ctx.ParamsInt64(":id"))
if err != nil {
- ctx.Error(500, "GetTrackedTimeByID", err)
+ ctx.Error(http.StatusInternalServerError, "GetTrackedTimeByID", err)
return
}
if !ctx.User.IsAdmin && time.UserID != ctx.User.ID {
//Only Admin and User itself can delete their time
- ctx.Status(403)
+ ctx.Status(http.StatusForbidden)
return
}
err = models.DeleteTime(time)
if err != nil {
- ctx.Error(500, "DeleteTime", err)
+ ctx.Error(http.StatusInternalServerError, "DeleteTime", err)
return
}
- ctx.Status(204)
+ ctx.Status(http.StatusNoContent)
}
// ListTrackedTimesByUser lists all tracked times of the user
func ListTrackedTimesByUser(ctx *context.APIContext) {
- // swagger:operation GET /repos/{owner}/{repo}/times/{user} user userTrackedTimes
+ // swagger:operation GET /repos/{owner}/{repo}/times/{user} repository userTrackedTimes
// ---
// summary: List a user's tracked times in a repo
+ // deprecated: true
// produces:
// - application/json
// parameters:
@@ -335,6 +354,8 @@ func ListTrackedTimesByUser(ctx *context.APIContext) {
// "$ref": "#/responses/TrackedTimeList"
// "400":
// "$ref": "#/responses/error"
+ // "403":
+ // "$ref": "#/responses/forbidden"
if !ctx.Repo.Repository.IsTimetrackerEnabled() {
ctx.Error(http.StatusBadRequest, "", "time tracking disabled")
@@ -353,9 +374,23 @@ func ListTrackedTimesByUser(ctx *context.APIContext) {
ctx.NotFound()
return
}
- trackedTimes, err := models.GetTrackedTimes(models.FindTrackedTimesOptions{
+
+ if !ctx.IsUserRepoAdmin() && !ctx.User.IsAdmin && ctx.User.ID != user.ID {
+ ctx.Error(http.StatusForbidden, "", fmt.Errorf("query user not allowed not enouth rights"))
+ return
+ }
+
+ if !ctx.IsUserRepoAdmin() && !ctx.User.IsAdmin && ctx.User.ID != user.ID {
+ ctx.Error(http.StatusForbidden, "", fmt.Errorf("query user not allowed not enouth rights"))
+ return
+ }
+
+ opts := models.FindTrackedTimesOptions{
UserID: user.ID,
- RepositoryID: ctx.Repo.Repository.ID})
+ RepositoryID: ctx.Repo.Repository.ID,
+ }
+
+ trackedTimes, err := models.GetTrackedTimes(opts)
if err != nil {
ctx.Error(http.StatusInternalServerError, "GetTrackedTimes", err)
return
@@ -385,11 +420,27 @@ func ListTrackedTimesByRepository(ctx *context.APIContext) {
// description: name of the repo
// type: string
// required: true
+ // - name: user
+ // in: query
+ // description: optional filter by user
+ // type: string
+ // - name: since
+ // in: query
+ // description: Only show times updated after the given time. This is a timestamp in RFC 3339 format
+ // type: string
+ // format: date-time
+ // - name: before
+ // in: query
+ // description: Only show times updated before the given time. This is a timestamp in RFC 3339 format
+ // type: string
+ // format: date-time
// responses:
// "200":
// "$ref": "#/responses/TrackedTimeList"
// "400":
// "$ref": "#/responses/error"
+ // "403":
+ // "$ref": "#/responses/forbidden"
if !ctx.Repo.Repository.IsTimetrackerEnabled() {
ctx.Error(http.StatusBadRequest, "", "time tracking disabled")
@@ -400,8 +451,30 @@ func ListTrackedTimesByRepository(ctx *context.APIContext) {
RepositoryID: ctx.Repo.Repository.ID,
}
+ // Filters
+ qUser := strings.Trim(ctx.Query("user"), " ")
+ if qUser != "" {
+ user, err := models.GetUserByName(qUser)
+ if err != nil {
+ ctx.Error(http.StatusInternalServerError, "GetUserByName", err)
+ return
+ }
+ opts.UserID = user.ID
+ }
+
+ var err error
+ if opts.CreatedBeforeUnix, opts.CreatedAfterUnix, err = utils.GetQueryBeforeSince(ctx); err != nil {
+ ctx.InternalServerError(err)
+ return
+ }
+
if !ctx.IsUserRepoAdmin() && !ctx.User.IsAdmin {
- opts.UserID = ctx.User.ID
+ if opts.UserID == 0 {
+ opts.UserID = ctx.User.ID
+ } else {
+ ctx.Error(http.StatusForbidden, "", fmt.Errorf("query user not allowed not enouth rights"))
+ return
+ }
}
trackedTimes, err := models.GetTrackedTimes(opts)
@@ -423,18 +496,39 @@ func ListMyTrackedTimes(ctx *context.APIContext) {
// summary: List the current user's tracked times
// produces:
// - application/json
+ // parameters:
+ // - name: since
+ // in: query
+ // description: Only show times updated after the given time. This is a timestamp in RFC 3339 format
+ // type: string
+ // format: date-time
+ // - name: before
+ // in: query
+ // description: Only show times updated before the given time. This is a timestamp in RFC 3339 format
+ // type: string
+ // format: date-time
// responses:
// "200":
// "$ref": "#/responses/TrackedTimeList"
- trackedTimes, err := models.GetTrackedTimes(models.FindTrackedTimesOptions{UserID: ctx.User.ID})
+ opts := models.FindTrackedTimesOptions{UserID: ctx.User.ID}
+
+ var err error
+ if opts.CreatedBeforeUnix, opts.CreatedAfterUnix, err = utils.GetQueryBeforeSince(ctx); err != nil {
+ ctx.InternalServerError(err)
+ return
+ }
+
+ trackedTimes, err := models.GetTrackedTimes(opts)
if err != nil {
ctx.Error(http.StatusInternalServerError, "GetTrackedTimesByUser", err)
return
}
+
if err = trackedTimes.LoadAttributes(); err != nil {
ctx.Error(http.StatusInternalServerError, "LoadAttributes", err)
return
}
+
ctx.JSON(http.StatusOK, trackedTimes.APIFormat())
}
diff --git a/routers/api/v1/utils/utils.go b/routers/api/v1/utils/utils.go
index f7c2b224d5..35f4873964 100644
--- a/routers/api/v1/utils/utils.go
+++ b/routers/api/v1/utils/utils.go
@@ -4,7 +4,12 @@
package utils
-import "code.gitea.io/gitea/modules/context"
+import (
+ "strings"
+ "time"
+
+ "code.gitea.io/gitea/modules/context"
+)
// UserID user ID of authenticated user, or 0 if not authenticated
func UserID(ctx *context.APIContext) int64 {
@@ -13,3 +18,29 @@ func UserID(ctx *context.APIContext) int64 {
}
return ctx.User.ID
}
+
+// GetQueryBeforeSince return parsed time (unix format) from URL query's before and since
+func GetQueryBeforeSince(ctx *context.APIContext) (before, since int64, err error) {
+ qCreatedBefore := strings.Trim(ctx.Query("before"), " ")
+ if qCreatedBefore != "" {
+ createdBefore, err := time.Parse(time.RFC3339, qCreatedBefore)
+ if err != nil {
+ return 0, 0, err
+ }
+ if !createdBefore.IsZero() {
+ before = createdBefore.Unix()
+ }
+ }
+
+ qCreatedAfter := strings.Trim(ctx.Query("since"), " ")
+ if qCreatedAfter != "" {
+ createdAfter, err := time.Parse(time.RFC3339, qCreatedAfter)
+ if err != nil {
+ return 0, 0, err
+ }
+ if !createdAfter.IsZero() {
+ since = createdAfter.Unix()
+ }
+ }
+ return before, since, nil
+}