Skip to content

Commit 8051056

Browse files
GiteaBotlunny
andauthored
Fix track time issue id (#36664) (#36689)
Backport #36664 by @lunny --------- Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
1 parent 0b2f757 commit 8051056

File tree

6 files changed

+46
-6
lines changed

6 files changed

+46
-6
lines changed

models/issues/comment.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -692,7 +692,7 @@ func (c *Comment) LoadTime(ctx context.Context) error {
692692
return nil
693693
}
694694
var err error
695-
c.Time, err = GetTrackedTimeByID(ctx, c.TimeID)
695+
c.Time, err = GetTrackedTimeByID(ctx, c.IssueID, c.TimeID)
696696
return err
697697
}
698698

models/issues/tracked_time.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -311,13 +311,13 @@ func deleteTime(ctx context.Context, t *TrackedTime) error {
311311
}
312312

313313
// GetTrackedTimeByID returns raw TrackedTime without loading attributes by id
314-
func GetTrackedTimeByID(ctx context.Context, id int64) (*TrackedTime, error) {
314+
func GetTrackedTimeByID(ctx context.Context, issueID, trackedTimeID int64) (*TrackedTime, error) {
315315
time := new(TrackedTime)
316-
has, err := db.GetEngine(ctx).ID(id).Get(time)
316+
has, err := db.GetEngine(ctx).ID(trackedTimeID).Where("issue_id = ?", issueID).Get(time)
317317
if err != nil {
318318
return nil, err
319319
} else if !has {
320-
return nil, db.ErrNotExist{Resource: "tracked_time", ID: id}
320+
return nil, db.ErrNotExist{Resource: "tracked_time", ID: trackedTimeID}
321321
}
322322
return time, nil
323323
}

routers/api/v1/repo/issue_tracked_time.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -356,7 +356,7 @@ func DeleteTime(ctx *context.APIContext) {
356356
return
357357
}
358358

359-
time, err := issues_model.GetTrackedTimeByID(ctx, ctx.PathParamInt64("id"))
359+
time, err := issues_model.GetTrackedTimeByID(ctx, issue.ID, ctx.PathParamInt64("id"))
360360
if err != nil {
361361
if db.IsErrNotExist(err) {
362362
ctx.APIErrorNotFound(err)

routers/web/repo/issue_timetrack.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ func DeleteTime(c *context.Context) {
6060
return
6161
}
6262

63-
t, err := issues_model.GetTrackedTimeByID(c, c.PathParamInt64("timeid"))
63+
t, err := issues_model.GetTrackedTimeByID(c, issue.ID, c.PathParamInt64("timeid"))
6464
if err != nil {
6565
if db.IsErrNotExist(err) {
6666
c.NotFound(err)

tests/integration/api_issue_tracked_time_test.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,12 @@ func TestAPIDeleteTrackedTime(t *testing.T) {
7979
AddTokenAuth(token)
8080
MakeRequest(t, req, http.StatusForbidden)
8181

82+
// Deletion should be scoped to the issue in the URL
83+
time5 := unittest.AssertExistsAndLoadBean(t, &issues_model.TrackedTime{ID: 5})
84+
req = NewRequestf(t, "DELETE", "/api/v1/repos/%s/%s/issues/%d/times/%d", user2.Name, issue2.Repo.Name, issue2.Index, time5.ID).
85+
AddTokenAuth(token)
86+
MakeRequest(t, req, http.StatusNotFound)
87+
8288
time3 := unittest.AssertExistsAndLoadBean(t, &issues_model.TrackedTime{ID: 3})
8389
req = NewRequestf(t, "DELETE", "/api/v1/repos/%s/%s/issues/%d/times/%d", user2.Name, issue2.Repo.Name, issue2.Index, time3.ID).
8490
AddTokenAuth(token)
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// Copyright 2026 The Gitea Authors. All rights reserved.
2+
// SPDX-License-Identifier: MIT
3+
4+
package integration
5+
6+
import (
7+
"fmt"
8+
"net/http"
9+
"testing"
10+
11+
issues_model "code.gitea.io/gitea/models/issues"
12+
"code.gitea.io/gitea/models/unittest"
13+
"code.gitea.io/gitea/tests"
14+
15+
"github.com/stretchr/testify/assert"
16+
)
17+
18+
func TestIssueTimeDeleteScoped(t *testing.T) {
19+
defer tests.PrepareTestEnv(t)()
20+
21+
issue1 := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 1})
22+
assert.NoError(t, issue1.LoadRepo(t.Context()))
23+
tracked := unittest.AssertExistsAndLoadBean(t, &issues_model.TrackedTime{ID: 5})
24+
25+
session := loginUser(t, issue1.Repo.OwnerName)
26+
url := fmt.Sprintf("/%s/%s/issues/%d/times/%d/delete", issue1.Repo.OwnerName, issue1.Repo.Name, issue1.Index, tracked.ID)
27+
req := NewRequestWithValues(t, "POST", url, map[string]string{
28+
"_csrf": GetUserCSRFToken(t, session),
29+
})
30+
session.MakeRequest(t, req, http.StatusNotFound)
31+
32+
tracked = unittest.AssertExistsAndLoadBean(t, &issues_model.TrackedTime{ID: tracked.ID})
33+
assert.False(t, tracked.Deleted)
34+
}

0 commit comments

Comments
 (0)