Refactor Issues Subscription (#8738)
* FIX: getIssueWatchers() get only aktive suscriber * save query to work later with it or not ... * fix test + add new case * corect tests + GetIssueWatch * API issue_subscripton: Put/Delete require tocken * remove redundant code * swagger specify return value * remove unused binding * remove note because I'll implement this in a different way and in another PR * ID should be unique! * use xorm session * Revert "use xorm session" This reverts commit c1de540147199f2f1a8dd0d008f54af3603e2229. * better test code * more acurate comments * use assert.False/True instead of Equal * use more assert methodes
This commit is contained in:
parent
dfd8b94923
commit
2ab8c78c30
6 changed files with 47 additions and 52 deletions
|
@ -13,3 +13,19 @@
|
|||
is_watching: false
|
||||
created_unix: 946684800
|
||||
updated_unix: 946684800
|
||||
|
||||
-
|
||||
id: 3
|
||||
user_id: 2
|
||||
issue_id: 7
|
||||
is_watching: true
|
||||
created_unix: 946684800
|
||||
updated_unix: 946684800
|
||||
|
||||
-
|
||||
id: 4
|
||||
user_id: 1
|
||||
issue_id: 7
|
||||
is_watching: false
|
||||
created_unix: 946684800
|
||||
updated_unix: 946684800
|
||||
|
|
|
@ -56,6 +56,7 @@ func getIssueWatch(e Engine, userID, issueID int64) (iw *IssueWatch, exists bool
|
|||
exists, err = e.
|
||||
Where("user_id = ?", userID).
|
||||
And("issue_id = ?", issueID).
|
||||
And("is_watching = ?", true).
|
||||
Get(iw)
|
||||
return
|
||||
}
|
||||
|
@ -80,6 +81,7 @@ func GetIssueWatchers(issueID int64) (IssueWatchList, error) {
|
|||
func getIssueWatchers(e Engine, issueID int64) (watches IssueWatchList, err error) {
|
||||
err = e.
|
||||
Where("`issue_watch`.issue_id = ?", issueID).
|
||||
And("`issue_watch`.is_watching = ?", true).
|
||||
And("`user`.is_active = ?", true).
|
||||
And("`user`.prohibit_login = ?", false).
|
||||
Join("INNER", "`user`", "`user`.id = `issue_watch`.user_id").
|
||||
|
|
|
@ -15,26 +15,26 @@ func TestCreateOrUpdateIssueWatch(t *testing.T) {
|
|||
|
||||
assert.NoError(t, CreateOrUpdateIssueWatch(3, 1, true))
|
||||
iw := AssertExistsAndLoadBean(t, &IssueWatch{UserID: 3, IssueID: 1}).(*IssueWatch)
|
||||
assert.Equal(t, true, iw.IsWatching)
|
||||
assert.True(t, iw.IsWatching)
|
||||
|
||||
assert.NoError(t, CreateOrUpdateIssueWatch(1, 1, false))
|
||||
iw = AssertExistsAndLoadBean(t, &IssueWatch{UserID: 1, IssueID: 1}).(*IssueWatch)
|
||||
assert.Equal(t, false, iw.IsWatching)
|
||||
assert.False(t, iw.IsWatching)
|
||||
}
|
||||
|
||||
func TestGetIssueWatch(t *testing.T) {
|
||||
assert.NoError(t, PrepareTestDatabase())
|
||||
|
||||
_, exists, err := GetIssueWatch(9, 1)
|
||||
assert.Equal(t, true, exists)
|
||||
assert.True(t, exists)
|
||||
assert.NoError(t, err)
|
||||
|
||||
_, exists, err = GetIssueWatch(2, 2)
|
||||
assert.Equal(t, true, exists)
|
||||
assert.False(t, exists)
|
||||
assert.NoError(t, err)
|
||||
|
||||
_, exists, err = GetIssueWatch(3, 1)
|
||||
assert.Equal(t, false, exists)
|
||||
assert.False(t, exists)
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
|
@ -44,13 +44,20 @@ func TestGetIssueWatchers(t *testing.T) {
|
|||
iws, err := GetIssueWatchers(1)
|
||||
assert.NoError(t, err)
|
||||
// Watcher is inactive, thus 0
|
||||
assert.Equal(t, 0, len(iws))
|
||||
assert.Len(t, iws, 0)
|
||||
|
||||
iws, err = GetIssueWatchers(2)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, 1, len(iws))
|
||||
// Watcher is explicit not watching
|
||||
assert.Len(t, iws, 0)
|
||||
|
||||
iws, err = GetIssueWatchers(5)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, 0, len(iws))
|
||||
// Issue has no Watchers
|
||||
assert.Len(t, iws, 0)
|
||||
|
||||
iws, err = GetIssueWatchers(7)
|
||||
assert.NoError(t, err)
|
||||
// Issue has one watcher
|
||||
assert.Len(t, iws, 1)
|
||||
}
|
||||
|
|
|
@ -691,9 +691,9 @@ func RegisterRoutes(m *macaron.Macaron) {
|
|||
m.Post("/stop", reqToken(), repo.StopIssueStopwatch)
|
||||
})
|
||||
m.Group("/subscriptions", func() {
|
||||
m.Get("", bind(api.User{}), repo.GetIssueSubscribers)
|
||||
m.Put("/:user", repo.AddIssueSubscription)
|
||||
m.Delete("/:user", repo.DelIssueSubscription)
|
||||
m.Get("", repo.GetIssueSubscribers)
|
||||
m.Put("/:user", reqToken(), repo.AddIssueSubscription)
|
||||
m.Delete("/:user", reqToken(), repo.DelIssueSubscription)
|
||||
})
|
||||
})
|
||||
}, mustEnableIssuesOrPulls)
|
||||
|
|
|
@ -7,7 +7,6 @@ package repo
|
|||
import (
|
||||
"code.gitea.io/gitea/models"
|
||||
"code.gitea.io/gitea/modules/context"
|
||||
api "code.gitea.io/gitea/modules/structs"
|
||||
)
|
||||
|
||||
// AddIssueSubscription Subscribe user to issue
|
||||
|
@ -48,40 +47,7 @@ func AddIssueSubscription(ctx *context.APIContext) {
|
|||
// description: User can only subscribe itself if he is no admin
|
||||
// "404":
|
||||
// description: Issue not found
|
||||
issue, err := models.GetIssueByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index"))
|
||||
if err != nil {
|
||||
if models.IsErrIssueNotExist(err) {
|
||||
ctx.NotFound()
|
||||
} else {
|
||||
ctx.Error(500, "GetIssueByIndex", err)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
user, err := models.GetUserByName(ctx.Params(":user"))
|
||||
if err != nil {
|
||||
if models.IsErrUserNotExist(err) {
|
||||
ctx.NotFound()
|
||||
} else {
|
||||
ctx.Error(500, "GetUserByName", err)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
//only admin and user for itself can change subscription
|
||||
if user.ID != ctx.User.ID && !ctx.User.IsAdmin {
|
||||
ctx.Error(403, "User", nil)
|
||||
return
|
||||
}
|
||||
|
||||
if err := models.CreateOrUpdateIssueWatch(user.ID, issue.ID, true); err != nil {
|
||||
ctx.Error(500, "CreateOrUpdateIssueWatch", err)
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Status(201)
|
||||
setIssueSubscription(ctx, true)
|
||||
}
|
||||
|
||||
// DelIssueSubscription Unsubscribe user from issue
|
||||
|
@ -122,6 +88,10 @@ func DelIssueSubscription(ctx *context.APIContext) {
|
|||
// description: User can only subscribe itself if he is no admin
|
||||
// "404":
|
||||
// description: Issue not found
|
||||
setIssueSubscription(ctx, false)
|
||||
}
|
||||
|
||||
func setIssueSubscription(ctx *context.APIContext, watch bool) {
|
||||
issue, err := models.GetIssueByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index"))
|
||||
if err != nil {
|
||||
if models.IsErrIssueNotExist(err) {
|
||||
|
@ -150,7 +120,7 @@ func DelIssueSubscription(ctx *context.APIContext) {
|
|||
return
|
||||
}
|
||||
|
||||
if err := models.CreateOrUpdateIssueWatch(user.ID, issue.ID, false); err != nil {
|
||||
if err := models.CreateOrUpdateIssueWatch(user.ID, issue.ID, watch); err != nil {
|
||||
ctx.Error(500, "CreateOrUpdateIssueWatch", err)
|
||||
return
|
||||
}
|
||||
|
@ -159,7 +129,7 @@ func DelIssueSubscription(ctx *context.APIContext) {
|
|||
}
|
||||
|
||||
// GetIssueSubscribers return subscribers of an issue
|
||||
func GetIssueSubscribers(ctx *context.APIContext, form api.User) {
|
||||
func GetIssueSubscribers(ctx *context.APIContext) {
|
||||
// swagger:operation GET /repos/{owner}/{repo}/issues/{index}/subscriptions issue issueSubscriptions
|
||||
// ---
|
||||
// summary: Get users who subscribed on an issue.
|
||||
|
@ -185,8 +155,8 @@ func GetIssueSubscribers(ctx *context.APIContext, form api.User) {
|
|||
// format: int64
|
||||
// required: true
|
||||
// responses:
|
||||
// "201":
|
||||
// "$ref": "#/responses/empty"
|
||||
// "200":
|
||||
// "$ref": "#/responses/UserList"
|
||||
// "404":
|
||||
// description: Issue not found
|
||||
issue, err := models.GetIssueByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index"))
|
||||
|
|
|
@ -3832,8 +3832,8 @@
|
|||
}
|
||||
],
|
||||
"responses": {
|
||||
"201": {
|
||||
"$ref": "#/responses/empty"
|
||||
"200": {
|
||||
"$ref": "#/responses/UserList"
|
||||
},
|
||||
"404": {
|
||||
"description": "Issue not found"
|
||||
|
|
Reference in a new issue