MM-31713 Server/API: GetUserThread method (#16659)
Co-authored-by: Mattermod <mattermod@users.noreply.github.com>
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
c14194d78b
Коммит
77da23e84b
22
api4/user.go
22
api4/user.go
@@ -95,6 +95,7 @@ func (api *API) InitUser() {
|
|||||||
api.BaseRoutes.UserThreads.Handle("", api.ApiSessionRequired(getThreadsForUser)).Methods("GET")
|
api.BaseRoutes.UserThreads.Handle("", api.ApiSessionRequired(getThreadsForUser)).Methods("GET")
|
||||||
api.BaseRoutes.UserThreads.Handle("/read", api.ApiSessionRequired(updateReadStateAllThreadsByUser)).Methods("PUT")
|
api.BaseRoutes.UserThreads.Handle("/read", api.ApiSessionRequired(updateReadStateAllThreadsByUser)).Methods("PUT")
|
||||||
|
|
||||||
|
api.BaseRoutes.UserThread.Handle("", api.ApiSessionRequired(getThreadForUser)).Methods("GET")
|
||||||
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")
|
||||||
api.BaseRoutes.UserThread.Handle("/read/{timestamp:[0-9]+}", api.ApiSessionRequired(updateReadStateThreadByUser)).Methods("PUT")
|
api.BaseRoutes.UserThread.Handle("/read/{timestamp:[0-9]+}", api.ApiSessionRequired(updateReadStateThreadByUser)).Methods("PUT")
|
||||||
@@ -2820,6 +2821,27 @@ func migrateAuthToSaml(c *Context, w http.ResponseWriter, r *http.Request) {
|
|||||||
ReturnStatusOK(w)
|
ReturnStatusOK(w)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getThreadForUser(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||||
|
c.RequireUserId().RequireTeamId().RequireThreadId()
|
||||||
|
if c.Err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !c.App.SessionHasPermissionToUser(*c.App.Session(), c.Params.UserId) {
|
||||||
|
c.SetPermissionError(model.PERMISSION_EDIT_OTHER_USERS)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
extendedStr := r.URL.Query().Get("extended")
|
||||||
|
|
||||||
|
extended, _ := strconv.ParseBool(extendedStr)
|
||||||
|
threads, err := c.App.GetThreadForUser(c.Params.UserId, c.Params.TeamId, c.Params.ThreadId, extended)
|
||||||
|
if err != nil {
|
||||||
|
c.Err = err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
w.Write([]byte(threads.ToJson()))
|
||||||
|
}
|
||||||
|
|
||||||
func getThreadsForUser(c *Context, w http.ResponseWriter, r *http.Request) {
|
func getThreadsForUser(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||||
c.RequireUserId().RequireTeamId()
|
c.RequireUserId().RequireTeamId()
|
||||||
if c.Err != nil {
|
if c.Err != nil {
|
||||||
|
|||||||
@@ -5668,6 +5668,45 @@ func TestThreadCounts(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSingleThreadGet(t *testing.T) {
|
||||||
|
th := Setup(t).InitBasic()
|
||||||
|
defer th.TearDown()
|
||||||
|
os.Setenv("MM_FEATUREFLAGS_COLLAPSEDTHREADS", "true")
|
||||||
|
defer os.Unsetenv("MM_FEATUREFLAGS_COLLAPSEDTHREADS")
|
||||||
|
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, _ := postAndCheck(t, Client, &model.Post{ChannelId: th.BasicChannel.Id, Message: "testMsg"})
|
||||||
|
// reply with another
|
||||||
|
time.Sleep(1)
|
||||||
|
postAndCheck(t, th.SystemAdminClient, &model.Post{ChannelId: th.BasicChannel.Id, Message: "testReply", RootId: rpost.Id})
|
||||||
|
|
||||||
|
// create another thread to check that we are not returning it by mistake
|
||||||
|
rpost2, _ := postAndCheck(t, Client, &model.Post{ChannelId: th.BasicChannel2.Id, Message: "testMsg2"})
|
||||||
|
time.Sleep(1)
|
||||||
|
postAndCheck(t, th.SystemAdminClient, &model.Post{ChannelId: th.BasicChannel2.Id, Message: "testReply", RootId: rpost2.Id})
|
||||||
|
|
||||||
|
// regular user should have two threads with 3 replies total
|
||||||
|
threads, _ := checkThreadListReplies(t, th, th.Client, th.BasicUser.Id, 2, 2, nil)
|
||||||
|
|
||||||
|
tr, resp := th.Client.GetUserThread(th.BasicUser.Id, th.BasicTeam.Id, threads.Threads[0].PostId, false)
|
||||||
|
CheckNoError(t, resp)
|
||||||
|
require.NotNil(t, tr)
|
||||||
|
require.Equal(t, threads.Threads[0].PostId, tr.PostId)
|
||||||
|
require.Empty(t, tr.Participants[0].Username)
|
||||||
|
|
||||||
|
tr, resp = th.Client.GetUserThread(th.BasicUser.Id, th.BasicTeam.Id, threads.Threads[0].PostId, true)
|
||||||
|
CheckNoError(t, resp)
|
||||||
|
require.NotEmpty(t, tr.Participants[0].Username)
|
||||||
|
}
|
||||||
|
|
||||||
func TestMaintainUnreadMentionsInThread(t *testing.T) {
|
func TestMaintainUnreadMentionsInThread(t *testing.T) {
|
||||||
th := Setup(t).InitBasic()
|
th := Setup(t).InitBasic()
|
||||||
defer th.TearDown()
|
defer th.TearDown()
|
||||||
|
|||||||
@@ -693,6 +693,7 @@ 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)
|
||||||
|
GetThreadForUser(userId, teamId, threadId string, extended bool) (*model.ThreadResponse, *model.AppError)
|
||||||
GetThreadMembershipsForUser(userId, teamId string) ([]*model.ThreadMembership, error)
|
GetThreadMembershipsForUser(userId, teamId string) ([]*model.ThreadMembership, error)
|
||||||
GetThreadsForUser(userId, teamId 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)
|
||||||
|
|||||||
@@ -8529,6 +8529,28 @@ func (a *OpenTracingAppLayer) GetTermsOfService(id string) (*model.TermsOfServic
|
|||||||
return resultVar0, resultVar1
|
return resultVar0, resultVar1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *OpenTracingAppLayer) GetThreadForUser(userId string, teamId string, threadId string, extended bool) (*model.ThreadResponse, *model.AppError) {
|
||||||
|
origCtx := a.ctx
|
||||||
|
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.GetThreadForUser")
|
||||||
|
|
||||||
|
a.ctx = newCtx
|
||||||
|
a.app.Srv().Store.SetContext(newCtx)
|
||||||
|
defer func() {
|
||||||
|
a.app.Srv().Store.SetContext(origCtx)
|
||||||
|
a.ctx = origCtx
|
||||||
|
}()
|
||||||
|
|
||||||
|
defer span.Finish()
|
||||||
|
resultVar0, resultVar1 := a.app.GetThreadForUser(userId, teamId, threadId, extended)
|
||||||
|
|
||||||
|
if resultVar1 != nil {
|
||||||
|
span.LogFields(spanlog.Error(resultVar1))
|
||||||
|
ext.Error.Set(span, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
return resultVar0, resultVar1
|
||||||
|
}
|
||||||
|
|
||||||
func (a *OpenTracingAppLayer) GetThreadMembershipsForUser(userId string, teamId 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")
|
||||||
|
|||||||
13
app/user.go
13
app/user.go
@@ -2371,6 +2371,19 @@ func (a *App) GetThreadsForUser(userId, teamId string, options model.GetUserThre
|
|||||||
return threads, nil
|
return threads, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *App) GetThreadForUser(userId, teamId, threadId string, extended bool) (*model.ThreadResponse, *model.AppError) {
|
||||||
|
thread, err := a.Srv().Store.Thread().GetThreadForUser(userId, teamId, threadId, extended)
|
||||||
|
if err != nil {
|
||||||
|
return nil, model.NewAppError("GetThreadForUser", "app.user.get_threads_for_user.app_error", nil, err.Error(), http.StatusInternalServerError)
|
||||||
|
}
|
||||||
|
if thread == nil {
|
||||||
|
return nil, model.NewAppError("GetThreadForUser", "app.user.get_threads_for_user.not_found", nil, "thread not found/followed", http.StatusNotFound)
|
||||||
|
}
|
||||||
|
a.sanitizeProfiles(thread.Participants, false)
|
||||||
|
thread.Post.SanitizeProps()
|
||||||
|
return thread, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (a *App) UpdateThreadsReadForUser(userId, teamId string) *model.AppError {
|
func (a *App) UpdateThreadsReadForUser(userId, teamId string) *model.AppError {
|
||||||
nErr := a.Srv().Store.Thread().MarkAllAsRead(userId, teamId)
|
nErr := a.Srv().Store.Thread().MarkAllAsRead(userId, teamId)
|
||||||
if nErr != nil {
|
if nErr != nil {
|
||||||
|
|||||||
@@ -5626,6 +5626,10 @@
|
|||||||
"id": "app.user.get_threads_for_user.app_error",
|
"id": "app.user.get_threads_for_user.app_error",
|
||||||
"translation": "Unable to get user threads"
|
"translation": "Unable to get user threads"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": "app.user.get_threads_for_user.not_found",
|
||||||
|
"translation": "User thread doesn't exist or is not followed"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "app.user.get_total_users_count.app_error",
|
"id": "app.user.get_total_users_count.app_error",
|
||||||
"translation": "We could not count the users."
|
"translation": "We could not count the users."
|
||||||
|
|||||||
@@ -5824,6 +5824,23 @@ func (c *Client4) GetUserThreads(userId, teamId string, options GetUserThreadsOp
|
|||||||
return &threads, BuildResponse(r)
|
return &threads, BuildResponse(r)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Client4) GetUserThread(userId, teamId, threadId string, extended bool) (*ThreadResponse, *Response) {
|
||||||
|
url := c.GetUserThreadRoute(userId, teamId, threadId)
|
||||||
|
if extended {
|
||||||
|
url += "?extended=true"
|
||||||
|
}
|
||||||
|
r, appErr := c.DoApiGet(url, "")
|
||||||
|
if appErr != nil {
|
||||||
|
return nil, BuildErrorResponse(r, appErr)
|
||||||
|
}
|
||||||
|
defer closeBody(r)
|
||||||
|
|
||||||
|
var thread ThreadResponse
|
||||||
|
json.NewDecoder(r.Body).Decode(&thread)
|
||||||
|
|
||||||
|
return &thread, BuildResponse(r)
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Client4) UpdateThreadsReadForUser(userId, teamId string) *Response {
|
func (c *Client4) UpdateThreadsReadForUser(userId, teamId string) *Response {
|
||||||
r, appErr := c.DoApiPut(fmt.Sprintf("%s/read", c.GetUserThreadsRoute(userId, teamId)), "")
|
r, appErr := c.DoApiPut(fmt.Sprintf("%s/read", c.GetUserThreadsRoute(userId, teamId)), "")
|
||||||
if appErr != nil {
|
if appErr != nil {
|
||||||
|
|||||||
@@ -50,6 +50,11 @@ type GetUserThreadsOpts struct {
|
|||||||
Since uint64
|
Since uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (o *ThreadResponse) ToJson() string {
|
||||||
|
b, _ := json.Marshal(o)
|
||||||
|
return string(b)
|
||||||
|
}
|
||||||
|
|
||||||
func (o *Threads) ToJson() string {
|
func (o *Threads) ToJson() string {
|
||||||
b, _ := json.Marshal(o)
|
b, _ := json.Marshal(o)
|
||||||
return string(b)
|
return string(b)
|
||||||
|
|||||||
@@ -7828,6 +7828,24 @@ func (s *OpenTracingLayerThreadStore) GetPosts(threadId string, since int64) ([]
|
|||||||
return result, err
|
return result, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *OpenTracingLayerThreadStore) GetThreadForUser(userId string, teamId string, threadId string, extended bool) (*model.ThreadResponse, error) {
|
||||||
|
origCtx := s.Root.Store.Context()
|
||||||
|
span, newCtx := tracing.StartSpanWithParentByContext(s.Root.Store.Context(), "ThreadStore.GetThreadForUser")
|
||||||
|
s.Root.Store.SetContext(newCtx)
|
||||||
|
defer func() {
|
||||||
|
s.Root.Store.SetContext(origCtx)
|
||||||
|
}()
|
||||||
|
|
||||||
|
defer span.Finish()
|
||||||
|
result, err := s.ThreadStore.GetThreadForUser(userId, teamId, threadId, extended)
|
||||||
|
if err != nil {
|
||||||
|
span.LogFields(spanlog.Error(err))
|
||||||
|
ext.Error.Set(span, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, err
|
||||||
|
}
|
||||||
|
|
||||||
func (s *OpenTracingLayerThreadStore) GetThreadsForUser(userId string, teamId 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")
|
||||||
|
|||||||
@@ -8498,6 +8498,26 @@ func (s *RetryLayerThreadStore) GetPosts(threadId string, since int64) ([]*model
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *RetryLayerThreadStore) GetThreadForUser(userId string, teamId string, threadId string, extended bool) (*model.ThreadResponse, error) {
|
||||||
|
|
||||||
|
tries := 0
|
||||||
|
for {
|
||||||
|
result, err := s.ThreadStore.GetThreadForUser(userId, teamId, threadId, extended)
|
||||||
|
if err == nil {
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
if !isRepeatableError(err) {
|
||||||
|
return result, err
|
||||||
|
}
|
||||||
|
tries++
|
||||||
|
if tries >= 3 {
|
||||||
|
err = errors.Wrap(err, "giving up after 3 consecutive repeatable transaction failures")
|
||||||
|
return result, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
func (s *RetryLayerThreadStore) GetThreadsForUser(userId string, teamId 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
|
||||||
|
|||||||
@@ -283,6 +283,71 @@ func (s *SqlThreadStore) GetThreadsForUser(userId, teamId string, opts model.Get
|
|||||||
|
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
func (s *SqlThreadStore) GetThreadForUser(userId, teamId, threadId string, extended bool) (*model.ThreadResponse, error) {
|
||||||
|
type JoinedThread struct {
|
||||||
|
PostId string
|
||||||
|
Following bool
|
||||||
|
ReplyCount int64
|
||||||
|
LastReplyAt int64
|
||||||
|
LastViewedAt int64
|
||||||
|
UnreadReplies int64
|
||||||
|
UnreadMentions int64
|
||||||
|
Participants model.StringArray
|
||||||
|
model.Post
|
||||||
|
}
|
||||||
|
|
||||||
|
unreadRepliesQuery := "SELECT COUNT(Posts.Id) From Posts Where Posts.RootId=ThreadMemberships.PostId AND Posts.UpdateAt >= ThreadMemberships.LastViewed AND Posts.DeleteAt=0"
|
||||||
|
fetchConditions := sq.And{
|
||||||
|
sq.Or{sq.Eq{"Channels.TeamId": teamId}, sq.Eq{"Channels.TeamId": ""}},
|
||||||
|
sq.Eq{"ThreadMemberships.UserId": userId},
|
||||||
|
sq.Eq{"Threads.PostId": threadId},
|
||||||
|
}
|
||||||
|
|
||||||
|
var thread JoinedThread
|
||||||
|
query, args, _ := s.getQueryBuilder().
|
||||||
|
Select("Threads.*, Posts.*, ThreadMemberships.LastViewed as LastViewedAt, ThreadMemberships.UnreadMentions as UnreadMentions, ThreadMemberships.Following").
|
||||||
|
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(fetchConditions).ToSql()
|
||||||
|
err := s.GetReplica().SelectOne(&thread, query, args...)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if !thread.Following {
|
||||||
|
return nil, nil // in case the thread is not followed anymore - return nil error to be interpreted as 404
|
||||||
|
}
|
||||||
|
|
||||||
|
var users []*model.User
|
||||||
|
if extended {
|
||||||
|
var err error
|
||||||
|
users, err = s.User().GetProfileByIds(thread.Participants, &store.UserGetByIdsOpts{}, true)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(err, "failed to get threads for user id=%s", userId)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for _, userId := range thread.Participants {
|
||||||
|
users = append(users, &model.User{Id: userId})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result := &model.ThreadResponse{
|
||||||
|
PostId: thread.PostId,
|
||||||
|
ReplyCount: thread.ReplyCount,
|
||||||
|
LastReplyAt: thread.LastReplyAt,
|
||||||
|
LastViewedAt: thread.LastViewedAt,
|
||||||
|
UnreadReplies: thread.UnreadReplies,
|
||||||
|
UnreadMentions: thread.UnreadMentions,
|
||||||
|
Participants: users,
|
||||||
|
Post: &thread.Post,
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (s *SqlThreadStore) MarkAllAsRead(userId, teamId string) error {
|
func (s *SqlThreadStore) MarkAllAsRead(userId, teamId string) error {
|
||||||
memberships, err := s.GetMembershipsForUser(userId, teamId)
|
memberships, err := s.GetMembershipsForUser(userId, teamId)
|
||||||
|
|||||||
@@ -252,6 +252,7 @@ type ThreadStore interface {
|
|||||||
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, teamId string, opts model.GetUserThreadsOpts) (*model.Threads, error)
|
GetThreadsForUser(userId, teamId string, opts model.GetUserThreadsOpts) (*model.Threads, error)
|
||||||
|
GetThreadForUser(userId, teamId, threadId string, extended bool) (*model.ThreadResponse, 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)
|
||||||
|
|
||||||
|
|||||||
@@ -171,6 +171,29 @@ func (_m *ThreadStore) GetPosts(threadId string, since int64) ([]*model.Post, er
|
|||||||
return r0, r1
|
return r0, r1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetThreadForUser provides a mock function with given fields: userId, teamId, threadId, extended
|
||||||
|
func (_m *ThreadStore) GetThreadForUser(userId string, teamId string, threadId string, extended bool) (*model.ThreadResponse, error) {
|
||||||
|
ret := _m.Called(userId, teamId, threadId, extended)
|
||||||
|
|
||||||
|
var r0 *model.ThreadResponse
|
||||||
|
if rf, ok := ret.Get(0).(func(string, string, string, bool) *model.ThreadResponse); ok {
|
||||||
|
r0 = rf(userId, teamId, threadId, extended)
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).(*model.ThreadResponse)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var r1 error
|
||||||
|
if rf, ok := ret.Get(1).(func(string, string, string, bool) error); ok {
|
||||||
|
r1 = rf(userId, teamId, threadId, extended)
|
||||||
|
} else {
|
||||||
|
r1 = ret.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
// GetThreadsForUser provides a mock function with given fields: userId, teamId, opts
|
// GetThreadsForUser provides a mock function with given fields: userId, teamId, opts
|
||||||
func (_m *ThreadStore) GetThreadsForUser(userId string, teamId 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, teamId, opts)
|
ret := _m.Called(userId, teamId, opts)
|
||||||
|
|||||||
@@ -7064,6 +7064,22 @@ func (s *TimerLayerThreadStore) GetPosts(threadId string, since int64) ([]*model
|
|||||||
return result, err
|
return result, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *TimerLayerThreadStore) GetThreadForUser(userId string, teamId string, threadId string, extended bool) (*model.ThreadResponse, error) {
|
||||||
|
start := timemodule.Now()
|
||||||
|
|
||||||
|
result, err := s.ThreadStore.GetThreadForUser(userId, teamId, threadId, extended)
|
||||||
|
|
||||||
|
elapsed := float64(timemodule.Since(start)) / float64(timemodule.Second)
|
||||||
|
if s.Root.Metrics != nil {
|
||||||
|
success := "false"
|
||||||
|
if err == nil {
|
||||||
|
success = "true"
|
||||||
|
}
|
||||||
|
s.Root.Metrics.ObserveStoreMethodDuration("ThreadStore.GetThreadForUser", success, elapsed)
|
||||||
|
}
|
||||||
|
return result, err
|
||||||
|
}
|
||||||
|
|
||||||
func (s *TimerLayerThreadStore) GetThreadsForUser(userId string, teamId 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()
|
||||||
|
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user