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 |   is_watching: false | ||||||
|   created_unix: 946684800 |   created_unix: 946684800 | ||||||
|   updated_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. | 	exists, err = e. | ||||||
| 		Where("user_id = ?", userID). | 		Where("user_id = ?", userID). | ||||||
| 		And("issue_id = ?", issueID). | 		And("issue_id = ?", issueID). | ||||||
|  | 		And("is_watching = ?", true). | ||||||
| 		Get(iw) | 		Get(iw) | ||||||
| 	return | 	return | ||||||
| } | } | ||||||
|  | @ -80,6 +81,7 @@ func GetIssueWatchers(issueID int64) (IssueWatchList, error) { | ||||||
| func getIssueWatchers(e Engine, issueID int64) (watches IssueWatchList, err error) { | func getIssueWatchers(e Engine, issueID int64) (watches IssueWatchList, err error) { | ||||||
| 	err = e. | 	err = e. | ||||||
| 		Where("`issue_watch`.issue_id = ?", issueID). | 		Where("`issue_watch`.issue_id = ?", issueID). | ||||||
|  | 		And("`issue_watch`.is_watching = ?", true). | ||||||
| 		And("`user`.is_active = ?", true). | 		And("`user`.is_active = ?", true). | ||||||
| 		And("`user`.prohibit_login = ?", false). | 		And("`user`.prohibit_login = ?", false). | ||||||
| 		Join("INNER", "`user`", "`user`.id = `issue_watch`.user_id"). | 		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)) | 	assert.NoError(t, CreateOrUpdateIssueWatch(3, 1, true)) | ||||||
| 	iw := AssertExistsAndLoadBean(t, &IssueWatch{UserID: 3, IssueID: 1}).(*IssueWatch) | 	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)) | 	assert.NoError(t, CreateOrUpdateIssueWatch(1, 1, false)) | ||||||
| 	iw = AssertExistsAndLoadBean(t, &IssueWatch{UserID: 1, IssueID: 1}).(*IssueWatch) | 	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) { | func TestGetIssueWatch(t *testing.T) { | ||||||
| 	assert.NoError(t, PrepareTestDatabase()) | 	assert.NoError(t, PrepareTestDatabase()) | ||||||
| 
 | 
 | ||||||
| 	_, exists, err := GetIssueWatch(9, 1) | 	_, exists, err := GetIssueWatch(9, 1) | ||||||
| 	assert.Equal(t, true, exists) | 	assert.True(t, exists) | ||||||
| 	assert.NoError(t, err) | 	assert.NoError(t, err) | ||||||
| 
 | 
 | ||||||
| 	_, exists, err = GetIssueWatch(2, 2) | 	_, exists, err = GetIssueWatch(2, 2) | ||||||
| 	assert.Equal(t, true, exists) | 	assert.False(t, exists) | ||||||
| 	assert.NoError(t, err) | 	assert.NoError(t, err) | ||||||
| 
 | 
 | ||||||
| 	_, exists, err = GetIssueWatch(3, 1) | 	_, exists, err = GetIssueWatch(3, 1) | ||||||
| 	assert.Equal(t, false, exists) | 	assert.False(t, exists) | ||||||
| 	assert.NoError(t, err) | 	assert.NoError(t, err) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -44,13 +44,20 @@ func TestGetIssueWatchers(t *testing.T) { | ||||||
| 	iws, err := GetIssueWatchers(1) | 	iws, err := GetIssueWatchers(1) | ||||||
| 	assert.NoError(t, err) | 	assert.NoError(t, err) | ||||||
| 	// Watcher is inactive, thus 0
 | 	// Watcher is inactive, thus 0
 | ||||||
| 	assert.Equal(t, 0, len(iws)) | 	assert.Len(t, iws, 0) | ||||||
| 
 | 
 | ||||||
| 	iws, err = GetIssueWatchers(2) | 	iws, err = GetIssueWatchers(2) | ||||||
| 	assert.NoError(t, err) | 	assert.NoError(t, err) | ||||||
| 	assert.Equal(t, 1, len(iws)) | 	// Watcher is explicit not watching
 | ||||||
|  | 	assert.Len(t, iws, 0) | ||||||
| 
 | 
 | ||||||
| 	iws, err = GetIssueWatchers(5) | 	iws, err = GetIssueWatchers(5) | ||||||
| 	assert.NoError(t, err) | 	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.Post("/stop", reqToken(), repo.StopIssueStopwatch) | ||||||
| 						}) | 						}) | ||||||
| 						m.Group("/subscriptions", func() { | 						m.Group("/subscriptions", func() { | ||||||
| 							m.Get("", bind(api.User{}), repo.GetIssueSubscribers) | 							m.Get("", repo.GetIssueSubscribers) | ||||||
| 							m.Put("/:user", repo.AddIssueSubscription) | 							m.Put("/:user", reqToken(), repo.AddIssueSubscription) | ||||||
| 							m.Delete("/:user", repo.DelIssueSubscription) | 							m.Delete("/:user", reqToken(), repo.DelIssueSubscription) | ||||||
| 						}) | 						}) | ||||||
| 					}) | 					}) | ||||||
| 				}, mustEnableIssuesOrPulls) | 				}, mustEnableIssuesOrPulls) | ||||||
|  |  | ||||||
|  | @ -7,7 +7,6 @@ package repo | ||||||
| import ( | import ( | ||||||
| 	"code.gitea.io/gitea/models" | 	"code.gitea.io/gitea/models" | ||||||
| 	"code.gitea.io/gitea/modules/context" | 	"code.gitea.io/gitea/modules/context" | ||||||
| 	api "code.gitea.io/gitea/modules/structs" |  | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| // AddIssueSubscription Subscribe user to issue
 | // 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
 | 	//     description: User can only subscribe itself if he is no admin
 | ||||||
| 	//   "404":
 | 	//   "404":
 | ||||||
| 	//     description: Issue not found
 | 	//     description: Issue not found
 | ||||||
| 	issue, err := models.GetIssueByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) | 	setIssueSubscription(ctx, true) | ||||||
| 	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) |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // DelIssueSubscription Unsubscribe user from issue
 | // 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
 | 	//     description: User can only subscribe itself if he is no admin
 | ||||||
