Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[API] Add notification endpoint #9488

Merged
merged 6 commits into from
Jan 9, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
106 changes: 106 additions & 0 deletions integrations/api_notification_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
// Copyright 2020 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package integrations

import (
"fmt"
"net/http"
"testing"
6543 marked this conversation as resolved.
Show resolved Hide resolved

"code.gitea.io/gitea/models"
api "code.gitea.io/gitea/modules/structs"

"github.com/stretchr/testify/assert"
)

func TestAPINotification(t *testing.T) {
defer prepareTestEnv(t)()

user2 := models.AssertExistsAndLoadBean(t, &models.User{ID: 2}).(*models.User)
repo1 := models.AssertExistsAndLoadBean(t, &models.Repository{ID: 1}).(*models.Repository)
thread5 := models.AssertExistsAndLoadBean(t, &models.Notification{ID: 5}).(*models.Notification)
assert.NoError(t, thread5.LoadAttributes())
session := loginUser(t, user2.Name)
token := getTokenForLoggedInUser(t, session)

// -- GET /notifications --
// test filter
since := "2000-01-01T00%3A50%3A01%2B00%3A00" //946687801
req := NewRequest(t, "GET", fmt.Sprintf("/api/v1/notifications?since=%s&token=%s", since, token))
resp := session.MakeRequest(t, req, http.StatusOK)
var apiNL []api.NotificationThread
DecodeJSON(t, resp, &apiNL)

assert.Len(t, apiNL, 1)
assert.EqualValues(t, 5, apiNL[0].ID)

// test filter
before := "2000-01-01T01%3A06%3A59%2B00%3A00" //946688819

req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/notifications?all=%s&before=%s&token=%s", "true", before, token))
resp = session.MakeRequest(t, req, http.StatusOK)
DecodeJSON(t, resp, &apiNL)

assert.Len(t, apiNL, 3)
assert.EqualValues(t, 4, apiNL[0].ID)
assert.EqualValues(t, true, apiNL[0].Unread)
assert.EqualValues(t, false, apiNL[0].Pinned)
assert.EqualValues(t, 3, apiNL[1].ID)
assert.EqualValues(t, false, apiNL[1].Unread)
assert.EqualValues(t, true, apiNL[1].Pinned)
assert.EqualValues(t, 2, apiNL[2].ID)
assert.EqualValues(t, false, apiNL[2].Unread)
assert.EqualValues(t, false, apiNL[2].Pinned)

// -- GET /repos/{owner}/{repo}/notifications --
req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/repos/%s/%s/notifications?token=%s", user2.Name, repo1.Name, token))
resp = session.MakeRequest(t, req, http.StatusOK)
DecodeJSON(t, resp, &apiNL)

assert.Len(t, apiNL, 1)
assert.EqualValues(t, 4, apiNL[0].ID)

// -- GET /notifications/threads/{id} --
// get forbidden
req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/notifications/threads/%d?token=%s", 1, token))
resp = session.MakeRequest(t, req, http.StatusForbidden)

// get own
req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/notifications/threads/%d?token=%s", thread5.ID, token))
resp = session.MakeRequest(t, req, http.StatusOK)
var apiN api.NotificationThread
DecodeJSON(t, resp, &apiN)

assert.EqualValues(t, 5, apiN.ID)
assert.EqualValues(t, false, apiN.Pinned)
assert.EqualValues(t, true, apiN.Unread)
assert.EqualValues(t, "issue4", apiN.Subject.Title)
assert.EqualValues(t, "Issue", apiN.Subject.Type)
assert.EqualValues(t, thread5.Issue.APIURL(), apiN.Subject.URL)
assert.EqualValues(t, thread5.Repository.HTMLURL(), apiN.Repository.HTMLURL)

// -- mark notifications as read --
req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/notifications?token=%s", token))
resp = session.MakeRequest(t, req, http.StatusOK)
DecodeJSON(t, resp, &apiNL)
assert.Len(t, apiNL, 2)

lastReadAt := "2000-01-01T00%3A50%3A01%2B00%3A00" //946687801 <- only Notification 4 is in this filter ...
req = NewRequest(t, "PUT", fmt.Sprintf("/api/v1/repos/%s/%s/notifications?last_read_at=%s&token=%s", user2.Name, repo1.Name, lastReadAt, token))
resp = session.MakeRequest(t, req, http.StatusResetContent)

req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/notifications?token=%s", token))
resp = session.MakeRequest(t, req, http.StatusOK)
DecodeJSON(t, resp, &apiNL)
assert.Len(t, apiNL, 1)

// -- PATCH /notifications/threads/{id} --
req = NewRequest(t, "PATCH", fmt.Sprintf("/api/v1/notifications/threads/%d?token=%s", thread5.ID, token))
resp = session.MakeRequest(t, req, http.StatusResetContent)

assert.Equal(t, models.NotificationStatusUnread, thread5.Status)
thread5 = models.AssertExistsAndLoadBean(t, &models.Notification{ID: 5}).(*models.Notification)
assert.Equal(t, models.NotificationStatusRead, thread5.Status)
}
29 changes: 20 additions & 9 deletions models/fixtures/notification.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
updated_by: 2
issue_id: 1
created_unix: 946684800
updated_unix: 946684800
updated_unix: 946684820

-
id: 2
Expand All @@ -17,8 +17,8 @@
source: 1 # issue
updated_by: 1
issue_id: 2
created_unix: 946684800
updated_unix: 946684800
created_unix: 946685800
updated_unix: 946685820

-
id: 3
Expand All @@ -27,9 +27,9 @@
status: 3 # pinned
source: 1 # issue
updated_by: 1
issue_id: 2
created_unix: 946684800
updated_unix: 946684800
issue_id: 3
created_unix: 946686800
updated_unix: 946686800

-
id: 4
Expand All @@ -38,6 +38,17 @@
status: 1 # unread
source: 1 # issue
updated_by: 1
issue_id: 2
created_unix: 946684800
updated_unix: 946684800
issue_id: 5
created_unix: 946687800
updated_unix: 946687800

-
id: 5
user_id: 2
repo_id: 2
status: 1 # unread
source: 1 # issue
updated_by: 5
issue_id: 4
created_unix: 946688800
updated_unix: 946688820
14 changes: 14 additions & 0 deletions models/issue.go
Original file line number Diff line number Diff line change
Expand Up @@ -843,6 +843,20 @@ func (issue *Issue) GetLastEventLabel() string {
return "repo.issues.opened_by"
}

// GetLastComment return last comment for the current issue.
func (issue *Issue) GetLastComment() (*Comment, error) {
var c Comment
exist, err := x.Where("type = ?", CommentTypeComment).
And("issue_id = ?", issue.ID).Desc("id").Get(&c)
if err != nil {
return nil, err
}
if !exist {
return nil, nil
}
return &c, nil
}

// GetLastEventLabelFake returns the localization label for the current issue without providing a link in the username.
func (issue *Issue) GetLastEventLabelFake() string {
if issue.IsClosed {
Expand Down
17 changes: 17 additions & 0 deletions models/issue_comment.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ package models

import (
"fmt"
"path"
"strings"

"code.gitea.io/gitea/modules/git"
Expand Down Expand Up @@ -235,6 +236,22 @@ func (c *Comment) HTMLURL() string {
return fmt.Sprintf("%s#%s", c.Issue.HTMLURL(), c.HashTag())
}

// APIURL formats a API-string to the issue-comment
func (c *Comment) APIURL() string {
err := c.LoadIssue()
if err != nil { // Silently dropping errors :unamused:
log.Error("LoadIssue(%d): %v", c.IssueID, err)
return ""
}
err = c.Issue.loadRepo(x)
if err != nil { // Silently dropping errors :unamused:
log.Error("loadRepo(%d): %v", c.Issue.RepoID, err)
return ""
}

return c.Issue.Repo.APIURL() + "/" + path.Join("issues/comments", fmt.Sprint(c.ID))
}

// IssueURL formats a URL-string to the issue
func (c *Comment) IssueURL() string {
err := c.LoadIssue()
Expand Down
Loading