MM-30558 - Add unreadReplies and unreadMentions to thread membership (#16304)
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
cd9185fa23
Коммит
86e228b6c6
@@ -21,8 +21,6 @@ type Routes struct {
|
|||||||
|
|
||||||
Users *mux.Router // 'api/v4/users'
|
Users *mux.Router // 'api/v4/users'
|
||||||
User *mux.Router // 'api/v4/users/{user_id:[A-Za-z0-9]+}'
|
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\\_\\-\\.]+}'
|
UserByUsername *mux.Router // 'api/v4/users/username/{username:[A-Za-z0-9\\_\\-\\.]+}'
|
||||||
UserByEmail *mux.Router // 'api/v4/users/email/{email:.+}'
|
UserByEmail *mux.Router // 'api/v4/users/email/{email:.+}'
|
||||||
|
|
||||||
@@ -33,6 +31,8 @@ type Routes struct {
|
|||||||
TeamsForUser *mux.Router // 'api/v4/users/{user_id:[A-Za-z0-9]+}/teams'
|
TeamsForUser *mux.Router // 'api/v4/users/{user_id:[A-Za-z0-9]+}/teams'
|
||||||
Team *mux.Router // 'api/v4/teams/{team_id:[A-Za-z0-9]+}'
|
Team *mux.Router // 'api/v4/teams/{team_id:[A-Za-z0-9]+}'
|
||||||
TeamForUser *mux.Router // 'api/v4/users/{user_id:[A-Za-z0-9]+}/teams/{team_id:[A-Za-z0-9]+}'
|
TeamForUser *mux.Router // 'api/v4/users/{user_id:[A-Za-z0-9]+}/teams/{team_id:[A-Za-z0-9]+}'
|
||||||
|
UserThreads *mux.Router // 'api/v4/users/{user_id:[A-Za-z0-9]+}/teams/{team_id:[A-Za-z0-9]+}/threads'
|
||||||
|
UserThread *mux.Router // 'api/v4/users/{user_id:[A-Za-z0-9]+}/teams/{team_id:[A-Za-z0-9]+}/threads/{thread_id:[A-Za-z0-9]+}'
|
||||||
TeamByName *mux.Router // 'api/v4/teams/name/{team_name:[A-Za-z0-9_-]+}'
|
TeamByName *mux.Router // 'api/v4/teams/name/{team_name:[A-Za-z0-9_-]+}'
|
||||||
TeamMembers *mux.Router // 'api/v4/teams/{team_id:[A-Za-z0-9]+}/members'
|
TeamMembers *mux.Router // 'api/v4/teams/{team_id:[A-Za-z0-9]+}/members'
|
||||||
TeamMember *mux.Router // 'api/v4/teams/{team_id:[A-Za-z0-9]+}/members/{user_id:[A-Za-z0-9]+}'
|
TeamMember *mux.Router // 'api/v4/teams/{team_id:[A-Za-z0-9]+}/members/{user_id:[A-Za-z0-9]+}'
|
||||||
@@ -145,8 +145,6 @@ func Init(configservice configservice.ConfigService, globalOptionsFunc app.AppOp
|
|||||||
|
|
||||||
api.BaseRoutes.Users = api.BaseRoutes.ApiRoot.PathPrefix("/users").Subrouter()
|
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.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.UserByUsername = api.BaseRoutes.Users.PathPrefix("/username/{username:[A-Za-z0-9\\_\\-\\.]+}").Subrouter()
|
||||||
api.BaseRoutes.UserByEmail = api.BaseRoutes.Users.PathPrefix("/email/{email:.+}").Subrouter()
|
api.BaseRoutes.UserByEmail = api.BaseRoutes.Users.PathPrefix("/email/{email:.+}").Subrouter()
|
||||||
|
|
||||||
@@ -157,6 +155,8 @@ func Init(configservice configservice.ConfigService, globalOptionsFunc app.AppOp
|
|||||||
api.BaseRoutes.TeamsForUser = api.BaseRoutes.User.PathPrefix("/teams").Subrouter()
|
api.BaseRoutes.TeamsForUser = api.BaseRoutes.User.PathPrefix("/teams").Subrouter()
|
||||||
api.BaseRoutes.Team = api.BaseRoutes.Teams.PathPrefix("/{team_id:[A-Za-z0-9]+}").Subrouter()
|
api.BaseRoutes.Team = api.BaseRoutes.Teams.PathPrefix("/{team_id:[A-Za-z0-9]+}").Subrouter()
|
||||||
api.BaseRoutes.TeamForUser = api.BaseRoutes.TeamsForUser.PathPrefix("/{team_id:[A-Za-z0-9]+}").Subrouter()
|
api.BaseRoutes.TeamForUser = api.BaseRoutes.TeamsForUser.PathPrefix("/{team_id:[A-Za-z0-9]+}").Subrouter()
|
||||||
|
api.BaseRoutes.UserThreads = api.BaseRoutes.TeamForUser.PathPrefix("/threads").Subrouter()
|
||||||
|
api.BaseRoutes.UserThread = api.BaseRoutes.TeamForUser.PathPrefix("/threads/{thread_id:[A-Za-z0-9]+}").Subrouter()
|
||||||
api.BaseRoutes.TeamByName = api.BaseRoutes.Teams.PathPrefix("/name/{team_name:[A-Za-z0-9_-]+}").Subrouter()
|
api.BaseRoutes.TeamByName = api.BaseRoutes.Teams.PathPrefix("/name/{team_name:[A-Za-z0-9_-]+}").Subrouter()
|
||||||
api.BaseRoutes.TeamMembers = api.BaseRoutes.Team.PathPrefix("/members").Subrouter()
|
api.BaseRoutes.TeamMembers = api.BaseRoutes.Team.PathPrefix("/members").Subrouter()
|
||||||
api.BaseRoutes.TeamMember = api.BaseRoutes.TeamMembers.PathPrefix("/{user_id:[A-Za-z0-9]+}").Subrouter()
|
api.BaseRoutes.TeamMember = api.BaseRoutes.TeamMembers.PathPrefix("/{user_id:[A-Za-z0-9]+}").Subrouter()
|
||||||
|
|||||||
23
api4/user.go
23
api4/user.go
@@ -93,7 +93,7 @@ func (api *API) InitUser() {
|
|||||||
api.BaseRoutes.User.Handle("/uploads", api.ApiSessionRequired(getUploadsForUser)).Methods("GET")
|
api.BaseRoutes.User.Handle("/uploads", api.ApiSessionRequired(getUploadsForUser)).Methods("GET")
|
||||||
|
|
||||||
api.BaseRoutes.UserThreads.Handle("", api.ApiSessionRequired(getThreadsForUser)).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.UserThreads.Handle("/read", api.ApiSessionRequired(updateReadStateAllThreadsByUser)).Methods("PUT")
|
||||||
|
|
||||||
api.BaseRoutes.UserThread.Handle("/following", api.ApiSessionRequired(followThreadByUser)).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("/following", api.ApiSessionRequired(unfollowThreadByUser)).Methods("DELETE")
|
||||||
@@ -2815,7 +2815,7 @@ func migrateAuthToSaml(c *Context, w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func getThreadsForUser(c *Context, w http.ResponseWriter, r *http.Request) {
|
func getThreadsForUser(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||||
c.RequireUserId()
|
c.RequireUserId().RequireTeamId()
|
||||||
if c.Err != nil {
|
if c.Err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -2869,7 +2869,7 @@ func getThreadsForUser(c *Context, w http.ResponseWriter, r *http.Request) {
|
|||||||
options.Deleted, _ = strconv.ParseBool(deletedStr)
|
options.Deleted, _ = strconv.ParseBool(deletedStr)
|
||||||
options.Extended, _ = strconv.ParseBool(extendedStr)
|
options.Extended, _ = strconv.ParseBool(extendedStr)
|
||||||
|
|
||||||
threads, err := c.App.GetThreadsForUser(c.Params.UserId, options)
|
threads, err := c.App.GetThreadsForUser(c.Params.UserId, c.Params.TeamId, options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.Err = err
|
c.Err = err
|
||||||
return
|
return
|
||||||
@@ -2879,7 +2879,7 @@ func getThreadsForUser(c *Context, w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func updateReadStateThreadByUser(c *Context, w http.ResponseWriter, r *http.Request) {
|
func updateReadStateThreadByUser(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||||
c.RequireUserId().RequireThreadId().RequireTimestamp()
|
c.RequireUserId().RequireThreadId().RequireTimestamp().RequireTeamId()
|
||||||
if c.Err != nil {
|
if c.Err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -2888,13 +2888,14 @@ func updateReadStateThreadByUser(c *Context, w http.ResponseWriter, r *http.Requ
|
|||||||
defer c.LogAuditRec(auditRec)
|
defer c.LogAuditRec(auditRec)
|
||||||
auditRec.AddMeta("user_id", c.Params.UserId)
|
auditRec.AddMeta("user_id", c.Params.UserId)
|
||||||
auditRec.AddMeta("thread_id", c.Params.ThreadId)
|
auditRec.AddMeta("thread_id", c.Params.ThreadId)
|
||||||
|
auditRec.AddMeta("team_id", c.Params.TeamId)
|
||||||
auditRec.AddMeta("timestamp", c.Params.Timestamp)
|
auditRec.AddMeta("timestamp", c.Params.Timestamp)
|
||||||
if !c.App.SessionHasPermissionToUser(*c.App.Session(), c.Params.UserId) {
|
if !c.App.SessionHasPermissionToUser(*c.App.Session(), c.Params.UserId) {
|
||||||
c.SetPermissionError(model.PERMISSION_EDIT_OTHER_USERS)
|
c.SetPermissionError(model.PERMISSION_EDIT_OTHER_USERS)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err := c.App.UpdateThreadReadForUser(c.Params.UserId, c.Params.ThreadId, c.Params.Timestamp)
|
err := c.App.UpdateThreadReadForUser(c.Params.UserId, c.Params.TeamId, c.Params.ThreadId, c.Params.Timestamp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.Err = err
|
c.Err = err
|
||||||
return
|
return
|
||||||
@@ -2906,7 +2907,7 @@ func updateReadStateThreadByUser(c *Context, w http.ResponseWriter, r *http.Requ
|
|||||||
}
|
}
|
||||||
|
|
||||||
func unfollowThreadByUser(c *Context, w http.ResponseWriter, r *http.Request) {
|
func unfollowThreadByUser(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||||
c.RequireUserId().RequireThreadId()
|
c.RequireUserId().RequireThreadId().RequireTeamId()
|
||||||
if c.Err != nil {
|
if c.Err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -2915,6 +2916,7 @@ func unfollowThreadByUser(c *Context, w http.ResponseWriter, r *http.Request) {
|
|||||||
defer c.LogAuditRec(auditRec)
|
defer c.LogAuditRec(auditRec)
|
||||||
auditRec.AddMeta("user_id", c.Params.UserId)
|
auditRec.AddMeta("user_id", c.Params.UserId)
|
||||||
auditRec.AddMeta("thread_id", c.Params.ThreadId)
|
auditRec.AddMeta("thread_id", c.Params.ThreadId)
|
||||||
|
auditRec.AddMeta("team_id", c.Params.TeamId)
|
||||||
|
|
||||||
if !c.App.SessionHasPermissionToUser(*c.App.Session(), c.Params.UserId) {
|
if !c.App.SessionHasPermissionToUser(*c.App.Session(), c.Params.UserId) {
|
||||||
c.SetPermissionError(model.PERMISSION_EDIT_OTHER_USERS)
|
c.SetPermissionError(model.PERMISSION_EDIT_OTHER_USERS)
|
||||||
@@ -2933,7 +2935,7 @@ func unfollowThreadByUser(c *Context, w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func followThreadByUser(c *Context, w http.ResponseWriter, r *http.Request) {
|
func followThreadByUser(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||||
c.RequireUserId().RequireThreadId()
|
c.RequireUserId().RequireThreadId().RequireTeamId()
|
||||||
if c.Err != nil {
|
if c.Err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -2942,6 +2944,7 @@ func followThreadByUser(c *Context, w http.ResponseWriter, r *http.Request) {
|
|||||||
defer c.LogAuditRec(auditRec)
|
defer c.LogAuditRec(auditRec)
|
||||||
auditRec.AddMeta("user_id", c.Params.UserId)
|
auditRec.AddMeta("user_id", c.Params.UserId)
|
||||||
auditRec.AddMeta("thread_id", c.Params.ThreadId)
|
auditRec.AddMeta("thread_id", c.Params.ThreadId)
|
||||||
|
auditRec.AddMeta("team_id", c.Params.TeamId)
|
||||||
|
|
||||||
if !c.App.SessionHasPermissionToUser(*c.App.Session(), c.Params.UserId) {
|
if !c.App.SessionHasPermissionToUser(*c.App.Session(), c.Params.UserId) {
|
||||||
c.SetPermissionError(model.PERMISSION_EDIT_OTHER_USERS)
|
c.SetPermissionError(model.PERMISSION_EDIT_OTHER_USERS)
|
||||||
@@ -2959,7 +2962,7 @@ func followThreadByUser(c *Context, w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func updateReadStateAllThreadsByUser(c *Context, w http.ResponseWriter, r *http.Request) {
|
func updateReadStateAllThreadsByUser(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||||
c.RequireUserId().RequireTimestamp()
|
c.RequireUserId().RequireTeamId()
|
||||||
if c.Err != nil {
|
if c.Err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -2967,14 +2970,14 @@ func updateReadStateAllThreadsByUser(c *Context, w http.ResponseWriter, r *http.
|
|||||||
auditRec := c.MakeAuditRecord("updateReadStateAllThreadsByUser", audit.Fail)
|
auditRec := c.MakeAuditRecord("updateReadStateAllThreadsByUser", audit.Fail)
|
||||||
defer c.LogAuditRec(auditRec)
|
defer c.LogAuditRec(auditRec)
|
||||||
auditRec.AddMeta("user_id", c.Params.UserId)
|
auditRec.AddMeta("user_id", c.Params.UserId)
|
||||||
auditRec.AddMeta("timestamp", c.Params.Timestamp)
|
auditRec.AddMeta("team_id", c.Params.TeamId)
|
||||||
|
|
||||||
if !c.App.SessionHasPermissionToUser(*c.App.Session(), c.Params.UserId) {
|
if !c.App.SessionHasPermissionToUser(*c.App.Session(), c.Params.UserId) {
|
||||||
c.SetPermissionError(model.PERMISSION_EDIT_OTHER_USERS)
|
c.SetPermissionError(model.PERMISSION_EDIT_OTHER_USERS)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err := c.App.UpdateThreadsReadForUser(c.Params.UserId, c.Params.Timestamp)
|
err := c.App.UpdateThreadsReadForUser(c.Params.UserId, c.Params.TeamId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.Err = err
|
c.Err = err
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -5269,7 +5269,7 @@ func TestGetThreadsForUser(t *testing.T) {
|
|||||||
|
|
||||||
defer th.App.Srv().Store.Post().PermanentDeleteByUser(th.BasicUser.Id)
|
defer th.App.Srv().Store.Post().PermanentDeleteByUser(th.BasicUser.Id)
|
||||||
|
|
||||||
uss, resp := th.Client.GetUserThreads(th.BasicUser.Id, model.GetUserThreadsOpts{
|
uss, resp := th.Client.GetUserThreads(th.BasicUser.Id, th.BasicTeam.Id, model.GetUserThreadsOpts{
|
||||||
Page: 0,
|
Page: 0,
|
||||||
PageSize: 30,
|
PageSize: 30,
|
||||||
})
|
})
|
||||||
@@ -5289,7 +5289,7 @@ func TestGetThreadsForUser(t *testing.T) {
|
|||||||
|
|
||||||
defer th.App.Srv().Store.Post().PermanentDeleteByUser(th.BasicUser.Id)
|
defer th.App.Srv().Store.Post().PermanentDeleteByUser(th.BasicUser.Id)
|
||||||
|
|
||||||
uss, resp := th.Client.GetUserThreads(th.BasicUser.Id, model.GetUserThreadsOpts{
|
uss, resp := th.Client.GetUserThreads(th.BasicUser.Id, th.BasicTeam.Id, model.GetUserThreadsOpts{
|
||||||
Page: 0,
|
Page: 0,
|
||||||
PageSize: 30,
|
PageSize: 30,
|
||||||
})
|
})
|
||||||
@@ -5311,7 +5311,7 @@ func TestGetThreadsForUser(t *testing.T) {
|
|||||||
|
|
||||||
defer th.App.Srv().Store.Post().PermanentDeleteByUser(th.BasicUser.Id)
|
defer th.App.Srv().Store.Post().PermanentDeleteByUser(th.BasicUser.Id)
|
||||||
|
|
||||||
uss, resp := th.Client.GetUserThreads(th.BasicUser.Id, model.GetUserThreadsOpts{
|
uss, resp := th.Client.GetUserThreads(th.BasicUser.Id, th.BasicTeam.Id, model.GetUserThreadsOpts{
|
||||||
Page: 0,
|
Page: 0,
|
||||||
PageSize: 30,
|
PageSize: 30,
|
||||||
Extended: true,
|
Extended: true,
|
||||||
@@ -5335,7 +5335,7 @@ func TestGetThreadsForUser(t *testing.T) {
|
|||||||
|
|
||||||
defer th.App.Srv().Store.Post().PermanentDeleteByUser(th.BasicUser.Id)
|
defer th.App.Srv().Store.Post().PermanentDeleteByUser(th.BasicUser.Id)
|
||||||
|
|
||||||
uss, resp := th.Client.GetUserThreads(th.BasicUser.Id, model.GetUserThreadsOpts{
|
uss, resp := th.Client.GetUserThreads(th.BasicUser.Id, th.BasicTeam.Id, model.GetUserThreadsOpts{
|
||||||
Page: 0,
|
Page: 0,
|
||||||
PageSize: 30,
|
PageSize: 30,
|
||||||
Deleted: false,
|
Deleted: false,
|
||||||
@@ -5350,7 +5350,7 @@ func TestGetThreadsForUser(t *testing.T) {
|
|||||||
require.True(t, res)
|
require.True(t, res)
|
||||||
require.Nil(t, resp2.Error)
|
require.Nil(t, resp2.Error)
|
||||||
|
|
||||||
uss, resp = th.Client.GetUserThreads(th.BasicUser.Id, model.GetUserThreadsOpts{
|
uss, resp = th.Client.GetUserThreads(th.BasicUser.Id, th.BasicTeam.Id, model.GetUserThreadsOpts{
|
||||||
Page: 0,
|
Page: 0,
|
||||||
PageSize: 30,
|
PageSize: 30,
|
||||||
Deleted: false,
|
Deleted: false,
|
||||||
@@ -5358,7 +5358,7 @@ func TestGetThreadsForUser(t *testing.T) {
|
|||||||
require.Nil(t, resp.Error)
|
require.Nil(t, resp.Error)
|
||||||
require.Len(t, uss.Threads, 0)
|
require.Len(t, uss.Threads, 0)
|
||||||
|
|
||||||
uss, resp = th.Client.GetUserThreads(th.BasicUser.Id, model.GetUserThreadsOpts{
|
uss, resp = th.Client.GetUserThreads(th.BasicUser.Id, th.BasicTeam.Id, model.GetUserThreadsOpts{
|
||||||
Page: 0,
|
Page: 0,
|
||||||
PageSize: 30,
|
PageSize: 30,
|
||||||
Deleted: true,
|
Deleted: true,
|
||||||
@@ -5387,7 +5387,7 @@ func TestGetThreadsForUser(t *testing.T) {
|
|||||||
|
|
||||||
defer th.App.Srv().Store.Post().PermanentDeleteByUser(th.BasicUser.Id)
|
defer th.App.Srv().Store.Post().PermanentDeleteByUser(th.BasicUser.Id)
|
||||||
|
|
||||||
uss, resp := th.Client.GetUserThreads(th.BasicUser.Id, model.GetUserThreadsOpts{
|
uss, resp := th.Client.GetUserThreads(th.BasicUser.Id, th.BasicTeam.Id, model.GetUserThreadsOpts{
|
||||||
Page: 0,
|
Page: 0,
|
||||||
PageSize: 30,
|
PageSize: 30,
|
||||||
Deleted: false,
|
Deleted: false,
|
||||||
@@ -5446,7 +5446,7 @@ func TestThreadSocketEvents(t *testing.T) {
|
|||||||
require.Truef(t, caught, "User should have received %s event", model.WEBSOCKET_EVENT_THREAD_UPDATED)
|
require.Truef(t, caught, "User should have received %s event", model.WEBSOCKET_EVENT_THREAD_UPDATED)
|
||||||
})
|
})
|
||||||
|
|
||||||
resp = th.Client.UpdateThreadFollowForUser(th.BasicUser.Id, rpost.Id, false)
|
resp = th.Client.UpdateThreadFollowForUser(th.BasicUser.Id, th.BasicTeam.Id, rpost.Id, false)
|
||||||
CheckNoError(t, resp)
|
CheckNoError(t, resp)
|
||||||
CheckOKStatus(t, resp)
|
CheckOKStatus(t, resp)
|
||||||
|
|
||||||
@@ -5468,7 +5468,7 @@ func TestThreadSocketEvents(t *testing.T) {
|
|||||||
require.Truef(t, caught, "User should have received %s event", model.WEBSOCKET_EVENT_THREAD_FOLLOW_CHANGED)
|
require.Truef(t, caught, "User should have received %s event", model.WEBSOCKET_EVENT_THREAD_FOLLOW_CHANGED)
|
||||||
})
|
})
|
||||||
|
|
||||||
resp = th.Client.UpdateThreadReadForUser(th.BasicUser.Id, rpost.Id, 123)
|
resp = th.Client.UpdateThreadReadForUser(th.BasicUser.Id, th.BasicTeam.Id, rpost.Id, 123)
|
||||||
CheckNoError(t, resp)
|
CheckNoError(t, resp)
|
||||||
CheckOKStatus(t, resp)
|
CheckOKStatus(t, resp)
|
||||||
|
|
||||||
@@ -5509,7 +5509,7 @@ func TestFollowThreads(t *testing.T) {
|
|||||||
|
|
||||||
defer th.App.Srv().Store.Post().PermanentDeleteByUser(th.BasicUser.Id)
|
defer th.App.Srv().Store.Post().PermanentDeleteByUser(th.BasicUser.Id)
|
||||||
var uss *model.Threads
|
var uss *model.Threads
|
||||||
uss, resp = th.Client.GetUserThreads(th.BasicUser.Id, model.GetUserThreadsOpts{
|
uss, resp = th.Client.GetUserThreads(th.BasicUser.Id, th.BasicTeam.Id, model.GetUserThreadsOpts{
|
||||||
Page: 0,
|
Page: 0,
|
||||||
PageSize: 30,
|
PageSize: 30,
|
||||||
Deleted: false,
|
Deleted: false,
|
||||||
@@ -5517,11 +5517,11 @@ func TestFollowThreads(t *testing.T) {
|
|||||||
CheckNoError(t, resp)
|
CheckNoError(t, resp)
|
||||||
require.Len(t, uss.Threads, 1)
|
require.Len(t, uss.Threads, 1)
|
||||||
|
|
||||||
resp = th.Client.UpdateThreadFollowForUser(th.BasicUser.Id, rpost.Id, false)
|
resp = th.Client.UpdateThreadFollowForUser(th.BasicUser.Id, th.BasicTeam.Id, rpost.Id, false)
|
||||||
CheckNoError(t, resp)
|
CheckNoError(t, resp)
|
||||||
CheckOKStatus(t, resp)
|
CheckOKStatus(t, resp)
|
||||||
|
|
||||||
uss, resp = th.Client.GetUserThreads(th.BasicUser.Id, model.GetUserThreadsOpts{
|
uss, resp = th.Client.GetUserThreads(th.BasicUser.Id, th.BasicTeam.Id, model.GetUserThreadsOpts{
|
||||||
Page: 0,
|
Page: 0,
|
||||||
PageSize: 30,
|
PageSize: 30,
|
||||||
Deleted: false,
|
Deleted: false,
|
||||||
@@ -5529,11 +5529,11 @@ func TestFollowThreads(t *testing.T) {
|
|||||||
CheckNoError(t, resp)
|
CheckNoError(t, resp)
|
||||||
require.Len(t, uss.Threads, 0)
|
require.Len(t, uss.Threads, 0)
|
||||||
|
|
||||||
resp = th.Client.UpdateThreadFollowForUser(th.BasicUser.Id, rpost.Id, true)
|
resp = th.Client.UpdateThreadFollowForUser(th.BasicUser.Id, th.BasicTeam.Id, rpost.Id, true)
|
||||||
CheckNoError(t, resp)
|
CheckNoError(t, resp)
|
||||||
CheckOKStatus(t, resp)
|
CheckOKStatus(t, resp)
|
||||||
|
|
||||||
uss, resp = th.Client.GetUserThreads(th.BasicUser.Id, model.GetUserThreadsOpts{
|
uss, resp = th.Client.GetUserThreads(th.BasicUser.Id, th.BasicTeam.Id, model.GetUserThreadsOpts{
|
||||||
Page: 0,
|
Page: 0,
|
||||||
PageSize: 30,
|
PageSize: 30,
|
||||||
Deleted: false,
|
Deleted: false,
|
||||||
@@ -5544,13 +5544,76 @@ func TestFollowThreads(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestMaintainUnreadRepliesInThread(t *testing.T) {
|
||||||
|
th := Setup(t).InitBasic()
|
||||||
|
defer th.TearDown()
|
||||||
|
th.App.UpdateConfig(func(cfg *model.Config) {
|
||||||
|
*cfg.ServiceSettings.ThreadAutoFollow = true
|
||||||
|
*cfg.ServiceSettings.CollapsedThreads = model.COLLAPSED_THREADS_DEFAULT_ON
|
||||||
|
})
|
||||||
|
|
||||||
|
Client := th.Client
|
||||||
|
defer th.App.Srv().Store.Post().PermanentDeleteByUser(th.BasicUser.Id)
|
||||||
|
defer th.App.Srv().Store.Post().PermanentDeleteByUser(th.SystemAdminUser.Id)
|
||||||
|
|
||||||
|
// create a post by regular user
|
||||||
|
rpost, resp := Client.CreatePost(&model.Post{ChannelId: th.BasicChannel.Id, Message: "testMsg"})
|
||||||
|
CheckNoError(t, resp)
|
||||||
|
CheckCreatedStatus(t, resp)
|
||||||
|
// reply with another
|
||||||
|
_, resp2 := th.SystemAdminClient.CreatePost(&model.Post{ChannelId: th.BasicChannel.Id, Message: "testReply", RootId: rpost.Id})
|
||||||
|
CheckNoError(t, resp2)
|
||||||
|
CheckCreatedStatus(t, resp2)
|
||||||
|
|
||||||
|
checkThreadList := func(client *model.Client4, userId string, expectedReplies, expectedThreads int) (*model.Threads, *model.Response) {
|
||||||
|
u, r := client.GetUserThreads(userId, th.BasicTeam.Id, model.GetUserThreadsOpts{
|
||||||
|
Page: 0,
|
||||||
|
PageSize: 30,
|
||||||
|
Deleted: false,
|
||||||
|
})
|
||||||
|
CheckNoError(t, r)
|
||||||
|
require.Len(t, u.Threads, expectedThreads)
|
||||||
|
require.EqualValues(t, expectedReplies, u.Threads[0].UnreadReplies)
|
||||||
|
|
||||||
|
sum := int64(0)
|
||||||
|
for _, thr := range u.Threads {
|
||||||
|
sum += thr.UnreadReplies
|
||||||
|
}
|
||||||
|
require.Equal(t, sum, u.TotalUnreadReplies)
|
||||||
|
|
||||||
|
return u, r
|
||||||
|
}
|
||||||
|
// regular user should have one thread with one reply
|
||||||
|
checkThreadList(th.Client, th.BasicUser.Id, 1, 1)
|
||||||
|
|
||||||
|
// add another reply by regular user
|
||||||
|
_, resp3 := Client.CreatePost(&model.Post{ChannelId: th.BasicChannel.Id, Message: "testReply2", RootId: rpost.Id})
|
||||||
|
CheckNoError(t, resp3)
|
||||||
|
CheckCreatedStatus(t, resp3)
|
||||||
|
|
||||||
|
// replying to the thread clears reply count, so it should be 0
|
||||||
|
checkThreadList(th.Client, th.BasicUser.Id, 0, 1)
|
||||||
|
|
||||||
|
// the other user should have 2 replies
|
||||||
|
checkThreadList(th.SystemAdminClient, th.SystemAdminUser.Id, 2, 1)
|
||||||
|
|
||||||
|
// mark all as read for user
|
||||||
|
resp = th.Client.UpdateThreadsReadForUser(th.BasicUser.Id, th.BasicTeam.Id)
|
||||||
|
CheckNoError(t, resp)
|
||||||
|
CheckOKStatus(t, resp)
|
||||||
|
|
||||||
|
// reply count should be 0
|
||||||
|
checkThreadList(th.Client, th.BasicUser.Id, 0, 1)
|
||||||
|
|
||||||
|
// the other user should also have 2
|
||||||
|
checkThreadList(th.SystemAdminClient, th.SystemAdminUser.Id, 2, 1)
|
||||||
|
}
|
||||||
func postAndCheck(t *testing.T, client *model.Client4, post *model.Post) (*model.Post, *model.Response) {
|
func postAndCheck(t *testing.T, client *model.Client4, post *model.Post) (*model.Post, *model.Response) {
|
||||||
p, resp := client.CreatePost(post)
|
p, resp := client.CreatePost(post)
|
||||||
CheckNoError(t, resp)
|
CheckNoError(t, resp)
|
||||||
CheckCreatedStatus(t, resp)
|
CheckCreatedStatus(t, resp)
|
||||||
return p, resp
|
return p, resp
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMaintainUnreadMentionsInThread(t *testing.T) {
|
func TestMaintainUnreadMentionsInThread(t *testing.T) {
|
||||||
th := Setup(t).InitBasic()
|
th := Setup(t).InitBasic()
|
||||||
defer th.TearDown()
|
defer th.TearDown()
|
||||||
@@ -5559,24 +5622,19 @@ func TestMaintainUnreadMentionsInThread(t *testing.T) {
|
|||||||
*cfg.ServiceSettings.ThreadAutoFollow = true
|
*cfg.ServiceSettings.ThreadAutoFollow = true
|
||||||
*cfg.ServiceSettings.CollapsedThreads = model.COLLAPSED_THREADS_DEFAULT_ON
|
*cfg.ServiceSettings.CollapsedThreads = model.COLLAPSED_THREADS_DEFAULT_ON
|
||||||
})
|
})
|
||||||
|
|
||||||
checkThreadList := func(client *model.Client4, userId string, expectedMentions, expectedThreads int) (*model.Threads, *model.Response) {
|
checkThreadList := func(client *model.Client4, userId string, expectedMentions, expectedThreads int) (*model.Threads, *model.Response) {
|
||||||
uss, resp := client.GetUserThreads(userId, model.GetUserThreadsOpts{
|
uss, resp := client.GetUserThreads(userId, th.BasicTeam.Id, model.GetUserThreadsOpts{
|
||||||
Page: 0,
|
Page: 0,
|
||||||
PageSize: 30,
|
PageSize: 30,
|
||||||
Deleted: false,
|
Deleted: false,
|
||||||
})
|
})
|
||||||
CheckNoError(t, resp)
|
CheckNoError(t, resp)
|
||||||
require.Len(t, uss.Threads, expectedThreads)
|
require.Len(t, uss.Threads, expectedThreads)
|
||||||
|
|
||||||
// validate amount of mentions via store. once GetUserThreads starts returning mentions - update
|
|
||||||
memberships, err := th.App.Srv().Store.Thread().GetMembershipsForUser(userId)
|
|
||||||
require.NoError(t, err)
|
|
||||||
sum := int64(0)
|
sum := int64(0)
|
||||||
for _, membership := range memberships {
|
for _, thr := range uss.Threads {
|
||||||
sum += membership.UnreadMentions
|
sum += thr.UnreadMentions
|
||||||
}
|
}
|
||||||
require.EqualValues(t, expectedMentions, sum)
|
require.Equal(t, sum, uss.TotalUnreadMentions)
|
||||||
return uss, resp
|
return uss, resp
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5628,13 +5686,13 @@ func TestReadThreads(t *testing.T) {
|
|||||||
rpost, resp := Client.CreatePost(&model.Post{ChannelId: th.BasicChannel.Id, Message: "testMsg"})
|
rpost, resp := Client.CreatePost(&model.Post{ChannelId: th.BasicChannel.Id, Message: "testMsg"})
|
||||||
CheckNoError(t, resp)
|
CheckNoError(t, resp)
|
||||||
CheckCreatedStatus(t, resp)
|
CheckCreatedStatus(t, resp)
|
||||||
rpost2, resp2 := Client.CreatePost(&model.Post{ChannelId: th.BasicChannel.Id, Message: "testReply", RootId: rpost.Id})
|
_, resp2 := Client.CreatePost(&model.Post{ChannelId: th.BasicChannel.Id, Message: "testReply", RootId: rpost.Id})
|
||||||
CheckNoError(t, resp2)
|
CheckNoError(t, resp2)
|
||||||
CheckCreatedStatus(t, resp2)
|
CheckCreatedStatus(t, resp2)
|
||||||
defer th.App.Srv().Store.Post().PermanentDeleteByUser(th.BasicUser.Id)
|
defer th.App.Srv().Store.Post().PermanentDeleteByUser(th.BasicUser.Id)
|
||||||
|
|
||||||
var uss, uss2, uss3 *model.Threads
|
var uss, uss2 *model.Threads
|
||||||
uss, resp = th.Client.GetUserThreads(th.BasicUser.Id, model.GetUserThreadsOpts{
|
uss, resp = th.Client.GetUserThreads(th.BasicUser.Id, th.BasicTeam.Id, model.GetUserThreadsOpts{
|
||||||
Page: 0,
|
Page: 0,
|
||||||
PageSize: 30,
|
PageSize: 30,
|
||||||
Deleted: false,
|
Deleted: false,
|
||||||
@@ -5643,11 +5701,11 @@ func TestReadThreads(t *testing.T) {
|
|||||||
require.Len(t, uss.Threads, 1)
|
require.Len(t, uss.Threads, 1)
|
||||||
|
|
||||||
time.Sleep(1)
|
time.Sleep(1)
|
||||||
resp = th.Client.UpdateThreadsReadForUser(th.BasicUser.Id, model.GetMillis())
|
resp = th.Client.UpdateThreadsReadForUser(th.BasicUser.Id, th.BasicTeam.Id)
|
||||||
CheckNoError(t, resp)
|
CheckNoError(t, resp)
|
||||||
CheckOKStatus(t, resp)
|
CheckOKStatus(t, resp)
|
||||||
|
|
||||||
uss2, resp = th.Client.GetUserThreads(th.BasicUser.Id, model.GetUserThreadsOpts{
|
uss2, resp = th.Client.GetUserThreads(th.BasicUser.Id, th.BasicTeam.Id, model.GetUserThreadsOpts{
|
||||||
Page: 0,
|
Page: 0,
|
||||||
PageSize: 30,
|
PageSize: 30,
|
||||||
Deleted: false,
|
Deleted: false,
|
||||||
@@ -5655,19 +5713,6 @@ func TestReadThreads(t *testing.T) {
|
|||||||
CheckNoError(t, resp)
|
CheckNoError(t, resp)
|
||||||
require.Len(t, uss2.Threads, 1)
|
require.Len(t, uss2.Threads, 1)
|
||||||
require.Greater(t, uss2.Threads[0].LastViewedAt, uss.Threads[0].LastViewedAt)
|
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) {
|
t.Run("1 thread", func(t *testing.T) {
|
||||||
@@ -5690,7 +5735,7 @@ func TestReadThreads(t *testing.T) {
|
|||||||
defer th.App.Srv().Store.Post().PermanentDeleteByUser(th.BasicUser.Id)
|
defer th.App.Srv().Store.Post().PermanentDeleteByUser(th.BasicUser.Id)
|
||||||
|
|
||||||
var uss, uss2, uss3 *model.Threads
|
var uss, uss2, uss3 *model.Threads
|
||||||
uss, resp = th.Client.GetUserThreads(th.BasicUser.Id, model.GetUserThreadsOpts{
|
uss, resp = th.Client.GetUserThreads(th.BasicUser.Id, th.BasicTeam.Id, model.GetUserThreadsOpts{
|
||||||
Page: 0,
|
Page: 0,
|
||||||
PageSize: 30,
|
PageSize: 30,
|
||||||
Deleted: false,
|
Deleted: false,
|
||||||
@@ -5698,11 +5743,11 @@ func TestReadThreads(t *testing.T) {
|
|||||||
CheckNoError(t, resp)
|
CheckNoError(t, resp)
|
||||||
require.Len(t, uss.Threads, 2)
|
require.Len(t, uss.Threads, 2)
|
||||||
|
|
||||||
resp = th.Client.UpdateThreadReadForUser(th.BasicUser.Id, rrpost.Id, model.GetMillis())
|
resp = th.Client.UpdateThreadReadForUser(th.BasicUser.Id, th.BasicTeam.Id, rrpost.Id, model.GetMillis())
|
||||||
CheckNoError(t, resp)
|
CheckNoError(t, resp)
|
||||||
CheckOKStatus(t, resp)
|
CheckOKStatus(t, resp)
|
||||||
|
|
||||||
uss2, resp = th.Client.GetUserThreads(th.BasicUser.Id, model.GetUserThreadsOpts{
|
uss2, resp = th.Client.GetUserThreads(th.BasicUser.Id, th.BasicTeam.Id, model.GetUserThreadsOpts{
|
||||||
Page: 0,
|
Page: 0,
|
||||||
PageSize: 30,
|
PageSize: 30,
|
||||||
Deleted: false,
|
Deleted: false,
|
||||||
@@ -5712,11 +5757,11 @@ func TestReadThreads(t *testing.T) {
|
|||||||
require.Greater(t, uss2.Threads[1].LastViewedAt, uss.Threads[1].LastViewedAt)
|
require.Greater(t, uss2.Threads[1].LastViewedAt, uss.Threads[1].LastViewedAt)
|
||||||
|
|
||||||
timestamp := model.GetMillis()
|
timestamp := model.GetMillis()
|
||||||
resp = th.Client.UpdateThreadReadForUser(th.BasicUser.Id, rrpost.Id, timestamp)
|
resp = th.Client.UpdateThreadReadForUser(th.BasicUser.Id, th.BasicTeam.Id, rrpost.Id, timestamp)
|
||||||
CheckNoError(t, resp)
|
CheckNoError(t, resp)
|
||||||
CheckOKStatus(t, resp)
|
CheckOKStatus(t, resp)
|
||||||
|
|
||||||
uss3, resp = th.Client.GetUserThreads(th.BasicUser.Id, model.GetUserThreadsOpts{
|
uss3, resp = th.Client.GetUserThreads(th.BasicUser.Id, th.BasicTeam.Id, model.GetUserThreadsOpts{
|
||||||
Page: 0,
|
Page: 0,
|
||||||
PageSize: 30,
|
PageSize: 30,
|
||||||
Deleted: false,
|
Deleted: false,
|
||||||
|
|||||||
@@ -691,8 +691,8 @@ type AppIface interface {
|
|||||||
GetTeamsForUser(userId string) ([]*model.Team, *model.AppError)
|
GetTeamsForUser(userId string) ([]*model.Team, *model.AppError)
|
||||||
GetTeamsUnreadForUser(excludeTeamId string, userId string) ([]*model.TeamUnread, *model.AppError)
|
GetTeamsUnreadForUser(excludeTeamId string, userId string) ([]*model.TeamUnread, *model.AppError)
|
||||||
GetTermsOfService(id string) (*model.TermsOfService, *model.AppError)
|
GetTermsOfService(id string) (*model.TermsOfService, *model.AppError)
|
||||||
GetThreadMembershipsForUser(userId string) ([]*model.ThreadMembership, error)
|
GetThreadMembershipsForUser(userId, teamId string) ([]*model.ThreadMembership, error)
|
||||||
GetThreadsForUser(userId string, options model.GetUserThreadsOpts) (*model.Threads, *model.AppError)
|
GetThreadsForUser(userId, teamId string, options model.GetUserThreadsOpts) (*model.Threads, *model.AppError)
|
||||||
GetUploadSession(uploadId string) (*model.UploadSession, *model.AppError)
|
GetUploadSession(uploadId string) (*model.UploadSession, *model.AppError)
|
||||||
GetUploadSessionsForUser(userId string) ([]*model.UploadSession, *model.AppError)
|
GetUploadSessionsForUser(userId string) ([]*model.UploadSession, *model.AppError)
|
||||||
GetUser(userId string) (*model.User, *model.AppError)
|
GetUser(userId string) (*model.User, *model.AppError)
|
||||||
@@ -1002,8 +1002,8 @@ type AppIface interface {
|
|||||||
UpdateTeamPrivacy(teamId string, teamType string, allowOpenInvite bool) *model.AppError
|
UpdateTeamPrivacy(teamId string, teamType string, allowOpenInvite bool) *model.AppError
|
||||||
UpdateTeamScheme(team *model.Team) (*model.Team, *model.AppError)
|
UpdateTeamScheme(team *model.Team) (*model.Team, *model.AppError)
|
||||||
UpdateThreadFollowForUser(userId, threadId string, state bool) *model.AppError
|
UpdateThreadFollowForUser(userId, threadId string, state bool) *model.AppError
|
||||||
UpdateThreadReadForUser(userId, threadId string, timestamp int64) *model.AppError
|
UpdateThreadReadForUser(userId, teamId, threadId string, timestamp int64) *model.AppError
|
||||||
UpdateThreadsReadForUser(userId string, timestamp int64) *model.AppError
|
UpdateThreadsReadForUser(userId, teamId string) *model.AppError
|
||||||
UpdateUser(user *model.User, sendNotifications bool) (*model.User, *model.AppError)
|
UpdateUser(user *model.User, sendNotifications bool) (*model.User, *model.AppError)
|
||||||
UpdateUserActive(userId string, active bool) *model.AppError
|
UpdateUserActive(userId string, active bool) *model.AppError
|
||||||
UpdateUserAsUser(user *model.User, asAdmin bool) (*model.User, *model.AppError)
|
UpdateUserAsUser(user *model.User, asAdmin bool) (*model.User, *model.AppError)
|
||||||
|
|||||||
@@ -8485,7 +8485,7 @@ func (a *OpenTracingAppLayer) GetTermsOfService(id string) (*model.TermsOfServic
|
|||||||
return resultVar0, resultVar1
|
return resultVar0, resultVar1
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *OpenTracingAppLayer) GetThreadMembershipsForUser(userId string) ([]*model.ThreadMembership, error) {
|
func (a *OpenTracingAppLayer) GetThreadMembershipsForUser(userId string, teamId string) ([]*model.ThreadMembership, error) {
|
||||||
origCtx := a.ctx
|
origCtx := a.ctx
|
||||||
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.GetThreadMembershipsForUser")
|
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.GetThreadMembershipsForUser")
|
||||||
|
|
||||||
@@ -8497,7 +8497,7 @@ func (a *OpenTracingAppLayer) GetThreadMembershipsForUser(userId string) ([]*mod
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
defer span.Finish()
|
defer span.Finish()
|
||||||
resultVar0, resultVar1 := a.app.GetThreadMembershipsForUser(userId)
|
resultVar0, resultVar1 := a.app.GetThreadMembershipsForUser(userId, teamId)
|
||||||
|
|
||||||
if resultVar1 != nil {
|
if resultVar1 != nil {
|
||||||
span.LogFields(spanlog.Error(resultVar1))
|
span.LogFields(spanlog.Error(resultVar1))
|
||||||
@@ -8507,7 +8507,7 @@ func (a *OpenTracingAppLayer) GetThreadMembershipsForUser(userId string) ([]*mod
|
|||||||
return resultVar0, resultVar1
|
return resultVar0, resultVar1
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *OpenTracingAppLayer) GetThreadsForUser(userId string, options model.GetUserThreadsOpts) (*model.Threads, *model.AppError) {
|
func (a *OpenTracingAppLayer) GetThreadsForUser(userId string, teamId string, options model.GetUserThreadsOpts) (*model.Threads, *model.AppError) {
|
||||||
origCtx := a.ctx
|
origCtx := a.ctx
|
||||||
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.GetThreadsForUser")
|
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.GetThreadsForUser")
|
||||||
|
|
||||||
@@ -8519,7 +8519,7 @@ func (a *OpenTracingAppLayer) GetThreadsForUser(userId string, options model.Get
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
defer span.Finish()
|
defer span.Finish()
|
||||||
resultVar0, resultVar1 := a.app.GetThreadsForUser(userId, options)
|
resultVar0, resultVar1 := a.app.GetThreadsForUser(userId, teamId, options)
|
||||||
|
|
||||||
if resultVar1 != nil {
|
if resultVar1 != nil {
|
||||||
span.LogFields(spanlog.Error(resultVar1))
|
span.LogFields(spanlog.Error(resultVar1))
|
||||||
@@ -15319,7 +15319,7 @@ func (a *OpenTracingAppLayer) UpdateThreadFollowForUser(userId string, threadId
|
|||||||
return resultVar0
|
return resultVar0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *OpenTracingAppLayer) UpdateThreadReadForUser(userId string, threadId string, timestamp int64) *model.AppError {
|
func (a *OpenTracingAppLayer) UpdateThreadReadForUser(userId string, teamId string, threadId string, timestamp int64) *model.AppError {
|
||||||
origCtx := a.ctx
|
origCtx := a.ctx
|
||||||
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.UpdateThreadReadForUser")
|
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.UpdateThreadReadForUser")
|
||||||
|
|
||||||
@@ -15331,7 +15331,7 @@ func (a *OpenTracingAppLayer) UpdateThreadReadForUser(userId string, threadId st
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
defer span.Finish()
|
defer span.Finish()
|
||||||
resultVar0 := a.app.UpdateThreadReadForUser(userId, threadId, timestamp)
|
resultVar0 := a.app.UpdateThreadReadForUser(userId, teamId, threadId, timestamp)
|
||||||
|
|
||||||
if resultVar0 != nil {
|
if resultVar0 != nil {
|
||||||
span.LogFields(spanlog.Error(resultVar0))
|
span.LogFields(spanlog.Error(resultVar0))
|
||||||
@@ -15341,7 +15341,7 @@ func (a *OpenTracingAppLayer) UpdateThreadReadForUser(userId string, threadId st
|
|||||||
return resultVar0
|
return resultVar0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *OpenTracingAppLayer) UpdateThreadsReadForUser(userId string, timestamp int64) *model.AppError {
|
func (a *OpenTracingAppLayer) UpdateThreadsReadForUser(userId string, teamId string) *model.AppError {
|
||||||
origCtx := a.ctx
|
origCtx := a.ctx
|
||||||
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.UpdateThreadsReadForUser")
|
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.UpdateThreadsReadForUser")
|
||||||
|
|
||||||
@@ -15353,7 +15353,7 @@ func (a *OpenTracingAppLayer) UpdateThreadsReadForUser(userId string, timestamp
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
defer span.Finish()
|
defer span.Finish()
|
||||||
resultVar0 := a.app.UpdateThreadsReadForUser(userId, timestamp)
|
resultVar0 := a.app.UpdateThreadsReadForUser(userId, teamId)
|
||||||
|
|
||||||
if resultVar0 != nil {
|
if resultVar0 != nil {
|
||||||
span.LogFields(spanlog.Error(resultVar0))
|
span.LogFields(spanlog.Error(resultVar0))
|
||||||
|
|||||||
@@ -1538,6 +1538,6 @@ func isPostMention(user *model.User, post *model.Post, keywords map[string][]str
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *App) GetThreadMembershipsForUser(userId string) ([]*model.ThreadMembership, error) {
|
func (a *App) GetThreadMembershipsForUser(userId, teamId string) ([]*model.ThreadMembership, error) {
|
||||||
return a.Srv().Store.Thread().GetMembershipsForUser(userId)
|
return a.Srv().Store.Thread().GetMembershipsForUser(userId, teamId)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1892,11 +1892,11 @@ func TestThreadMembership(t *testing.T) {
|
|||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
|
|
||||||
// first user should now be part of the thread since they replied to a post
|
// first user should now be part of the thread since they replied to a post
|
||||||
memberships, err2 := th.App.GetThreadMembershipsForUser(user1.Id)
|
memberships, err2 := th.App.GetThreadMembershipsForUser(user1.Id, th.BasicTeam.Id)
|
||||||
require.Nil(t, err2)
|
require.Nil(t, err2)
|
||||||
require.Len(t, memberships, 1)
|
require.Len(t, memberships, 1)
|
||||||
// second user should also be part of a thread since they were mentioned
|
// second user should also be part of a thread since they were mentioned
|
||||||
memberships, err2 = th.App.GetThreadMembershipsForUser(user2.Id)
|
memberships, err2 = th.App.GetThreadMembershipsForUser(user2.Id, th.BasicTeam.Id)
|
||||||
require.Nil(t, err2)
|
require.Nil(t, err2)
|
||||||
require.Len(t, memberships, 1)
|
require.Len(t, memberships, 1)
|
||||||
|
|
||||||
@@ -1916,7 +1916,7 @@ func TestThreadMembership(t *testing.T) {
|
|||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
|
|
||||||
// first user should now be part of two threads
|
// first user should now be part of two threads
|
||||||
memberships, err2 = th.App.GetThreadMembershipsForUser(user1.Id)
|
memberships, err2 = th.App.GetThreadMembershipsForUser(user1.Id, th.BasicTeam.Id)
|
||||||
require.Nil(t, err2)
|
require.Nil(t, err2)
|
||||||
require.Len(t, memberships, 2)
|
require.Len(t, memberships, 2)
|
||||||
})
|
})
|
||||||
|
|||||||
36
app/user.go
36
app/user.go
@@ -2371,8 +2371,8 @@ func (a *App) ConvertBotToUser(bot *model.Bot, userPatch *model.UserPatch, sysad
|
|||||||
return user, nil
|
return user, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *App) GetThreadsForUser(userId string, options model.GetUserThreadsOpts) (*model.Threads, *model.AppError) {
|
func (a *App) GetThreadsForUser(userId, teamId string, options model.GetUserThreadsOpts) (*model.Threads, *model.AppError) {
|
||||||
threads, err := a.Srv().Store.Thread().GetThreadsForUser(userId, options)
|
threads, err := a.Srv().Store.Thread().GetThreadsForUser(userId, teamId, options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, model.NewAppError("GetThreadsForUser", "app.user.get_threads_for_user.app_error", nil, err.Error(), http.StatusInternalServerError)
|
return nil, model.NewAppError("GetThreadsForUser", "app.user.get_threads_for_user.app_error", nil, err.Error(), http.StatusInternalServerError)
|
||||||
}
|
}
|
||||||
@@ -2383,13 +2383,12 @@ func (a *App) GetThreadsForUser(userId string, options model.GetUserThreadsOpts)
|
|||||||
return threads, nil
|
return threads, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *App) UpdateThreadsReadForUser(userId string, timestamp int64) *model.AppError {
|
func (a *App) UpdateThreadsReadForUser(userId, teamId string) *model.AppError {
|
||||||
nErr := a.Srv().Store.Thread().MarkAllAsRead(userId, timestamp)
|
nErr := a.Srv().Store.Thread().MarkAllAsRead(userId, teamId)
|
||||||
if nErr != nil {
|
if nErr != nil {
|
||||||
return model.NewAppError("UpdateThreadsReadForUser", "app.user.update_threads_read_for_user.app_error", nil, nErr.Error(), http.StatusInternalServerError)
|
return model.NewAppError("UpdateThreadsReadForUser", "app.user.update_threads_read_for_user.app_error", nil, nErr.Error(), http.StatusInternalServerError)
|
||||||
}
|
}
|
||||||
message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_THREAD_READ_CHANGED, "", "", userId, nil)
|
message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_THREAD_READ_CHANGED, "", "", userId, nil)
|
||||||
message.Add("timestamp", timestamp)
|
|
||||||
a.Publish(message)
|
a.Publish(message)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -2406,8 +2405,31 @@ func (a *App) UpdateThreadFollowForUser(userId, threadId string, state bool) *mo
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *App) UpdateThreadReadForUser(userId, threadId string, timestamp int64) *model.AppError {
|
func (a *App) UpdateThreadReadForUser(userId, teamId, threadId string, timestamp int64) *model.AppError {
|
||||||
nErr := a.Srv().Store.Thread().MarkAsRead(userId, threadId, timestamp)
|
user, err := a.GetUser(userId)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
membership, nErr := a.Srv().Store.Thread().GetMembershipForUser(userId, threadId)
|
||||||
|
if nErr != nil {
|
||||||
|
return model.NewAppError("UpdateThreadsReadForUser", "app.user.update_threads_read_for_user.app_error", nil, nErr.Error(), http.StatusInternalServerError)
|
||||||
|
}
|
||||||
|
post, err := a.GetSinglePost(threadId)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
membership.UnreadMentions, err = a.countThreadMentions(user, post, teamId, timestamp)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
membership.Following = true
|
||||||
|
_, nErr = a.Srv().Store.Thread().UpdateMembership(membership)
|
||||||
|
if nErr != nil {
|
||||||
|
return model.NewAppError("UpdateThreadsReadForUser", "app.user.update_threads_read_for_user.app_error", nil, nErr.Error(), http.StatusInternalServerError)
|
||||||
|
}
|
||||||
|
|
||||||
|
nErr = a.Srv().Store.Thread().MarkAsRead(userId, threadId, timestamp)
|
||||||
if nErr != nil {
|
if nErr != nil {
|
||||||
return model.NewAppError("UpdateThreadReadForUser", "app.user.update_thread_read_for_user.app_error", nil, nErr.Error(), http.StatusInternalServerError)
|
return model.NewAppError("UpdateThreadReadForUser", "app.user.update_thread_read_for_user.app_error", nil, nErr.Error(), http.StatusInternalServerError)
|
||||||
}
|
}
|
||||||
|
|||||||
238
einterfaces/mocks/CloudInterface.go
Обычный файл
238
einterfaces/mocks/CloudInterface.go
Обычный файл
@@ -0,0 +1,238 @@
|
|||||||
|
// Code generated by mockery v1.0.0. DO NOT EDIT.
|
||||||
|
|
||||||
|
// Regenerate this file using `make einterfaces-mocks`.
|
||||||
|
|
||||||
|
package mocks
|
||||||
|
|
||||||
|
import (
|
||||||
|
model "github.com/mattermost/mattermost-server/v5/model"
|
||||||
|
mock "github.com/stretchr/testify/mock"
|
||||||
|
)
|
||||||
|
|
||||||
|
// CloudInterface is an autogenerated mock type for the CloudInterface type
|
||||||
|
type CloudInterface struct {
|
||||||
|
mock.Mock
|
||||||
|
}
|
||||||
|
|
||||||
|
// ConfirmCustomerPayment provides a mock function with given fields: _a0
|
||||||
|
func (_m *CloudInterface) ConfirmCustomerPayment(_a0 *model.ConfirmPaymentMethodRequest) *model.AppError {
|
||||||
|
ret := _m.Called(_a0)
|
||||||
|
|
||||||
|
var r0 *model.AppError
|
||||||
|
if rf, ok := ret.Get(0).(func(*model.ConfirmPaymentMethodRequest) *model.AppError); ok {
|
||||||
|
r0 = rf(_a0)
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).(*model.AppError)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateCustomerPayment provides a mock function with given fields:
|
||||||
|
func (_m *CloudInterface) CreateCustomerPayment() (*model.StripeSetupIntent, *model.AppError) {
|
||||||
|
ret := _m.Called()
|
||||||
|
|
||||||
|
var r0 *model.StripeSetupIntent
|
||||||
|
if rf, ok := ret.Get(0).(func() *model.StripeSetupIntent); ok {
|
||||||
|
r0 = rf()
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).(*model.StripeSetupIntent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var r1 *model.AppError
|
||||||
|
if rf, ok := ret.Get(1).(func() *model.AppError); ok {
|
||||||
|
r1 = rf()
|
||||||
|
} else {
|
||||||
|
if ret.Get(1) != nil {
|
||||||
|
r1 = ret.Get(1).(*model.AppError)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetCloudCustomer provides a mock function with given fields:
|
||||||
|
func (_m *CloudInterface) GetCloudCustomer() (*model.CloudCustomer, *model.AppError) {
|
||||||
|
ret := _m.Called()
|
||||||
|
|
||||||
|
var r0 *model.CloudCustomer
|
||||||
|
if rf, ok := ret.Get(0).(func() *model.CloudCustomer); ok {
|
||||||
|
r0 = rf()
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).(*model.CloudCustomer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var r1 *model.AppError
|
||||||
|
if rf, ok := ret.Get(1).(func() *model.AppError); ok {
|
||||||
|
r1 = rf()
|
||||||
|
} else {
|
||||||
|
if ret.Get(1) != nil {
|
||||||
|
r1 = ret.Get(1).(*model.AppError)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetCloudProducts provides a mock function with given fields:
|
||||||
|
func (_m *CloudInterface) GetCloudProducts() ([]*model.Product, *model.AppError) {
|
||||||
|
ret := _m.Called()
|
||||||
|
|
||||||
|
var r0 []*model.Product
|
||||||
|
if rf, ok := ret.Get(0).(func() []*model.Product); ok {
|
||||||
|
r0 = rf()
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).([]*model.Product)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var r1 *model.AppError
|
||||||
|
if rf, ok := ret.Get(1).(func() *model.AppError); ok {
|
||||||
|
r1 = rf()
|
||||||
|
} else {
|
||||||
|
if ret.Get(1) != nil {
|
||||||
|
r1 = ret.Get(1).(*model.AppError)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetInvoicePDF provides a mock function with given fields: invoiceID
|
||||||
|
func (_m *CloudInterface) GetInvoicePDF(invoiceID string) ([]byte, string, *model.AppError) {
|
||||||
|
ret := _m.Called(invoiceID)
|
||||||
|
|
||||||
|
var r0 []byte
|
||||||
|
if rf, ok := ret.Get(0).(func(string) []byte); ok {
|
||||||
|
r0 = rf(invoiceID)
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).([]byte)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var r1 string
|
||||||
|
if rf, ok := ret.Get(1).(func(string) string); ok {
|
||||||
|
r1 = rf(invoiceID)
|
||||||
|
} else {
|
||||||
|
r1 = ret.Get(1).(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
var r2 *model.AppError
|
||||||
|
if rf, ok := ret.Get(2).(func(string) *model.AppError); ok {
|
||||||
|
r2 = rf(invoiceID)
|
||||||
|
} else {
|
||||||
|
if ret.Get(2) != nil {
|
||||||
|
r2 = ret.Get(2).(*model.AppError)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1, r2
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetInvoicesForSubscription provides a mock function with given fields:
|
||||||
|
func (_m *CloudInterface) GetInvoicesForSubscription() ([]*model.Invoice, *model.AppError) {
|
||||||
|
ret := _m.Called()
|
||||||
|
|
||||||
|
var r0 []*model.Invoice
|
||||||
|
if rf, ok := ret.Get(0).(func() []*model.Invoice); ok {
|
||||||
|
r0 = rf()
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).([]*model.Invoice)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var r1 *model.AppError
|
||||||
|
if rf, ok := ret.Get(1).(func() *model.AppError); ok {
|
||||||
|
r1 = rf()
|
||||||
|
} else {
|
||||||
|
if ret.Get(1) != nil {
|
||||||
|
r1 = ret.Get(1).(*model.AppError)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetSubscription provides a mock function with given fields:
|
||||||
|
func (_m *CloudInterface) GetSubscription() (*model.Subscription, *model.AppError) {
|
||||||
|
ret := _m.Called()
|
||||||
|
|
||||||
|
var r0 *model.Subscription
|
||||||
|
if rf, ok := ret.Get(0).(func() *model.Subscription); ok {
|
||||||
|
r0 = rf()
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).(*model.Subscription)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var r1 *model.AppError
|
||||||
|
if rf, ok := ret.Get(1).(func() *model.AppError); ok {
|
||||||
|
r1 = rf()
|
||||||
|
} else {
|
||||||
|
if ret.Get(1) != nil {
|
||||||
|
r1 = ret.Get(1).(*model.AppError)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateCloudCustomer provides a mock function with given fields: customerInfo
|
||||||
|
func (_m *CloudInterface) UpdateCloudCustomer(customerInfo *model.CloudCustomerInfo) (*model.CloudCustomer, *model.AppError) {
|
||||||
|
ret := _m.Called(customerInfo)
|
||||||
|
|
||||||
|
var r0 *model.CloudCustomer
|
||||||
|
if rf, ok := ret.Get(0).(func(*model.CloudCustomerInfo) *model.CloudCustomer); ok {
|
||||||
|
r0 = rf(customerInfo)
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).(*model.CloudCustomer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var r1 *model.AppError
|
||||||
|
if rf, ok := ret.Get(1).(func(*model.CloudCustomerInfo) *model.AppError); ok {
|
||||||
|
r1 = rf(customerInfo)
|
||||||
|
} else {
|
||||||
|
if ret.Get(1) != nil {
|
||||||
|
r1 = ret.Get(1).(*model.AppError)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateCloudCustomerAddress provides a mock function with given fields: address
|
||||||
|
func (_m *CloudInterface) UpdateCloudCustomerAddress(address *model.Address) (*model.CloudCustomer, *model.AppError) {
|
||||||
|
ret := _m.Called(address)
|
||||||
|
|
||||||
|
var r0 *model.CloudCustomer
|
||||||
|
if rf, ok := ret.Get(0).(func(*model.Address) *model.CloudCustomer); ok {
|
||||||
|
r0 = rf(address)
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).(*model.CloudCustomer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var r1 *model.AppError
|
||||||
|
if rf, ok := ret.Get(1).(func(*model.Address) *model.AppError); ok {
|
||||||
|
r1 = rf(address)
|
||||||
|
} else {
|
||||||
|
if ret.Get(1) != nil {
|
||||||
|
r1 = ret.Get(1).(*model.AppError)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
47
einterfaces/mocks/CloudJobInterface.go
Обычный файл
47
einterfaces/mocks/CloudJobInterface.go
Обычный файл
@@ -0,0 +1,47 @@
|
|||||||
|
// Code generated by mockery v1.0.0. DO NOT EDIT.
|
||||||
|
|
||||||
|
// Regenerate this file using `make einterfaces-mocks`.
|
||||||
|
|
||||||
|
package mocks
|
||||||
|
|
||||||
|
import (
|
||||||
|
model "github.com/mattermost/mattermost-server/v5/model"
|
||||||
|
mock "github.com/stretchr/testify/mock"
|
||||||
|
)
|
||||||
|
|
||||||
|
// CloudJobInterface is an autogenerated mock type for the CloudJobInterface type
|
||||||
|
type CloudJobInterface struct {
|
||||||
|
mock.Mock
|
||||||
|
}
|
||||||
|
|
||||||
|
// MakeScheduler provides a mock function with given fields:
|
||||||
|
func (_m *CloudJobInterface) MakeScheduler() model.Scheduler {
|
||||||
|
ret := _m.Called()
|
||||||
|
|
||||||
|
var r0 model.Scheduler
|
||||||
|
if rf, ok := ret.Get(0).(func() model.Scheduler); ok {
|
||||||
|
r0 = rf()
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).(model.Scheduler)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0
|
||||||
|
}
|
||||||
|
|
||||||
|
// MakeWorker provides a mock function with given fields:
|
||||||
|
func (_m *CloudJobInterface) MakeWorker() model.Worker {
|
||||||
|
ret := _m.Called()
|
||||||
|
|
||||||
|
var r0 model.Worker
|
||||||
|
if rf, ok := ret.Get(0).(func() model.Worker); ok {
|
||||||
|
r0 = rf()
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).(model.Worker)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0
|
||||||
|
}
|
||||||
@@ -190,12 +190,12 @@ func (c *Client4) GetUserRoute(userId string) string {
|
|||||||
return fmt.Sprintf(c.GetUsersRoute()+"/%v", userId)
|
return fmt.Sprintf(c.GetUsersRoute()+"/%v", userId)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client4) GetUserThreadsRoute(userId string) string {
|
func (c *Client4) GetUserThreadsRoute(userID, teamID string) string {
|
||||||
return fmt.Sprintf(c.GetUsersRoute()+"/%v/threads", userId)
|
return c.GetUserRoute(userID) + c.GetTeamRoute(teamID) + "/threads"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client4) GetUserThreadRoute(userId, threadId string) string {
|
func (c *Client4) GetUserThreadRoute(userId, teamId, threadId string) string {
|
||||||
return fmt.Sprintf(c.GetUserThreadsRoute(userId)+"/%v", threadId)
|
return c.GetUserThreadsRoute(userId, teamId) + "/" + threadId
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client4) GetUserCategoryRoute(userID, teamID string) string {
|
func (c *Client4) GetUserCategoryRoute(userID, teamID string) string {
|
||||||
@@ -5767,7 +5767,7 @@ func (c *Client4) ListImports() ([]string, *Response) {
|
|||||||
return ArrayFromJson(r.Body), BuildResponse(r)
|
return ArrayFromJson(r.Body), BuildResponse(r)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client4) GetUserThreads(userId string, options GetUserThreadsOpts) (*Threads, *Response) {
|
func (c *Client4) GetUserThreads(userId, teamId string, options GetUserThreadsOpts) (*Threads, *Response) {
|
||||||
v := url.Values{}
|
v := url.Values{}
|
||||||
if options.Since != 0 {
|
if options.Since != 0 {
|
||||||
v.Set("since", fmt.Sprintf("%d", options.Since))
|
v.Set("since", fmt.Sprintf("%d", options.Since))
|
||||||
@@ -5785,7 +5785,7 @@ func (c *Client4) GetUserThreads(userId string, options GetUserThreadsOpts) (*Th
|
|||||||
v.Set("deleted", "true")
|
v.Set("deleted", "true")
|
||||||
}
|
}
|
||||||
|
|
||||||
url := c.GetUserThreadsRoute(userId)
|
url := c.GetUserThreadsRoute(userId, teamId)
|
||||||
if len(v) > 0 {
|
if len(v) > 0 {
|
||||||
url += "?" + v.Encode()
|
url += "?" + v.Encode()
|
||||||
}
|
}
|
||||||
@@ -5802,8 +5802,8 @@ func (c *Client4) GetUserThreads(userId string, options GetUserThreadsOpts) (*Th
|
|||||||
return &threads, BuildResponse(r)
|
return &threads, BuildResponse(r)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client4) UpdateThreadsReadForUser(userId string, timestamp int64) *Response {
|
func (c *Client4) UpdateThreadsReadForUser(userId, teamId string) *Response {
|
||||||
r, appErr := c.DoApiPut(fmt.Sprintf("%s/read/%d", c.GetUserThreadsRoute(userId), timestamp), "")
|
r, appErr := c.DoApiPut(fmt.Sprintf("%s/read", c.GetUserThreadsRoute(userId, teamId)), "")
|
||||||
if appErr != nil {
|
if appErr != nil {
|
||||||
return BuildErrorResponse(r, appErr)
|
return BuildErrorResponse(r, appErr)
|
||||||
}
|
}
|
||||||
@@ -5812,8 +5812,8 @@ func (c *Client4) UpdateThreadsReadForUser(userId string, timestamp int64) *Resp
|
|||||||
return BuildResponse(r)
|
return BuildResponse(r)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client4) UpdateThreadReadForUser(userId, threadId string, timestamp int64) *Response {
|
func (c *Client4) UpdateThreadReadForUser(userId, teamId, threadId string, timestamp int64) *Response {
|
||||||
r, appErr := c.DoApiPut(fmt.Sprintf("%s/read/%d", c.GetUserThreadRoute(userId, threadId), timestamp), "")
|
r, appErr := c.DoApiPut(fmt.Sprintf("%s/read/%d", c.GetUserThreadRoute(userId, teamId, threadId), timestamp), "")
|
||||||
if appErr != nil {
|
if appErr != nil {
|
||||||
return BuildErrorResponse(r, appErr)
|
return BuildErrorResponse(r, appErr)
|
||||||
}
|
}
|
||||||
@@ -5822,13 +5822,13 @@ func (c *Client4) UpdateThreadReadForUser(userId, threadId string, timestamp int
|
|||||||
return BuildResponse(r)
|
return BuildResponse(r)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client4) UpdateThreadFollowForUser(userId, threadId string, state bool) *Response {
|
func (c *Client4) UpdateThreadFollowForUser(userId, teamId, threadId string, state bool) *Response {
|
||||||
var appErr *AppError
|
var appErr *AppError
|
||||||
var r *http.Response
|
var r *http.Response
|
||||||
if state {
|
if state {
|
||||||
r, appErr = c.DoApiPut(c.GetUserThreadRoute(userId, threadId)+"/following", "")
|
r, appErr = c.DoApiPut(c.GetUserThreadRoute(userId, teamId, threadId)+"/following", "")
|
||||||
} else {
|
} else {
|
||||||
r, appErr = c.DoApiDelete(c.GetUserThreadRoute(userId, threadId) + "/following")
|
r, appErr = c.DoApiDelete(c.GetUserThreadRoute(userId, teamId, threadId) + "/following")
|
||||||
}
|
}
|
||||||
if appErr != nil {
|
if appErr != nil {
|
||||||
return BuildErrorResponse(r, appErr)
|
return BuildErrorResponse(r, appErr)
|
||||||
|
|||||||
@@ -16,17 +16,21 @@ type Thread struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ThreadResponse struct {
|
type ThreadResponse struct {
|
||||||
PostId string `json:"id"`
|
PostId string `json:"id"`
|
||||||
ReplyCount int64 `json:"reply_count"`
|
ReplyCount int64 `json:"reply_count"`
|
||||||
LastReplyAt int64 `json:"last_reply_at"`
|
LastReplyAt int64 `json:"last_reply_at"`
|
||||||
LastViewedAt int64 `json:"last_viewed_at"`
|
LastViewedAt int64 `json:"last_viewed_at"`
|
||||||
Participants []*User `json:"participants"`
|
Participants []*User `json:"participants"`
|
||||||
Post *Post `json:"post"`
|
Post *Post `json:"post"`
|
||||||
|
UnreadReplies int64 `json:"unread_replies"`
|
||||||
|
UnreadMentions int64 `json:"unread_mentions"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Threads struct {
|
type Threads struct {
|
||||||
Total int64 `json:"total"`
|
Total int64 `json:"total"`
|
||||||
Threads []*ThreadResponse `json:"threads"`
|
TotalUnreadReplies int64 `json:"total_unread_replies"`
|
||||||
|
TotalUnreadMentions int64 `json:"total_unread_mentions"`
|
||||||
|
Threads []*ThreadResponse `json:"threads"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type GetUserThreadsOpts struct {
|
type GetUserThreadsOpts struct {
|
||||||
|
|||||||
@@ -7756,7 +7756,7 @@ func (s *OpenTracingLayerThreadStore) GetMembershipForUser(userId string, postId
|
|||||||
return result, err
|
return result, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *OpenTracingLayerThreadStore) GetMembershipsForUser(userId string) ([]*model.ThreadMembership, error) {
|
func (s *OpenTracingLayerThreadStore) GetMembershipsForUser(userId string, teamId string) ([]*model.ThreadMembership, error) {
|
||||||
origCtx := s.Root.Store.Context()
|
origCtx := s.Root.Store.Context()
|
||||||
span, newCtx := tracing.StartSpanWithParentByContext(s.Root.Store.Context(), "ThreadStore.GetMembershipsForUser")
|
span, newCtx := tracing.StartSpanWithParentByContext(s.Root.Store.Context(), "ThreadStore.GetMembershipsForUser")
|
||||||
s.Root.Store.SetContext(newCtx)
|
s.Root.Store.SetContext(newCtx)
|
||||||
@@ -7765,7 +7765,7 @@ func (s *OpenTracingLayerThreadStore) GetMembershipsForUser(userId string) ([]*m
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
defer span.Finish()
|
defer span.Finish()
|
||||||
result, err := s.ThreadStore.GetMembershipsForUser(userId)
|
result, err := s.ThreadStore.GetMembershipsForUser(userId, teamId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
span.LogFields(spanlog.Error(err))
|
span.LogFields(spanlog.Error(err))
|
||||||
ext.Error.Set(span, true)
|
ext.Error.Set(span, true)
|
||||||
@@ -7792,7 +7792,7 @@ func (s *OpenTracingLayerThreadStore) GetPosts(threadId string, since int64) ([]
|
|||||||
return result, err
|
return result, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *OpenTracingLayerThreadStore) GetThreadsForUser(userId string, opts model.GetUserThreadsOpts) (*model.Threads, error) {
|
func (s *OpenTracingLayerThreadStore) GetThreadsForUser(userId string, teamId string, opts model.GetUserThreadsOpts) (*model.Threads, error) {
|
||||||
origCtx := s.Root.Store.Context()
|
origCtx := s.Root.Store.Context()
|
||||||
span, newCtx := tracing.StartSpanWithParentByContext(s.Root.Store.Context(), "ThreadStore.GetThreadsForUser")
|
span, newCtx := tracing.StartSpanWithParentByContext(s.Root.Store.Context(), "ThreadStore.GetThreadsForUser")
|
||||||
s.Root.Store.SetContext(newCtx)
|
s.Root.Store.SetContext(newCtx)
|
||||||
@@ -7801,7 +7801,7 @@ func (s *OpenTracingLayerThreadStore) GetThreadsForUser(userId string, opts mode
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
defer span.Finish()
|
defer span.Finish()
|
||||||
result, err := s.ThreadStore.GetThreadsForUser(userId, opts)
|
result, err := s.ThreadStore.GetThreadsForUser(userId, teamId, opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
span.LogFields(spanlog.Error(err))
|
span.LogFields(spanlog.Error(err))
|
||||||
ext.Error.Set(span, true)
|
ext.Error.Set(span, true)
|
||||||
@@ -7810,7 +7810,7 @@ func (s *OpenTracingLayerThreadStore) GetThreadsForUser(userId string, opts mode
|
|||||||
return result, err
|
return result, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *OpenTracingLayerThreadStore) MarkAllAsRead(userId string, timestamp int64) error {
|
func (s *OpenTracingLayerThreadStore) MarkAllAsRead(userId string, teamId string) error {
|
||||||
origCtx := s.Root.Store.Context()
|
origCtx := s.Root.Store.Context()
|
||||||
span, newCtx := tracing.StartSpanWithParentByContext(s.Root.Store.Context(), "ThreadStore.MarkAllAsRead")
|
span, newCtx := tracing.StartSpanWithParentByContext(s.Root.Store.Context(), "ThreadStore.MarkAllAsRead")
|
||||||
s.Root.Store.SetContext(newCtx)
|
s.Root.Store.SetContext(newCtx)
|
||||||
@@ -7819,7 +7819,7 @@ func (s *OpenTracingLayerThreadStore) MarkAllAsRead(userId string, timestamp int
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
defer span.Finish()
|
defer span.Finish()
|
||||||
err := s.ThreadStore.MarkAllAsRead(userId, timestamp)
|
err := s.ThreadStore.MarkAllAsRead(userId, teamId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
span.LogFields(spanlog.Error(err))
|
span.LogFields(spanlog.Error(err))
|
||||||
ext.Error.Set(span, true)
|
ext.Error.Set(span, true)
|
||||||
|
|||||||
@@ -8418,11 +8418,11 @@ func (s *RetryLayerThreadStore) GetMembershipForUser(userId string, postId strin
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *RetryLayerThreadStore) GetMembershipsForUser(userId string) ([]*model.ThreadMembership, error) {
|
func (s *RetryLayerThreadStore) GetMembershipsForUser(userId string, teamId string) ([]*model.ThreadMembership, error) {
|
||||||
|
|
||||||
tries := 0
|
tries := 0
|
||||||
for {
|
for {
|
||||||
result, err := s.ThreadStore.GetMembershipsForUser(userId)
|
result, err := s.ThreadStore.GetMembershipsForUser(userId, teamId)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
@@ -8458,11 +8458,11 @@ func (s *RetryLayerThreadStore) GetPosts(threadId string, since int64) ([]*model
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *RetryLayerThreadStore) GetThreadsForUser(userId string, opts model.GetUserThreadsOpts) (*model.Threads, error) {
|
func (s *RetryLayerThreadStore) GetThreadsForUser(userId string, teamId string, opts model.GetUserThreadsOpts) (*model.Threads, error) {
|
||||||
|
|
||||||
tries := 0
|
tries := 0
|
||||||
for {
|
for {
|
||||||
result, err := s.ThreadStore.GetThreadsForUser(userId, opts)
|
result, err := s.ThreadStore.GetThreadsForUser(userId, teamId, opts)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
@@ -8478,11 +8478,11 @@ func (s *RetryLayerThreadStore) GetThreadsForUser(userId string, opts model.GetU
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *RetryLayerThreadStore) MarkAllAsRead(userId string, timestamp int64) error {
|
func (s *RetryLayerThreadStore) MarkAllAsRead(userId string, teamId string) error {
|
||||||
|
|
||||||
tries := 0
|
tries := 0
|
||||||
for {
|
for {
|
||||||
err := s.ThreadStore.MarkAllAsRead(userId, timestamp)
|
err := s.ThreadStore.MarkAllAsRead(userId, teamId)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -108,44 +108,119 @@ func (s *SqlThreadStore) Get(id string) (*model.Thread, error) {
|
|||||||
return &thread, nil
|
return &thread, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SqlThreadStore) GetThreadsForUser(userId string, opts model.GetUserThreadsOpts) (*model.Threads, error) {
|
func (s *SqlThreadStore) GetThreadsForUser(userId, teamId string, opts model.GetUserThreadsOpts) (*model.Threads, error) {
|
||||||
type JoinedThread struct {
|
type JoinedThread struct {
|
||||||
PostId string
|
PostId string
|
||||||
ReplyCount int64
|
ReplyCount int64
|
||||||
LastReplyAt int64
|
LastReplyAt int64
|
||||||
LastViewedAt int64
|
LastViewedAt int64
|
||||||
Participants model.StringArray
|
UnreadReplies int64
|
||||||
|
UnreadMentions int64
|
||||||
|
Participants model.StringArray
|
||||||
model.Post
|
model.Post
|
||||||
}
|
}
|
||||||
var threads []*JoinedThread
|
|
||||||
|
|
||||||
|
unreadRepliesQuery := "SELECT COUNT(Posts.Id) From Posts Where Posts.RootId=ThreadMemberships.PostId AND Posts.UpdateAt >= ThreadMemberships.LastViewed AND Posts.DeleteAt=0"
|
||||||
fetchConditions := sq.And{
|
fetchConditions := sq.And{
|
||||||
|
sq.Or{sq.Eq{"Channels.TeamId": teamId}, sq.Eq{"Channels.TeamId": ""}},
|
||||||
sq.Eq{"ThreadMemberships.UserId": userId},
|
sq.Eq{"ThreadMemberships.UserId": userId},
|
||||||
sq.Eq{"ThreadMemberships.Following": true},
|
sq.Eq{"ThreadMemberships.Following": true},
|
||||||
}
|
}
|
||||||
if !opts.Deleted {
|
|
||||||
fetchConditions = sq.And{fetchConditions, sq.Eq{"Posts.DeleteAt": 0}}
|
|
||||||
}
|
|
||||||
if opts.Since > 0 {
|
|
||||||
fetchConditions = sq.And{fetchConditions, sq.GtOrEq{"Threads.LastReplyAt": opts.Since}}
|
|
||||||
}
|
|
||||||
pageSize := uint64(30)
|
pageSize := uint64(30)
|
||||||
if opts.PageSize == 0 {
|
if opts.PageSize == 0 {
|
||||||
pageSize = opts.PageSize
|
pageSize = opts.PageSize
|
||||||
}
|
}
|
||||||
query, args, _ := s.getQueryBuilder().
|
|
||||||
Select("Threads.*, Posts.*, ThreadMemberships.LastViewed as LastViewedAt").
|
totalUnreadRepliesChan := make(chan store.StoreResult, 1)
|
||||||
From("Threads").
|
totalCountChan := make(chan store.StoreResult, 1)
|
||||||
LeftJoin("Posts ON Posts.Id = Threads.PostId").
|
totalUnreadMentionsChan := make(chan store.StoreResult, 1)
|
||||||
LeftJoin("ThreadMemberships ON ThreadMemberships.PostId = Threads.PostId").
|
threadsChan := make(chan store.StoreResult, 1)
|
||||||
OrderBy("Threads.LastReplyAt DESC").
|
go func() {
|
||||||
Offset(pageSize * opts.Page).
|
repliesQuery, repliesQueryArgs, _ := s.getQueryBuilder().
|
||||||
Limit(pageSize).
|
Select("COUNT(Posts.Id)").
|
||||||
Where(fetchConditions).ToSql()
|
From("Posts").
|
||||||
_, err := s.GetReplica().Select(&threads, query, args...)
|
LeftJoin("ThreadMemberships ON Posts.RootId = ThreadMemberships.PostId").
|
||||||
if err != nil {
|
LeftJoin("Channels ON Posts.ChannelId = Channels.Id").
|
||||||
return nil, errors.Wrapf(err, "failed to get threads for user id=%s", userId)
|
Where(fetchConditions).
|
||||||
|
Where("Posts.UpdateAt >= ThreadMemberships.LastViewed").ToSql()
|
||||||
|
|
||||||
|
totalUnreadReplies, err := s.GetMaster().SelectInt(repliesQuery, repliesQueryArgs...)
|
||||||
|
totalUnreadRepliesChan <- store.StoreResult{Data: totalUnreadReplies, NErr: errors.Wrapf(err, "failed to get count replies on threads for user id=%s", userId)}
|
||||||
|
close(totalUnreadRepliesChan)
|
||||||
|
}()
|
||||||
|
go func() {
|
||||||
|
threadsQuery, threadsQueryArgs, _ := s.getQueryBuilder().
|
||||||
|
Select("COUNT(ThreadMemberships.PostId)").
|
||||||
|
LeftJoin("Threads ON Threads.PostId = ThreadMemberships.PostId").
|
||||||
|
LeftJoin("Channels ON Threads.ChannelId = Channels.Id").
|
||||||
|
From("ThreadMemberships").
|
||||||
|
Where(fetchConditions).ToSql()
|
||||||
|
|
||||||
|
totalCount, err := s.GetMaster().SelectInt(threadsQuery, threadsQueryArgs...)
|
||||||
|
totalCountChan <- store.StoreResult{Data: totalCount, NErr: err}
|
||||||
|
close(totalCountChan)
|
||||||
|
}()
|
||||||
|
go func() {
|
||||||
|
mentionsQuery, mentionsQueryArgs, _ := s.getQueryBuilder().
|
||||||
|
Select("COALESCE(SUM(ThreadMemberships.UnreadMentions),0)").
|
||||||
|
From("ThreadMemberships").
|
||||||
|
LeftJoin("Threads ON Threads.PostId = ThreadMemberships.PostId").
|
||||||
|
LeftJoin("Channels ON Threads.ChannelId = Channels.Id").
|
||||||
|
Where(fetchConditions).ToSql()
|
||||||
|
totalUnreadMentions, err := s.GetMaster().SelectInt(mentionsQuery, mentionsQueryArgs...)
|
||||||
|
totalUnreadMentionsChan <- store.StoreResult{Data: totalUnreadMentions, NErr: err}
|
||||||
|
close(totalUnreadMentionsChan)
|
||||||
|
}()
|
||||||
|
go func() {
|
||||||
|
newFetchConditions := fetchConditions
|
||||||
|
if !opts.Deleted {
|
||||||
|
newFetchConditions = sq.And{fetchConditions, sq.Eq{"Posts.DeleteAt": 0}}
|
||||||
|
}
|
||||||
|
if opts.Since > 0 {
|
||||||
|
newFetchConditions = sq.And{newFetchConditions, sq.GtOrEq{"Threads.LastReplyAt": opts.Since}}
|
||||||
|
}
|
||||||
|
|
||||||
|
var threads []*JoinedThread
|
||||||
|
query, args, _ := s.getQueryBuilder().
|
||||||
|
Select("Threads.*, Posts.*, ThreadMemberships.LastViewed as LastViewedAt, ThreadMemberships.UnreadMentions as UnreadMentions").
|
||||||
|
From("Threads").
|
||||||
|
Column(sq.Alias(sq.Expr(unreadRepliesQuery), "UnreadReplies")).
|
||||||
|
LeftJoin("Posts ON Posts.Id = Threads.PostId").
|
||||||
|
LeftJoin("Channels ON Posts.ChannelId = Channels.Id").
|
||||||
|
LeftJoin("ThreadMemberships ON ThreadMemberships.PostId = Threads.PostId").
|
||||||
|
Where(newFetchConditions).
|
||||||
|
OrderBy("Threads.LastReplyAt DESC").
|
||||||
|
Offset(pageSize * opts.Page).
|
||||||
|
Limit(pageSize).ToSql()
|
||||||
|
_, err := s.GetReplica().Select(&threads, query, args...)
|
||||||
|
threadsChan <- store.StoreResult{Data: threads, NErr: err}
|
||||||
|
close(threadsChan)
|
||||||
|
}()
|
||||||
|
|
||||||
|
threadsResult := <-threadsChan
|
||||||
|
if threadsResult.NErr != nil {
|
||||||
|
return nil, threadsResult.NErr
|
||||||
}
|
}
|
||||||
|
threads := threadsResult.Data.([]*JoinedThread)
|
||||||
|
|
||||||
|
totalUnreadMentionsResult := <-totalUnreadMentionsChan
|
||||||
|
if totalUnreadMentionsResult.NErr != nil {
|
||||||
|
return nil, totalUnreadMentionsResult.NErr
|
||||||
|
}
|
||||||
|
totalUnreadMentions := totalUnreadMentionsResult.Data.(int64)
|
||||||
|
|
||||||
|
totalCountResult := <-totalCountChan
|
||||||
|
if totalCountResult.NErr != nil {
|
||||||
|
return nil, totalCountResult.NErr
|
||||||
|
}
|
||||||
|
totalCount := totalCountResult.Data.(int64)
|
||||||
|
|
||||||
|
totalUnreadRepliesResult := <-totalUnreadRepliesChan
|
||||||
|
if totalUnreadRepliesResult.NErr != nil {
|
||||||
|
return nil, totalUnreadRepliesResult.NErr
|
||||||
|
}
|
||||||
|
totalUnreadReplies := totalUnreadRepliesResult.Data.(int64)
|
||||||
|
|
||||||
var userIds []string
|
var userIds []string
|
||||||
userIdMap := map[string]bool{}
|
userIdMap := map[string]bool{}
|
||||||
@@ -159,9 +234,8 @@ func (s *SqlThreadStore) GetThreadsForUser(userId string, opts model.GetUserThre
|
|||||||
}
|
}
|
||||||
var users []*model.User
|
var users []*model.User
|
||||||
if opts.Extended {
|
if opts.Extended {
|
||||||
query, args, _ = s.getQueryBuilder().Select("*").From("Users").Where(sq.Eq{"Id": userIds}).ToSql()
|
query, args, _ := s.getQueryBuilder().Select("*").From("Users").Where(sq.Eq{"Id": userIds}).ToSql()
|
||||||
_, err = s.GetReplica().Select(&users, query, args...)
|
if _, err := s.GetReplica().Select(&users, query, args...); err != nil {
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrapf(err, "failed to get threads for user id=%s", userId)
|
return nil, errors.Wrapf(err, "failed to get threads for user id=%s", userId)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -171,8 +245,10 @@ func (s *SqlThreadStore) GetThreadsForUser(userId string, opts model.GetUserThre
|
|||||||
}
|
}
|
||||||
|
|
||||||
result := &model.Threads{
|
result := &model.Threads{
|
||||||
Total: 0,
|
Total: totalCount,
|
||||||
Threads: nil,
|
Threads: nil,
|
||||||
|
TotalUnreadMentions: totalUnreadMentions,
|
||||||
|
TotalUnreadReplies: totalUnreadReplies,
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, thread := range threads {
|
for _, thread := range threads {
|
||||||
@@ -191,20 +267,37 @@ func (s *SqlThreadStore) GetThreadsForUser(userId string, opts model.GetUserThre
|
|||||||
participants = append(participants, participant)
|
participants = append(participants, participant)
|
||||||
}
|
}
|
||||||
result.Threads = append(result.Threads, &model.ThreadResponse{
|
result.Threads = append(result.Threads, &model.ThreadResponse{
|
||||||
PostId: thread.PostId,
|
PostId: thread.PostId,
|
||||||
ReplyCount: thread.ReplyCount,
|
ReplyCount: thread.ReplyCount,
|
||||||
LastReplyAt: thread.LastReplyAt,
|
LastReplyAt: thread.LastReplyAt,
|
||||||
LastViewedAt: thread.LastViewedAt,
|
LastViewedAt: thread.LastViewedAt,
|
||||||
Participants: participants,
|
UnreadReplies: thread.UnreadReplies,
|
||||||
Post: &thread.Post,
|
UnreadMentions: thread.UnreadMentions,
|
||||||
|
Participants: participants,
|
||||||
|
Post: &thread.Post,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SqlThreadStore) MarkAllAsRead(userId string, timestamp int64) error {
|
func (s *SqlThreadStore) MarkAllAsRead(userId, teamId string) error {
|
||||||
query, args, _ := s.getQueryBuilder().Update("ThreadMemberships").Where(sq.Eq{"UserId": userId}).Set("LastViewed", timestamp).ToSql()
|
memberships, err := s.GetMembershipsForUser(userId, teamId)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
var membershipIds []string
|
||||||
|
for _, m := range memberships {
|
||||||
|
membershipIds = append(membershipIds, m.PostId)
|
||||||
|
}
|
||||||
|
timestamp := model.GetMillis()
|
||||||
|
query, args, _ := s.getQueryBuilder().
|
||||||
|
Update("ThreadMemberships").
|
||||||
|
Where(sq.Eq{"PostId": membershipIds}).
|
||||||
|
Where(sq.Eq{"UserId": userId}).
|
||||||
|
Set("LastViewed", timestamp).
|
||||||
|
Set("UnreadMentions", 0).
|
||||||
|
ToSql()
|
||||||
if _, err := s.GetMaster().Exec(query, args...); err != nil {
|
if _, err := s.GetMaster().Exec(query, args...); err != nil {
|
||||||
return errors.Wrapf(err, "failed to update thread read state for user id=%s", userId)
|
return errors.Wrapf(err, "failed to update thread read state for user id=%s", userId)
|
||||||
}
|
}
|
||||||
@@ -212,7 +305,11 @@ func (s *SqlThreadStore) MarkAllAsRead(userId string, timestamp int64) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *SqlThreadStore) MarkAsRead(userId, threadId string, timestamp int64) error {
|
func (s *SqlThreadStore) MarkAsRead(userId, threadId string, timestamp int64) error {
|
||||||
query, args, _ := s.getQueryBuilder().Update("ThreadMemberships").Where(sq.Eq{"UserId": userId}, sq.Eq{"PostId": threadId}).Set("LastViewed", timestamp).ToSql()
|
query, args, _ := s.getQueryBuilder().
|
||||||
|
Update("ThreadMemberships").
|
||||||
|
Where(sq.Eq{"UserId": userId}, sq.Eq{"PostId": threadId}).
|
||||||
|
Set("LastViewed", timestamp).
|
||||||
|
ToSql()
|
||||||
if _, err := s.GetMaster().Exec(query, args...); err != nil {
|
if _, err := s.GetMaster().Exec(query, args...); err != nil {
|
||||||
return errors.Wrapf(err, "failed to update thread read state for user id=%s thread_id=%v", userId, threadId)
|
return errors.Wrapf(err, "failed to update thread read state for user id=%s thread_id=%v", userId, threadId)
|
||||||
}
|
}
|
||||||
@@ -244,9 +341,19 @@ func (s *SqlThreadStore) UpdateMembership(membership *model.ThreadMembership) (*
|
|||||||
return membership, nil
|
return membership, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SqlThreadStore) GetMembershipsForUser(userId string) ([]*model.ThreadMembership, error) {
|
func (s *SqlThreadStore) GetMembershipsForUser(userId, teamId string) ([]*model.ThreadMembership, error) {
|
||||||
var memberships []*model.ThreadMembership
|
var memberships []*model.ThreadMembership
|
||||||
_, err := s.GetReplica().Select(&memberships, "SELECT * from ThreadMemberships WHERE UserId = :UserId", map[string]interface{}{"UserId": userId})
|
|
||||||
|
query, args, _ := s.getQueryBuilder().
|
||||||
|
Select("ThreadMemberships.*").
|
||||||
|
Join("Threads ON Threads.PostId = ThreadMemberships.PostId").
|
||||||
|
Join("Channels ON Threads.ChannelId = Channels.Id").
|
||||||
|
From("ThreadMemberships").
|
||||||
|
Where(sq.Or{sq.Eq{"Channels.TeamId": teamId}, sq.Eq{"Channels.TeamId": ""}}).
|
||||||
|
Where(sq.Eq{"ThreadMemberships.UserId": userId}).
|
||||||
|
ToSql()
|
||||||
|
|
||||||
|
_, err := s.GetReplica().Select(&memberships, query, args...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "failed to get thread membership with userid=%s", userId)
|
return nil, errors.Wrapf(err, "failed to get thread membership with userid=%s", userId)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -251,16 +251,16 @@ type ThreadStore interface {
|
|||||||
Save(thread *model.Thread) (*model.Thread, error)
|
Save(thread *model.Thread) (*model.Thread, error)
|
||||||
Update(thread *model.Thread) (*model.Thread, error)
|
Update(thread *model.Thread) (*model.Thread, error)
|
||||||
Get(id string) (*model.Thread, error)
|
Get(id string) (*model.Thread, error)
|
||||||
GetThreadsForUser(userId string, opts model.GetUserThreadsOpts) (*model.Threads, error)
|
GetThreadsForUser(userId, teamId string, opts model.GetUserThreadsOpts) (*model.Threads, error)
|
||||||
Delete(postId string) error
|
Delete(postId string) error
|
||||||
GetPosts(threadId string, since int64) ([]*model.Post, error)
|
GetPosts(threadId string, since int64) ([]*model.Post, error)
|
||||||
|
|
||||||
MarkAllAsRead(userId string, timestamp int64) error
|
MarkAllAsRead(userId, teamId string) error
|
||||||
MarkAsRead(userId, threadId string, timestamp int64) error
|
MarkAsRead(userId, threadId string, timestamp int64) error
|
||||||
|
|
||||||
SaveMembership(membership *model.ThreadMembership) (*model.ThreadMembership, error)
|
SaveMembership(membership *model.ThreadMembership) (*model.ThreadMembership, error)
|
||||||
UpdateMembership(membership *model.ThreadMembership) (*model.ThreadMembership, error)
|
UpdateMembership(membership *model.ThreadMembership) (*model.ThreadMembership, error)
|
||||||
GetMembershipsForUser(userId string) ([]*model.ThreadMembership, error)
|
GetMembershipsForUser(userId, teamId string) ([]*model.ThreadMembership, error)
|
||||||
GetMembershipForUser(userId, postId string) (*model.ThreadMembership, error)
|
GetMembershipForUser(userId, postId string) (*model.ThreadMembership, error)
|
||||||
DeleteMembershipForUser(userId, postId string) error
|
DeleteMembershipForUser(userId, postId string) error
|
||||||
CreateMembershipIfNeeded(userId, postId string, following, incrementMentions, updateFollowing bool) error
|
CreateMembershipIfNeeded(userId, postId string, following, incrementMentions, updateFollowing bool) error
|
||||||
|
|||||||
@@ -125,13 +125,13 @@ func (_m *ThreadStore) GetMembershipForUser(userId string, postId string) (*mode
|
|||||||
return r0, r1
|
return r0, r1
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetMembershipsForUser provides a mock function with given fields: userId
|
// GetMembershipsForUser provides a mock function with given fields: userId, teamId
|
||||||
func (_m *ThreadStore) GetMembershipsForUser(userId string) ([]*model.ThreadMembership, error) {
|
func (_m *ThreadStore) GetMembershipsForUser(userId string, teamId string) ([]*model.ThreadMembership, error) {
|
||||||
ret := _m.Called(userId)
|
ret := _m.Called(userId, teamId)
|
||||||
|
|
||||||
var r0 []*model.ThreadMembership
|
var r0 []*model.ThreadMembership
|
||||||
if rf, ok := ret.Get(0).(func(string) []*model.ThreadMembership); ok {
|
if rf, ok := ret.Get(0).(func(string, string) []*model.ThreadMembership); ok {
|
||||||
r0 = rf(userId)
|
r0 = rf(userId, teamId)
|
||||||
} else {
|
} else {
|
||||||
if ret.Get(0) != nil {
|
if ret.Get(0) != nil {
|
||||||
r0 = ret.Get(0).([]*model.ThreadMembership)
|
r0 = ret.Get(0).([]*model.ThreadMembership)
|
||||||
@@ -139,8 +139,8 @@ func (_m *ThreadStore) GetMembershipsForUser(userId string) ([]*model.ThreadMemb
|
|||||||
}
|
}
|
||||||
|
|
||||||
var r1 error
|
var r1 error
|
||||||
if rf, ok := ret.Get(1).(func(string) error); ok {
|
if rf, ok := ret.Get(1).(func(string, string) error); ok {
|
||||||
r1 = rf(userId)
|
r1 = rf(userId, teamId)
|
||||||
} else {
|
} else {
|
||||||
r1 = ret.Error(1)
|
r1 = ret.Error(1)
|
||||||
}
|
}
|
||||||
@@ -171,13 +171,13 @@ func (_m *ThreadStore) GetPosts(threadId string, since int64) ([]*model.Post, er
|
|||||||
return r0, r1
|
return r0, r1
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetThreadsForUser provides a mock function with given fields: userId, opts
|
// GetThreadsForUser provides a mock function with given fields: userId, teamId, opts
|
||||||
func (_m *ThreadStore) GetThreadsForUser(userId string, opts model.GetUserThreadsOpts) (*model.Threads, error) {
|
func (_m *ThreadStore) GetThreadsForUser(userId string, teamId string, opts model.GetUserThreadsOpts) (*model.Threads, error) {
|
||||||
ret := _m.Called(userId, opts)
|
ret := _m.Called(userId, teamId, opts)
|
||||||
|
|
||||||
var r0 *model.Threads
|
var r0 *model.Threads
|
||||||
if rf, ok := ret.Get(0).(func(string, model.GetUserThreadsOpts) *model.Threads); ok {
|
if rf, ok := ret.Get(0).(func(string, string, model.GetUserThreadsOpts) *model.Threads); ok {
|
||||||
r0 = rf(userId, opts)
|
r0 = rf(userId, teamId, opts)
|
||||||
} else {
|
} else {
|
||||||
if ret.Get(0) != nil {
|
if ret.Get(0) != nil {
|
||||||
r0 = ret.Get(0).(*model.Threads)
|
r0 = ret.Get(0).(*model.Threads)
|
||||||
@@ -185,8 +185,8 @@ func (_m *ThreadStore) GetThreadsForUser(userId string, opts model.GetUserThread
|
|||||||
}
|
}
|
||||||
|
|
||||||
var r1 error
|
var r1 error
|
||||||
if rf, ok := ret.Get(1).(func(string, model.GetUserThreadsOpts) error); ok {
|
if rf, ok := ret.Get(1).(func(string, string, model.GetUserThreadsOpts) error); ok {
|
||||||
r1 = rf(userId, opts)
|
r1 = rf(userId, teamId, opts)
|
||||||
} else {
|
} else {
|
||||||
r1 = ret.Error(1)
|
r1 = ret.Error(1)
|
||||||
}
|
}
|
||||||
@@ -194,13 +194,13 @@ func (_m *ThreadStore) GetThreadsForUser(userId string, opts model.GetUserThread
|
|||||||
return r0, r1
|
return r0, r1
|
||||||
}
|
}
|
||||||
|
|
||||||
// MarkAllAsRead provides a mock function with given fields: userId, timestamp
|
// MarkAllAsRead provides a mock function with given fields: userId, teamId
|
||||||
func (_m *ThreadStore) MarkAllAsRead(userId string, timestamp int64) error {
|
func (_m *ThreadStore) MarkAllAsRead(userId string, teamId string) error {
|
||||||
ret := _m.Called(userId, timestamp)
|
ret := _m.Called(userId, teamId)
|
||||||
|
|
||||||
var r0 error
|
var r0 error
|
||||||
if rf, ok := ret.Get(0).(func(string, int64) error); ok {
|
if rf, ok := ret.Get(0).(func(string, string) error); ok {
|
||||||
r0 = rf(userId, timestamp)
|
r0 = rf(userId, teamId)
|
||||||
} else {
|
} else {
|
||||||
r0 = ret.Error(0)
|
r0 = ret.Error(0)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7000,10 +7000,10 @@ func (s *TimerLayerThreadStore) GetMembershipForUser(userId string, postId strin
|
|||||||
return result, err
|
return result, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *TimerLayerThreadStore) GetMembershipsForUser(userId string) ([]*model.ThreadMembership, error) {
|
func (s *TimerLayerThreadStore) GetMembershipsForUser(userId string, teamId string) ([]*model.ThreadMembership, error) {
|
||||||
start := timemodule.Now()
|
start := timemodule.Now()
|
||||||
|
|
||||||
result, err := s.ThreadStore.GetMembershipsForUser(userId)
|
result, err := s.ThreadStore.GetMembershipsForUser(userId, teamId)
|
||||||
|
|
||||||
elapsed := float64(timemodule.Since(start)) / float64(timemodule.Second)
|
elapsed := float64(timemodule.Since(start)) / float64(timemodule.Second)
|
||||||
if s.Root.Metrics != nil {
|
if s.Root.Metrics != nil {
|
||||||
@@ -7032,10 +7032,10 @@ func (s *TimerLayerThreadStore) GetPosts(threadId string, since int64) ([]*model
|
|||||||
return result, err
|
return result, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *TimerLayerThreadStore) GetThreadsForUser(userId string, opts model.GetUserThreadsOpts) (*model.Threads, error) {
|
func (s *TimerLayerThreadStore) GetThreadsForUser(userId string, teamId string, opts model.GetUserThreadsOpts) (*model.Threads, error) {
|
||||||
start := timemodule.Now()
|
start := timemodule.Now()
|
||||||
|
|
||||||
result, err := s.ThreadStore.GetThreadsForUser(userId, opts)
|
result, err := s.ThreadStore.GetThreadsForUser(userId, teamId, opts)
|
||||||
|
|
||||||
elapsed := float64(timemodule.Since(start)) / float64(timemodule.Second)
|
elapsed := float64(timemodule.Since(start)) / float64(timemodule.Second)
|
||||||
if s.Root.Metrics != nil {
|
if s.Root.Metrics != nil {
|
||||||
@@ -7048,10 +7048,10 @@ func (s *TimerLayerThreadStore) GetThreadsForUser(userId string, opts model.GetU
|
|||||||
return result, err
|
return result, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *TimerLayerThreadStore) MarkAllAsRead(userId string, timestamp int64) error {
|
func (s *TimerLayerThreadStore) MarkAllAsRead(userId string, teamId string) error {
|
||||||
start := timemodule.Now()
|
start := timemodule.Now()
|
||||||
|
|
||||||
err := s.ThreadStore.MarkAllAsRead(userId, timestamp)
|
err := s.ThreadStore.MarkAllAsRead(userId, teamId)
|
||||||
|
|
||||||
elapsed := float64(timemodule.Since(start)) / float64(timemodule.Second)
|
elapsed := float64(timemodule.Since(start)) / float64(timemodule.Second)
|
||||||
if s.Root.Metrics != nil {
|
if s.Root.Metrics != nil {
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user