MM-29987 Implement new collapsed threads API (#16091)
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
483441cea2
Коммит
45e340b5be
@@ -21,6 +21,8 @@ type Routes struct {
|
||||
|
||||
Users *mux.Router // 'api/v4/users'
|
||||
User *mux.Router // 'api/v4/users/{user_id:[A-Za-z0-9]+}'
|
||||
UserThreads *mux.Router // 'api/v4/users/{user_id:[A-Za-z0-9]+}/threads'
|
||||
UserThread *mux.Router // 'api/v4/users/{user_id:[A-Za-z0-9]+}/threads/{thread_id:[A-Za-z0-9]+}'
|
||||
UserByUsername *mux.Router // 'api/v4/users/username/{username:[A-Za-z0-9\\_\\-\\.]+}'
|
||||
UserByEmail *mux.Router // 'api/v4/users/email/{email:.+}'
|
||||
|
||||
@@ -141,6 +143,8 @@ func Init(configservice configservice.ConfigService, globalOptionsFunc app.AppOp
|
||||
|
||||
api.BaseRoutes.Users = api.BaseRoutes.ApiRoot.PathPrefix("/users").Subrouter()
|
||||
api.BaseRoutes.User = api.BaseRoutes.ApiRoot.PathPrefix("/users/{user_id:[A-Za-z0-9]+}").Subrouter()
|
||||
api.BaseRoutes.UserThreads = api.BaseRoutes.ApiRoot.PathPrefix("/users/{user_id:[A-Za-z0-9]+}/threads").Subrouter()
|
||||
api.BaseRoutes.UserThread = api.BaseRoutes.ApiRoot.PathPrefix("/users/{user_id:[A-Za-z0-9]+}/threads/{thread_id:[A-Za-z0-9]+}").Subrouter()
|
||||
api.BaseRoutes.UserByUsername = api.BaseRoutes.Users.PathPrefix("/username/{username:[A-Za-z0-9\\_\\-\\.]+}").Subrouter()
|
||||
api.BaseRoutes.UserByEmail = api.BaseRoutes.Users.PathPrefix("/email/{email:.+}").Subrouter()
|
||||
|
||||
|
||||
177
api4/user.go
177
api4/user.go
@@ -91,6 +91,13 @@ func (api *API) InitUser() {
|
||||
api.BaseRoutes.Users.Handle("/migrate_auth/saml", api.ApiSessionRequired(migrateAuthToSaml)).Methods("POST")
|
||||
|
||||
api.BaseRoutes.User.Handle("/uploads", api.ApiSessionRequired(getUploadsForUser)).Methods("GET")
|
||||
|
||||
api.BaseRoutes.UserThreads.Handle("", api.ApiSessionRequired(getThreadsForUser)).Methods("GET")
|
||||
api.BaseRoutes.UserThreads.Handle("/read/{timestamp:[0-9]+}", api.ApiSessionRequired(updateReadStateAllThreadsByUser)).Methods("PUT")
|
||||
|
||||
api.BaseRoutes.UserThread.Handle("/following", api.ApiSessionRequired(followThreadByUser)).Methods("PUT")
|
||||
api.BaseRoutes.UserThread.Handle("/following", api.ApiSessionRequired(unfollowThreadByUser)).Methods("DELETE")
|
||||
api.BaseRoutes.UserThread.Handle("/read/{timestamp:[0-9]+}", api.ApiSessionRequired(updateReadStateThreadByUser)).Methods("PUT")
|
||||
}
|
||||
|
||||
func createUser(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
@@ -2806,3 +2813,173 @@ func migrateAuthToSaml(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
auditRec.Success()
|
||||
ReturnStatusOK(w)
|
||||
}
|
||||
|
||||
func getThreadsForUser(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
c.RequireUserId()
|
||||
if c.Err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if !c.App.SessionHasPermissionToUser(*c.App.Session(), c.Params.UserId) {
|
||||
c.SetPermissionError(model.PERMISSION_EDIT_OTHER_USERS)
|
||||
return
|
||||
}
|
||||
|
||||
options := model.GetUserThreadsOpts{
|
||||
Since: 0,
|
||||
Page: 0,
|
||||
PageSize: 30,
|
||||
Extended: false,
|
||||
Deleted: false,
|
||||
}
|
||||
|
||||
sinceString := r.URL.Query().Get("since")
|
||||
if len(sinceString) > 0 {
|
||||
since, parseError := strconv.ParseUint(sinceString, 10, 64)
|
||||
if parseError != nil {
|
||||
c.SetInvalidParam("since")
|
||||
return
|
||||
}
|
||||
options.Since = since
|
||||
}
|
||||
|
||||
pageString := r.URL.Query().Get("page")
|
||||
if len(pageString) > 0 {
|
||||
page, parseError := strconv.ParseUint(pageString, 10, 64)
|
||||
if parseError != nil {
|
||||
c.SetInvalidParam("page")
|
||||
return
|
||||
}
|
||||
options.Page = page
|
||||
}
|
||||
|
||||
pageSizeString := r.URL.Query().Get("pageSize")
|
||||
if len(pageString) > 0 {
|
||||
pageSize, parseError := strconv.ParseUint(pageSizeString, 10, 64)
|
||||
if parseError != nil {
|
||||
c.SetInvalidParam("pageSize")
|
||||
return
|
||||
}
|
||||
options.PageSize = pageSize
|
||||
}
|
||||
|
||||
deletedStr := r.URL.Query().Get("deleted")
|
||||
extendedStr := r.URL.Query().Get("extended")
|
||||
|
||||
options.Deleted, _ = strconv.ParseBool(deletedStr)
|
||||
options.Extended, _ = strconv.ParseBool(extendedStr)
|
||||
|
||||
threads, err := c.App.GetThreadsForUser(c.Params.UserId, options)
|
||||
if err != nil {
|
||||
c.Err = err
|
||||
return
|
||||
}
|
||||
|
||||
w.Write([]byte(threads.ToJson()))
|
||||
}
|
||||
|
||||
func updateReadStateThreadByUser(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
c.RequireUserId().RequireThreadId().RequireTimestamp()
|
||||
if c.Err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
auditRec := c.MakeAuditRecord("updateReadStateThreadByUser", audit.Fail)
|
||||
defer c.LogAuditRec(auditRec)
|
||||
auditRec.AddMeta("user_id", c.Params.UserId)
|
||||
auditRec.AddMeta("thread_id", c.Params.ThreadId)
|
||||
auditRec.AddMeta("timestamp", c.Params.Timestamp)
|
||||
if !c.App.SessionHasPermissionToUser(*c.App.Session(), c.Params.UserId) {
|
||||
c.SetPermissionError(model.PERMISSION_EDIT_OTHER_USERS)
|
||||
return
|
||||
}
|
||||
|
||||
err := c.App.UpdateThreadReadForUser(c.Params.UserId, c.Params.ThreadId, c.Params.Timestamp)
|
||||
if err != nil {
|
||||
c.Err = err
|
||||
return
|
||||
}
|
||||
|
||||
ReturnStatusOK(w)
|
||||
|
||||
auditRec.Success()
|
||||
}
|
||||
|
||||
func unfollowThreadByUser(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
c.RequireUserId().RequireThreadId()
|
||||
if c.Err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
auditRec := c.MakeAuditRecord("unfollowThreadByUser", audit.Fail)
|
||||
defer c.LogAuditRec(auditRec)
|
||||
auditRec.AddMeta("user_id", c.Params.UserId)
|
||||
auditRec.AddMeta("thread_id", c.Params.ThreadId)
|
||||
|
||||
if !c.App.SessionHasPermissionToUser(*c.App.Session(), c.Params.UserId) {
|
||||
c.SetPermissionError(model.PERMISSION_EDIT_OTHER_USERS)
|
||||
return
|
||||
}
|
||||
|
||||
err := c.App.UpdateThreadFollowForUser(c.Params.UserId, c.Params.ThreadId, false)
|
||||
if err != nil {
|
||||
c.Err = err
|
||||
return
|
||||
}
|
||||
|
||||
ReturnStatusOK(w)
|
||||
|
||||
auditRec.Success()
|
||||
}
|
||||
|
||||
func followThreadByUser(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
c.RequireUserId().RequireThreadId()
|
||||
if c.Err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
auditRec := c.MakeAuditRecord("followThreadByUser", audit.Fail)
|
||||
defer c.LogAuditRec(auditRec)
|
||||
auditRec.AddMeta("user_id", c.Params.UserId)
|
||||
auditRec.AddMeta("thread_id", c.Params.ThreadId)
|
||||
|
||||
if !c.App.SessionHasPermissionToUser(*c.App.Session(), c.Params.UserId) {
|
||||
c.SetPermissionError(model.PERMISSION_EDIT_OTHER_USERS)
|
||||
return
|
||||
}
|
||||
|
||||
err := c.App.UpdateThreadFollowForUser(c.Params.UserId, c.Params.ThreadId, true)
|
||||
if err != nil {
|
||||
c.Err = err
|
||||
return
|
||||
}
|
||||
|
||||
ReturnStatusOK(w)
|
||||
auditRec.Success()
|
||||
}
|
||||
|
||||
func updateReadStateAllThreadsByUser(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
c.RequireUserId().RequireTimestamp()
|
||||
if c.Err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
auditRec := c.MakeAuditRecord("updateReadStateAllThreadsByUser", audit.Fail)
|
||||
defer c.LogAuditRec(auditRec)
|
||||
auditRec.AddMeta("user_id", c.Params.UserId)
|
||||
auditRec.AddMeta("timestamp", c.Params.Timestamp)
|
||||
|
||||
if !c.App.SessionHasPermissionToUser(*c.App.Session(), c.Params.UserId) {
|
||||
c.SetPermissionError(model.PERMISSION_EDIT_OTHER_USERS)
|
||||
return
|
||||
}
|
||||
|
||||
err := c.App.UpdateThreadsReadForUser(c.Params.UserId, c.Params.Timestamp)
|
||||
if err != nil {
|
||||
c.Err = err
|
||||
return
|
||||
}
|
||||
|
||||
ReturnStatusOK(w)
|
||||
auditRec.Success()
|
||||
}
|
||||
|
||||
@@ -5255,3 +5255,308 @@ func TestUpdatePassword(t *testing.T) {
|
||||
CheckOKStatus(t, res)
|
||||
})
|
||||
}
|
||||
|
||||
func TestGetThreadsForUser(t *testing.T) {
|
||||
th := Setup(t).InitBasic()
|
||||
defer th.TearDown()
|
||||
|
||||
t.Run("empty", func(t *testing.T) {
|
||||
Client := th.Client
|
||||
|
||||
_, resp := Client.CreatePost(&model.Post{ChannelId: th.BasicChannel.Id, Message: "testMsg"})
|
||||
CheckNoError(t, resp)
|
||||
CheckCreatedStatus(t, resp)
|
||||
|
||||
defer th.App.Srv().Store.Post().PermanentDeleteByUser(th.BasicUser.Id)
|
||||
|
||||
uss, resp := th.Client.GetUserThreads(th.BasicUser.Id, model.GetUserThreadsOpts{
|
||||
Page: 0,
|
||||
PageSize: 30,
|
||||
})
|
||||
require.Nil(t, resp.Error)
|
||||
require.Len(t, uss.Threads, 0)
|
||||
})
|
||||
|
||||
t.Run("no params, 1 thread", func(t *testing.T) {
|
||||
Client := th.Client
|
||||
|
||||
rpost, resp := Client.CreatePost(&model.Post{ChannelId: th.BasicChannel.Id, Message: "testMsg"})
|
||||
CheckNoError(t, resp)
|
||||
CheckCreatedStatus(t, resp)
|
||||
_, resp2 := Client.CreatePost(&model.Post{ChannelId: th.BasicChannel.Id, Message: "testReply", RootId: rpost.Id})
|
||||
CheckNoError(t, resp2)
|
||||
CheckCreatedStatus(t, resp2)
|
||||
|
||||
defer th.App.Srv().Store.Post().PermanentDeleteByUser(th.BasicUser.Id)
|
||||
|
||||
uss, resp := th.Client.GetUserThreads(th.BasicUser.Id, model.GetUserThreadsOpts{
|
||||
Page: 0,
|
||||
PageSize: 30,
|
||||
})
|
||||
require.Nil(t, resp.Error)
|
||||
require.Len(t, uss.Threads, 1)
|
||||
require.Equal(t, uss.Threads[0].PostId, rpost.Id)
|
||||
require.Equal(t, uss.Threads[0].ReplyCount, int64(1))
|
||||
})
|
||||
|
||||
t.Run("extended, 1 thread", func(t *testing.T) {
|
||||
Client := th.Client
|
||||
|
||||
rpost, resp := Client.CreatePost(&model.Post{ChannelId: th.BasicChannel.Id, Message: "testMsg"})
|
||||
CheckNoError(t, resp)
|
||||
CheckCreatedStatus(t, resp)
|
||||
_, resp2 := Client.CreatePost(&model.Post{ChannelId: th.BasicChannel.Id, Message: "testReply", RootId: rpost.Id})
|
||||
CheckNoError(t, resp2)
|
||||
CheckCreatedStatus(t, resp2)
|
||||
|
||||
defer th.App.Srv().Store.Post().PermanentDeleteByUser(th.BasicUser.Id)
|
||||
|
||||
uss, resp := th.Client.GetUserThreads(th.BasicUser.Id, model.GetUserThreadsOpts{
|
||||
Page: 0,
|
||||
PageSize: 30,
|
||||
Extended: true,
|
||||
})
|
||||
require.Nil(t, resp.Error)
|
||||
require.Len(t, uss.Threads, 1)
|
||||
require.Equal(t, uss.Threads[0].PostId, rpost.Id)
|
||||
require.Equal(t, uss.Threads[0].ReplyCount, int64(1))
|
||||
require.Equal(t, uss.Threads[0].Participants[0].Id, th.BasicUser.Id)
|
||||
})
|
||||
|
||||
t.Run("deleted, 1 thread", func(t *testing.T) {
|
||||
Client := th.Client
|
||||
|
||||
rpost, resp := Client.CreatePost(&model.Post{ChannelId: th.BasicChannel.Id, Message: "testMsg"})
|
||||
CheckNoError(t, resp)
|
||||
CheckCreatedStatus(t, resp)
|
||||
_, resp2 := Client.CreatePost(&model.Post{ChannelId: th.BasicChannel.Id, Message: "testReply", RootId: rpost.Id})
|
||||
CheckNoError(t, resp2)
|
||||
CheckCreatedStatus(t, resp2)
|
||||
|
||||
defer th.App.Srv().Store.Post().PermanentDeleteByUser(th.BasicUser.Id)
|
||||
|
||||
uss, resp := th.Client.GetUserThreads(th.BasicUser.Id, model.GetUserThreadsOpts{
|
||||
Page: 0,
|
||||
PageSize: 30,
|
||||
Deleted: false,
|
||||
})
|
||||
require.Nil(t, resp.Error)
|
||||
require.Len(t, uss.Threads, 1)
|
||||
require.Equal(t, uss.Threads[0].PostId, rpost.Id)
|
||||
require.Equal(t, uss.Threads[0].ReplyCount, int64(1))
|
||||
require.Equal(t, uss.Threads[0].Participants[0].Id, th.BasicUser.Id)
|
||||
|
||||
res, resp2 := th.Client.DeletePost(rpost.Id)
|
||||
require.True(t, res)
|
||||
require.Nil(t, resp2.Error)
|
||||
|
||||
uss, resp = th.Client.GetUserThreads(th.BasicUser.Id, model.GetUserThreadsOpts{
|
||||
Page: 0,
|
||||
PageSize: 30,
|
||||
Deleted: false,
|
||||
})
|
||||
require.Nil(t, resp.Error)
|
||||
require.Len(t, uss.Threads, 0)
|
||||
|
||||
uss, resp = th.Client.GetUserThreads(th.BasicUser.Id, model.GetUserThreadsOpts{
|
||||
Page: 0,
|
||||
PageSize: 30,
|
||||
Deleted: true,
|
||||
})
|
||||
require.Nil(t, resp.Error)
|
||||
require.Len(t, uss.Threads, 1)
|
||||
require.Greater(t, uss.Threads[0].Post.DeleteAt, int64(0))
|
||||
|
||||
})
|
||||
|
||||
t.Run("paged, 30 threads", func(t *testing.T) {
|
||||
Client := th.Client
|
||||
|
||||
var rootIds []*model.Post
|
||||
for i := 0; i < 30; i++ {
|
||||
time.Sleep(1)
|
||||
rpost, resp := Client.CreatePost(&model.Post{ChannelId: th.BasicChannel.Id, Message: "testMsg"})
|
||||
CheckNoError(t, resp)
|
||||
CheckCreatedStatus(t, resp)
|
||||
rootIds = append(rootIds, rpost)
|
||||
time.Sleep(1)
|
||||
_, resp2 := Client.CreatePost(&model.Post{ChannelId: th.BasicChannel.Id, Message: "testReply", RootId: rpost.Id})
|
||||
CheckNoError(t, resp2)
|
||||
CheckCreatedStatus(t, resp2)
|
||||
}
|
||||
|
||||
defer th.App.Srv().Store.Post().PermanentDeleteByUser(th.BasicUser.Id)
|
||||
|
||||
uss, resp := th.Client.GetUserThreads(th.BasicUser.Id, model.GetUserThreadsOpts{
|
||||
Page: 0,
|
||||
PageSize: 30,
|
||||
Deleted: false,
|
||||
})
|
||||
require.Nil(t, resp.Error)
|
||||
require.Len(t, uss.Threads, 30)
|
||||
require.Len(t, rootIds, 30)
|
||||
require.Equal(t, uss.Threads[0].PostId, rootIds[29].Id)
|
||||
require.Equal(t, uss.Threads[0].ReplyCount, int64(1))
|
||||
require.Equal(t, uss.Threads[0].Participants[0].Id, th.BasicUser.Id)
|
||||
})
|
||||
}
|
||||
|
||||
func TestFollowThreads(t *testing.T) {
|
||||
th := Setup(t).InitBasic()
|
||||
defer th.TearDown()
|
||||
|
||||
t.Run("1 thread", func(t *testing.T) {
|
||||
Client := th.Client
|
||||
|
||||
rpost, resp := Client.CreatePost(&model.Post{ChannelId: th.BasicChannel.Id, Message: "testMsg"})
|
||||
CheckNoError(t, resp)
|
||||
CheckCreatedStatus(t, resp)
|
||||
_, resp2 := Client.CreatePost(&model.Post{ChannelId: th.BasicChannel.Id, Message: "testReply", RootId: rpost.Id})
|
||||
CheckNoError(t, resp2)
|
||||
CheckCreatedStatus(t, resp2)
|
||||
|
||||
defer th.App.Srv().Store.Post().PermanentDeleteByUser(th.BasicUser.Id)
|
||||
var uss *model.Threads
|
||||
uss, resp = th.Client.GetUserThreads(th.BasicUser.Id, model.GetUserThreadsOpts{
|
||||
Page: 0,
|
||||
PageSize: 30,
|
||||
Deleted: false,
|
||||
})
|
||||
CheckNoError(t, resp)
|
||||
require.Len(t, uss.Threads, 1)
|
||||
|
||||
resp = th.Client.UpdateThreadFollowForUser(th.BasicUser.Id, rpost.Id, false)
|
||||
CheckNoError(t, resp)
|
||||
CheckOKStatus(t, resp)
|
||||
|
||||
uss, resp = th.Client.GetUserThreads(th.BasicUser.Id, model.GetUserThreadsOpts{
|
||||
Page: 0,
|
||||
PageSize: 30,
|
||||
Deleted: false,
|
||||
})
|
||||
CheckNoError(t, resp)
|
||||
require.Len(t, uss.Threads, 0)
|
||||
|
||||
resp = th.Client.UpdateThreadFollowForUser(th.BasicUser.Id, rpost.Id, true)
|
||||
CheckNoError(t, resp)
|
||||
CheckOKStatus(t, resp)
|
||||
|
||||
uss, resp = th.Client.GetUserThreads(th.BasicUser.Id, model.GetUserThreadsOpts{
|
||||
Page: 0,
|
||||
PageSize: 30,
|
||||
Deleted: false,
|
||||
})
|
||||
CheckNoError(t, resp)
|
||||
require.Len(t, uss.Threads, 1)
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
func TestReadThreads(t *testing.T) {
|
||||
th := Setup(t).InitBasic()
|
||||
defer th.TearDown()
|
||||
|
||||
t.Run("all threads", func(t *testing.T) {
|
||||
Client := th.Client
|
||||
|
||||
rpost, resp := Client.CreatePost(&model.Post{ChannelId: th.BasicChannel.Id, Message: "testMsg"})
|
||||
CheckNoError(t, resp)
|
||||
CheckCreatedStatus(t, resp)
|
||||
rpost2, resp2 := Client.CreatePost(&model.Post{ChannelId: th.BasicChannel.Id, Message: "testReply", RootId: rpost.Id})
|
||||
CheckNoError(t, resp2)
|
||||
CheckCreatedStatus(t, resp2)
|
||||
defer th.App.Srv().Store.Post().PermanentDeleteByUser(th.BasicUser.Id)
|
||||
|
||||
var uss, uss2, uss3 *model.Threads
|
||||
uss, resp = th.Client.GetUserThreads(th.BasicUser.Id, model.GetUserThreadsOpts{
|
||||
Page: 0,
|
||||
PageSize: 30,
|
||||
Deleted: false,
|
||||
})
|
||||
CheckNoError(t, resp)
|
||||
require.Len(t, uss.Threads, 1)
|
||||
|
||||
time.Sleep(1)
|
||||
resp = th.Client.UpdateThreadsReadForUser(th.BasicUser.Id, model.GetMillis())
|
||||
CheckNoError(t, resp)
|
||||
CheckOKStatus(t, resp)
|
||||
|
||||
uss2, resp = th.Client.GetUserThreads(th.BasicUser.Id, model.GetUserThreadsOpts{
|
||||
Page: 0,
|
||||
PageSize: 30,
|
||||
Deleted: false,
|
||||
})
|
||||
CheckNoError(t, resp)
|
||||
require.Len(t, uss2.Threads, 1)
|
||||
require.Greater(t, uss2.Threads[0].LastViewedAt, uss.Threads[0].LastViewedAt)
|
||||
|
||||
resp = th.Client.UpdateThreadsReadForUser(th.BasicUser.Id, rpost2.UpdateAt)
|
||||
CheckNoError(t, resp)
|
||||
CheckOKStatus(t, resp)
|
||||
|
||||
uss3, resp = th.Client.GetUserThreads(th.BasicUser.Id, model.GetUserThreadsOpts{
|
||||
Page: 0,
|
||||
PageSize: 30,
|
||||
Deleted: false,
|
||||
})
|
||||
CheckNoError(t, resp)
|
||||
require.Len(t, uss3.Threads, 1)
|
||||
require.Equal(t, uss3.Threads[0].LastViewedAt, rpost2.UpdateAt)
|
||||
})
|
||||
|
||||
t.Run("1 thread", func(t *testing.T) {
|
||||
Client := th.Client
|
||||
|
||||
rpost, resp := Client.CreatePost(&model.Post{ChannelId: th.BasicChannel.Id, Message: "testMsg"})
|
||||
CheckNoError(t, resp)
|
||||
CheckCreatedStatus(t, resp)
|
||||
_, resp2 := Client.CreatePost(&model.Post{ChannelId: th.BasicChannel.Id, Message: "testReply", RootId: rpost.Id})
|
||||
CheckNoError(t, resp2)
|
||||
CheckCreatedStatus(t, resp2)
|
||||
|
||||
rrpost, rresp := Client.CreatePost(&model.Post{ChannelId: th.BasicChannel.Id, Message: "testMsg"})
|
||||
CheckNoError(t, rresp)
|
||||
CheckCreatedStatus(t, rresp)
|
||||
_, rresp2 := Client.CreatePost(&model.Post{ChannelId: th.BasicChannel.Id, Message: "testReply", RootId: rrpost.Id})
|
||||
CheckNoError(t, rresp2)
|
||||
CheckCreatedStatus(t, rresp2)
|
||||
|
||||
defer th.App.Srv().Store.Post().PermanentDeleteByUser(th.BasicUser.Id)
|
||||
|
||||
var uss, uss2, uss3 *model.Threads
|
||||
uss, resp = th.Client.GetUserThreads(th.BasicUser.Id, model.GetUserThreadsOpts{
|
||||
Page: 0,
|
||||
PageSize: 30,
|
||||
Deleted: false,
|
||||
})
|
||||
CheckNoError(t, resp)
|
||||
require.Len(t, uss.Threads, 2)
|
||||
|
||||
resp = th.Client.UpdateThreadReadForUser(th.BasicUser.Id, rrpost.Id, model.GetMillis())
|
||||
CheckNoError(t, resp)
|
||||
CheckOKStatus(t, resp)
|
||||
|
||||
uss2, resp = th.Client.GetUserThreads(th.BasicUser.Id, model.GetUserThreadsOpts{
|
||||
Page: 0,
|
||||
PageSize: 30,
|
||||
Deleted: false,
|
||||
})
|
||||
CheckNoError(t, resp)
|
||||
require.Len(t, uss2.Threads, 2)
|
||||
require.Greater(t, uss2.Threads[1].LastViewedAt, uss.Threads[1].LastViewedAt)
|
||||
|
||||
timestamp := model.GetMillis()
|
||||
resp = th.Client.UpdateThreadReadForUser(th.BasicUser.Id, rrpost.Id, timestamp)
|
||||
CheckNoError(t, resp)
|
||||
CheckOKStatus(t, resp)
|
||||
|
||||
uss3, resp = th.Client.GetUserThreads(th.BasicUser.Id, model.GetUserThreadsOpts{
|
||||
Page: 0,
|
||||
PageSize: 30,
|
||||
Deleted: false,
|
||||
})
|
||||
CheckNoError(t, resp)
|
||||
require.Len(t, uss3.Threads, 2)
|
||||
require.Equal(t, uss3.Threads[1].LastViewedAt, timestamp)
|
||||
})
|
||||
}
|
||||
|
||||
Ссылка в новой задаче
Block a user