MM-11210 Add "GET /posts/unread" API to support landing on the last unread post (#11486)
* [MM-11210] Add API GET 'api/v4/channels/{channel_id:[A-Za-z0-9]+}/posts/unread' for scrolling overhaul (#9108)
* Add API GET 'api/v4/channels/{channel_id:[A-Za-z0-9]+}/posts/unread'
* add constants
* refactor GetPostSince and added more tests
* move constants to app package
* [MM-11528 && MM-11583] Add userId to in the "posts/unread" path and update test with time delay to fix intermittent failure (#9229)
* add userId to in the "posts/unread" path and update test with time delay to fix intermittent failure
* add limit before and after to query
* remove time delay on test and put pretermined value of Post.CreateAt
* Fix conflict
* [MM-11876] Add cursor to posts list such as next_post_id and previous_post_id (#9707)
* add cursor to posts list such as next_post_id and previous_post_id
add publish previous_post_id on WEBSOCKET_EVENT_POSTED and only get next or previous post IDs if necessary
revert change on adding previous_post_id in WEBSOCKET_EVENT_POSTED
add missing strings import
fix merge conflicts
* update per comment
* update per feedback
* corrected the logic in getting the next and previous post ID
* fix logic to determine next and post IDs, and rename function to have suffix of "Time"
* rearrange logics and add mote tests
* fix merge conflict
* fix missing message when using unread API (#10233)
* MM-15569 Fixes failing test on TestGetPostsForChannelAroundLastUnread (#11039)
* Fix missing posts when getting posts since
* revert changes to GetPostsSince
* migrate Post.GetPostAfterTime and Post.GetPostBeforeTime to sync by default
* revert change to cacheItem
* Fix post ID validation, build query on squirrel and only return post ID as necessary
Этот коммит содержится в:
коммит произвёл
Sudheer
родитель
f56a8f5a99
Коммит
b832985f1d
88
api4/post.go
88
api4/post.go
@@ -9,6 +9,7 @@ import (
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/mattermost/mattermost-server/app"
|
||||
"github.com/mattermost/mattermost-server/model"
|
||||
)
|
||||
|
||||
@@ -22,6 +23,8 @@ func (api *API) InitPost() {
|
||||
api.BaseRoutes.PostsForChannel.Handle("", api.ApiSessionRequired(getPostsForChannel)).Methods("GET")
|
||||
api.BaseRoutes.PostsForUser.Handle("/flagged", api.ApiSessionRequired(getFlaggedPostsForUser)).Methods("GET")
|
||||
|
||||
api.BaseRoutes.ChannelForUser.Handle("/posts/unread", api.ApiSessionRequired(getPostsForChannelAroundLastUnread)).Methods("GET")
|
||||
|
||||
api.BaseRoutes.Team.Handle("/posts/search", api.ApiSessionRequired(searchPosts)).Methods("POST")
|
||||
api.BaseRoutes.Post.Handle("", api.ApiSessionRequired(updatePost)).Methods("PUT")
|
||||
api.BaseRoutes.Post.Handle("/patch", api.ApiSessionRequired(patchPost)).Methods("PUT")
|
||||
@@ -109,12 +112,20 @@ func getPostsForChannel(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
afterPost := r.URL.Query().Get("after")
|
||||
beforePost := r.URL.Query().Get("before")
|
||||
sinceString := r.URL.Query().Get("since")
|
||||
if len(afterPost) > 0 && !model.IsValidId(afterPost) {
|
||||
c.SetInvalidParam("after")
|
||||
return
|
||||
}
|
||||
|
||||
beforePost := r.URL.Query().Get("before")
|
||||
if len(beforePost) > 0 && !model.IsValidId(beforePost) {
|
||||
c.SetInvalidParam("before")
|
||||
return
|
||||
}
|
||||
|
||||
sinceString := r.URL.Query().Get("since")
|
||||
var since int64
|
||||
var parseError error
|
||||
|
||||
if len(sinceString) > 0 {
|
||||
since, parseError = strconv.ParseInt(sinceString, 10, 64)
|
||||
if parseError != nil {
|
||||
@@ -123,7 +134,11 @@ func getPostsForChannel(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
}
|
||||
|
||||
if !c.App.SessionHasPermissionToChannel(c.App.Session, c.Params.ChannelId, model.PERMISSION_READ_CHANNEL) {
|
||||
channelId := c.Params.ChannelId
|
||||
page := c.Params.Page
|
||||
perPage := c.Params.PerPage
|
||||
|
||||
if !c.App.SessionHasPermissionToChannel(c.App.Session, channelId, model.PERMISSION_READ_CHANNEL) {
|
||||
c.SetPermissionError(model.PERMISSION_READ_CHANNEL)
|
||||
return
|
||||
}
|
||||
@@ -133,31 +148,31 @@ func getPostsForChannel(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
etag := ""
|
||||
|
||||
if since > 0 {
|
||||
list, err = c.App.GetPostsSince(c.Params.ChannelId, since)
|
||||
list, err = c.App.GetPostsSince(channelId, since)
|
||||
} else if len(afterPost) > 0 {
|
||||
etag = c.App.GetPostsEtag(c.Params.ChannelId)
|
||||
etag = c.App.GetPostsEtag(channelId)
|
||||
|
||||
if c.HandleEtag(etag, "Get Posts After", w, r) {
|
||||
return
|
||||
}
|
||||
|
||||
list, err = c.App.GetPostsAfterPost(c.Params.ChannelId, afterPost, c.Params.Page, c.Params.PerPage)
|
||||
list, err = c.App.GetPostsAfterPost(channelId, afterPost, page, perPage)
|
||||
} else if len(beforePost) > 0 {
|
||||
etag = c.App.GetPostsEtag(c.Params.ChannelId)
|
||||
etag = c.App.GetPostsEtag(channelId)
|
||||
|
||||
if c.HandleEtag(etag, "Get Posts Before", w, r) {
|
||||
return
|
||||
}
|
||||
|
||||
list, err = c.App.GetPostsBeforePost(c.Params.ChannelId, beforePost, c.Params.Page, c.Params.PerPage)
|
||||
list, err = c.App.GetPostsBeforePost(channelId, beforePost, page, perPage)
|
||||
} else {
|
||||
etag = c.App.GetPostsEtag(c.Params.ChannelId)
|
||||
etag = c.App.GetPostsEtag(channelId)
|
||||
|
||||
if c.HandleEtag(etag, "Get Posts", w, r) {
|
||||
return
|
||||
}
|
||||
|
||||
list, err = c.App.GetPostsPage(c.Params.ChannelId, c.Params.Page, c.Params.PerPage)
|
||||
list, err = c.App.GetPostsPage(channelId, page, perPage)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
@@ -169,7 +184,56 @@ func getPostsForChannel(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set(model.HEADER_ETAG_SERVER, etag)
|
||||
}
|
||||
|
||||
w.Write([]byte(c.App.PreparePostListForClient(list).ToJson()))
|
||||
c.App.AddCursorIdsForPostList(list, afterPost, beforePost, since, page, perPage)
|
||||
clientPostList := c.App.PreparePostListForClient(list)
|
||||
|
||||
w.Write([]byte(clientPostList.ToJson()))
|
||||
}
|
||||
|
||||
func getPostsForChannelAroundLastUnread(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
c.RequireUserId().RequireChannelId()
|
||||
if c.Err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
userId := c.Params.UserId
|
||||
if !c.App.SessionHasPermissionToUser(c.App.Session, userId) {
|
||||
c.SetPermissionError(model.PERMISSION_EDIT_OTHER_USERS)
|
||||
return
|
||||
}
|
||||
|
||||
channelId := c.Params.ChannelId
|
||||
if !c.App.SessionHasPermissionToChannel(c.App.Session, channelId, model.PERMISSION_READ_CHANNEL) {
|
||||
c.SetPermissionError(model.PERMISSION_READ_CHANNEL)
|
||||
return
|
||||
}
|
||||
|
||||
postList, err := c.App.GetPostsForChannelAroundLastUnread(channelId, userId, c.Params.LimitBefore, c.Params.LimitAfter)
|
||||
if err != nil {
|
||||
c.Err = err
|
||||
return
|
||||
}
|
||||
|
||||
etag := ""
|
||||
if len(postList.Order) == 0 {
|
||||
etag = c.App.GetPostsEtag(channelId)
|
||||
|
||||
if c.HandleEtag(etag, "Get Posts", w, r) {
|
||||
return
|
||||
}
|
||||
|
||||
postList, err = c.App.GetPostsPage(channelId, app.PAGE_DEFAULT, c.Params.LimitBefore)
|
||||
}
|
||||
|
||||
postList.NextPostId = c.App.GetNextPostIdFromPostList(postList)
|
||||
postList.PrevPostId = c.App.GetPrevPostIdFromPostList(postList)
|
||||
|
||||
clientPostList := c.App.PreparePostListForClient(postList)
|
||||
|
||||
if len(etag) > 0 {
|
||||
w.Header().Set(model.HEADER_ETAG_SERVER, etag)
|
||||
}
|
||||
w.Write([]byte(clientPostList.ToJson()))
|
||||
}
|
||||
|
||||
func getFlaggedPostsForUser(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
Ссылка в новой задаче
Block a user