| 	//   "404":
 | 	//   "404":
 | ||||||
| 	//     description: Issue not found
 | 	//     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")) | 	issue, err := models.GetIssueByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		if models.IsErrIssueNotExist(err) { | 		if models.IsErrIssueNotExist(err) { | ||||||
|  | @ -150,7 +120,7 @@ func DelIssueSubscription(ctx *context.APIContext) { | ||||||
| 		return | 		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) | 		ctx.Error(500, "CreateOrUpdateIssueWatch", err) | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
|  | @ -159,7 +129,7 @@ func DelIssueSubscription(ctx *context.APIContext) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // GetIssueSubscribers return subscribers of an issue
 | // 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
 | 	// swagger:operation GET /repos/{owner}/{repo}/issues/{index}/subscriptions issue issueSubscriptions
 | ||||||
| 	// ---
 | 	// ---
 | ||||||
| 	// summary: Get users who subscribed on an issue.
 | 	// summary: Get users who subscribed on an issue.
 | ||||||
|  | @ -185,8 +155,8 @@ func GetIssueSubscribers(ctx *context.APIContext, form api.User) { | ||||||
| 	//   format: int64
 | 	//   format: int64
 | ||||||
| 	//   required: true
 | 	//   required: true
 | ||||||
| 	// responses:
 | 	// responses:
 | ||||||
| 	//   "201":
 | 	//   "200":
 | ||||||
| 	//     "$ref": "#/responses/empty"
 | 	//     "$ref": "#/responses/UserList"
 | ||||||
| 	//   "404":
 | 	//   "404":
 | ||||||
| 	//     description: Issue not found
 | 	//     description: Issue not found
 | ||||||
| 	issue, err := models.GetIssueByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) | 	issue, err := models.GetIssueByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) | ||||||
|  |  | ||||||
|  | @ -3832,8 +3832,8 @@ | ||||||
|           } |           } | ||||||
|         ], |         ], | ||||||
|         "responses": { |         "responses": { | ||||||
|           "201": { |           "200": { | ||||||
|             "$ref": "#/responses/empty" |             "$ref": "#/responses/UserList" | ||||||
|           }, |           }, | ||||||
|           "404": { |           "404": { | ||||||
|             "description": "Issue not found" |             "description": "Issue not found" | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue