mirror of
https://github.com/mattermost/mattermost.git
synced 2025-02-25 18:55:24 -06:00
Added the SearchPostsInTeam method to the plugin API (#10106)
This commit is contained in:
committed by
Hanzei
parent
87e36a3ecf
commit
c08fda1337
@@ -394,7 +394,7 @@ func searchPosts(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
startTime := time.Now()
|
||||
|
||||
results, err := c.App.SearchPostsInTeam(terms, c.App.Session.UserId, c.Params.TeamId, isOrSearch, includeDeletedChannels, int(timeZoneOffset), page, perPage)
|
||||
results, err := c.App.SearchPostsInTeamForUser(terms, c.App.Session.UserId, c.Params.TeamId, isOrSearch, includeDeletedChannels, int(timeZoneOffset), page, perPage)
|
||||
|
||||
elapsedTime := float64(time.Since(startTime)) / float64(time.Second)
|
||||
metrics := c.App.Metrics
|
||||
|
||||
@@ -342,6 +342,14 @@ func (api *PluginAPI) SearchUsers(search *model.UserSearch) ([]*model.User, *mod
|
||||
return api.app.SearchUsers(search, pluginSearchUsersOptions)
|
||||
}
|
||||
|
||||
func (api *PluginAPI) SearchPostsInTeam(teamId string, paramsList []*model.SearchParams) ([]*model.Post, *model.AppError) {
|
||||
postList, err := api.app.SearchPostsInTeam(teamId, paramsList)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return postList.ToSlice(), nil
|
||||
}
|
||||
|
||||
func (api *PluginAPI) AddChannelMember(channelId, userId string) (*model.ChannelMember, *model.AppError) {
|
||||
// For now, don't allow overriding these via the plugin API.
|
||||
userRequestorId := ""
|
||||
|
||||
@@ -693,6 +693,52 @@ func TestPluginAPISearchChannels(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestPluginAPISearchPostsInTeam(t *testing.T) {
|
||||
th := Setup().InitBasic()
|
||||
defer th.TearDown()
|
||||
api := th.SetupPluginAPI()
|
||||
|
||||
testCases := []struct {
|
||||
description string
|
||||
teamId string
|
||||
params []*model.SearchParams
|
||||
expectedPostsLen int
|
||||
}{
|
||||
{
|
||||
"nil params",
|
||||
th.BasicTeam.Id,
|
||||
nil,
|
||||
0,
|
||||
},
|
||||
{
|
||||
"empty params",
|
||||
th.BasicTeam.Id,
|
||||
[]*model.SearchParams{},
|
||||
0,
|
||||
},
|
||||
{
|
||||
"doesn't match any posts",
|
||||
th.BasicTeam.Id,
|
||||
model.ParseSearchParams("bad message", 0),
|
||||
0,
|
||||
},
|
||||
{
|
||||
"matched posts",
|
||||
th.BasicTeam.Id,
|
||||
model.ParseSearchParams(th.BasicPost.Message, 0),
|
||||
1,
|
||||
},
|
||||
}
|
||||
|
||||
for _, testCase := range testCases {
|
||||
t.Run(testCase.description, func(t *testing.T) {
|
||||
posts, err := api.SearchPostsInTeam(testCase.teamId, testCase.params)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, testCase.expectedPostsLen, len(posts))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestPluginAPIGetChannelsForTeamForUser(t *testing.T) {
|
||||
th := Setup().InitBasic()
|
||||
defer th.TearDown()
|
||||
|
||||
77
app/post.go
77
app/post.go
@@ -743,7 +743,42 @@ func (a *App) parseAndFetchChannelIdByNameFromInFilter(channelName, userId, team
|
||||
return channel, nil
|
||||
}
|
||||
|
||||
func (a *App) SearchPostsInTeam(terms string, userId string, teamId string, isOrSearch bool, includeDeletedChannels bool, timeZoneOffset int, page, perPage int) (*model.PostSearchResults, *model.AppError) {
|
||||
func (a *App) searchPostsInTeam(teamId string, userId string, paramsList []*model.SearchParams, modifierFun func(*model.SearchParams)) (*model.PostList, *model.AppError) {
|
||||
channels := []store.StoreChannel{}
|
||||
|
||||
for _, params := range paramsList {
|
||||
// Don't allow users to search for everything.
|
||||
if params.Terms == "*" {
|
||||
continue
|
||||
}
|
||||
modifierFun(params)
|
||||
channels = append(channels, a.Srv.Store.Post().Search(teamId, userId, params))
|
||||
}
|
||||
|
||||
posts := model.NewPostList()
|
||||
for _, channel := range channels {
|
||||
result := <-channel
|
||||
if result.Err != nil {
|
||||
return nil, result.Err
|
||||
}
|
||||
data := result.Data.(*model.PostList)
|
||||
posts.Extend(data)
|
||||
}
|
||||
|
||||
posts.SortByCreateAt()
|
||||
return posts, nil
|
||||
}
|
||||
|
||||
func (a *App) SearchPostsInTeam(teamId string, paramsList []*model.SearchParams) (*model.PostList, *model.AppError) {
|
||||
if !*a.Config().ServiceSettings.EnablePostSearch {
|
||||
return nil, model.NewAppError("SearchPostsInTeam", "store.sql_post.search.disabled", nil, fmt.Sprintf("teamId=%v", teamId), http.StatusNotImplemented)
|
||||
}
|
||||
return a.searchPostsInTeam(teamId, "", paramsList, func(params *model.SearchParams) {
|
||||
params.SearchWithoutUserId = true
|
||||
})
|
||||
}
|
||||
|
||||
func (a *App) SearchPostsInTeamForUser(terms string, userId string, teamId string, isOrSearch bool, includeDeletedChannels bool, timeZoneOffset int, page, perPage int) (*model.PostSearchResults, *model.AppError) {
|
||||
paramsList := model.ParseSearchParams(terms, timeZoneOffset)
|
||||
includeDeleted := includeDeletedChannels && *a.Config().TeamSettings.ExperimentalViewArchivedChannels
|
||||
|
||||
@@ -815,7 +850,7 @@ func (a *App) SearchPostsInTeam(terms string, userId string, teamId string, isOr
|
||||
}
|
||||
|
||||
if !*a.Config().ServiceSettings.EnablePostSearch {
|
||||
return nil, model.NewAppError("SearchPostsInTeam", "store.sql_post.search.disabled", nil, fmt.Sprintf("teamId=%v userId=%v", teamId, userId), http.StatusNotImplemented)
|
||||
return nil, model.NewAppError("SearchPostsInTeamForUser", "store.sql_post.search.disabled", nil, fmt.Sprintf("teamId=%v userId=%v", teamId, userId), http.StatusNotImplemented)
|
||||
}
|
||||
|
||||
// Since we don't support paging we just return nothing for later pages
|
||||
@@ -823,39 +858,23 @@ func (a *App) SearchPostsInTeam(terms string, userId string, teamId string, isOr
|
||||
return model.MakePostSearchResults(model.NewPostList(), nil), nil
|
||||
}
|
||||
|
||||
channels := []store.StoreChannel{}
|
||||
|
||||
for _, params := range paramsList {
|
||||
posts, err := a.searchPostsInTeam(teamId, userId, paramsList, func(params *model.SearchParams) {
|
||||
params.IncludeDeletedChannels = includeDeleted
|
||||
params.OrTerms = isOrSearch
|
||||
// don't allow users to search for everything
|
||||
if params.Terms != "*" {
|
||||
for idx, channelName := range params.InChannels {
|
||||
if strings.HasPrefix(channelName, "@") {
|
||||
channel, err := a.parseAndFetchChannelIdByNameFromInFilter(channelName, userId, teamId, includeDeletedChannels)
|
||||
if err != nil {
|
||||
mlog.Error(fmt.Sprint(err))
|
||||
continue
|
||||
}
|
||||
params.InChannels[idx] = channel.Name
|
||||
for idx, channelName := range params.InChannels {
|
||||
if strings.HasPrefix(channelName, "@") {
|
||||
channel, err := a.parseAndFetchChannelIdByNameFromInFilter(channelName, userId, teamId, includeDeletedChannels)
|
||||
if err != nil {
|
||||
mlog.Error(fmt.Sprint(err))
|
||||
continue
|
||||
}
|
||||
params.InChannels[idx] = channel.Name
|
||||
}
|
||||
channels = append(channels, a.Srv.Store.Post().Search(teamId, userId, params))
|
||||
}
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
posts := model.NewPostList()
|
||||
for _, channel := range channels {
|
||||
result := <-channel
|
||||
if result.Err != nil {
|
||||
return nil, result.Err
|
||||
}
|
||||
data := result.Data.(*model.PostList)
|
||||
posts.Extend(data)
|
||||
}
|
||||
|
||||
posts.SortByCreateAt()
|
||||
|
||||
return model.MakePostSearchResults(posts, nil), nil
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,14 @@ func NewPostList() *PostList {
|
||||
}
|
||||
}
|
||||
|
||||
func (o *PostList) ToSlice() []*Post {
|
||||
var posts []*Post
|
||||
for _, id := range o.Order {
|
||||
posts = append(posts, o.Posts[id])
|
||||
}
|
||||
return posts
|
||||
}
|
||||
|
||||
func (o *PostList) WithRewrittenImageURLs(f func(string) string) *PostList {
|
||||
copy := *o
|
||||
copy.Posts = make(map[string]*Post)
|
||||
|
||||
@@ -90,3 +90,21 @@ func TestPostListSortByCreateAt(t *testing.T) {
|
||||
assert.EqualValues(t, pl.Order[1], p1.Id)
|
||||
assert.EqualValues(t, pl.Order[2], p2.Id)
|
||||
}
|
||||
|
||||
func TestPostListToSlice(t *testing.T) {
|
||||
pl := PostList{}
|
||||
p1 := &Post{Id: NewId(), Message: NewId(), CreateAt: 2}
|
||||
pl.AddPost(p1)
|
||||
p2 := &Post{Id: NewId(), Message: NewId(), CreateAt: 1}
|
||||
pl.AddPost(p2)
|
||||
p3 := &Post{Id: NewId(), Message: NewId(), CreateAt: 3}
|
||||
pl.AddPost(p3)
|
||||
|
||||
pl.AddOrder(p1.Id)
|
||||
pl.AddOrder(p2.Id)
|
||||
pl.AddOrder(p3.Id)
|
||||
|
||||
want := []*Post{p1, p2, p3}
|
||||
|
||||
assert.Equal(t, want, pl.ToSlice())
|
||||
}
|
||||
|
||||
@@ -23,6 +23,8 @@ type SearchParams struct {
|
||||
OrTerms bool
|
||||
IncludeDeletedChannels bool
|
||||
TimeZoneOffset int
|
||||
// True if this search doesn't originate from a "current user".
|
||||
SearchWithoutUserId bool
|
||||
}
|
||||
|
||||
// Returns the epoch timestamp of the start of the day specified by SearchParams.AfterDate
|
||||
|
||||
@@ -226,6 +226,11 @@ type API interface {
|
||||
// Minimum server version: 5.6
|
||||
SearchUsers(search *model.UserSearch) ([]*model.User, *model.AppError)
|
||||
|
||||
// SearchPostsInTeam returns a list of posts in a specific team that match the given params.
|
||||
//
|
||||
// Minimum server version: 5.10
|
||||
SearchPostsInTeam(teamId string, paramsList []*model.SearchParams) ([]*model.Post, *model.AppError)
|
||||
|
||||
// AddChannelMember creates a channel membership for a user.
|
||||
AddChannelMember(channelId, userId string) (*model.ChannelMember, *model.AppError)
|
||||
|
||||
|
||||
@@ -2053,6 +2053,36 @@ func (s *apiRPCServer) SearchUsers(args *Z_SearchUsersArgs, returns *Z_SearchUse
|
||||
return nil
|
||||
}
|
||||
|
||||
type Z_SearchPostsInTeamArgs struct {
|
||||
A string
|
||||
B []*model.SearchParams
|
||||
}
|
||||
|
||||
type Z_SearchPostsInTeamReturns struct {
|
||||
A []*model.Post
|
||||
B *model.AppError
|
||||
}
|
||||
|
||||
func (g *apiRPCClient) SearchPostsInTeam(teamId string, paramsList []*model.SearchParams) ([]*model.Post, *model.AppError) {
|
||||
_args := &Z_SearchPostsInTeamArgs{teamId, paramsList}
|
||||
_returns := &Z_SearchPostsInTeamReturns{}
|
||||
if err := g.client.Call("Plugin.SearchPostsInTeam", _args, _returns); err != nil {
|
||||
log.Printf("RPC call to SearchPostsInTeam API failed: %s", err.Error())
|
||||
}
|
||||
return _returns.A, _returns.B
|
||||
}
|
||||
|
||||
func (s *apiRPCServer) SearchPostsInTeam(args *Z_SearchPostsInTeamArgs, returns *Z_SearchPostsInTeamReturns) error {
|
||||
if hook, ok := s.impl.(interface {
|
||||
SearchPostsInTeam(teamId string, paramsList []*model.SearchParams) ([]*model.Post, *model.AppError)
|
||||
}); ok {
|
||||
returns.A, returns.B = hook.SearchPostsInTeam(args.A, args.B)
|
||||
} else {
|
||||
return encodableError(fmt.Errorf("API SearchPostsInTeam called but not implemented."))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type Z_AddChannelMemberArgs struct {
|
||||
A string
|
||||
B string
|
||||
|
||||
@@ -1983,6 +1983,31 @@ func (_m *API) SearchChannels(teamId string, term string) ([]*model.Channel, *mo
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// SearchPostsInTeam provides a mock function with given fields: teamId, paramsList
|
||||
func (_m *API) SearchPostsInTeam(teamId string, paramsList []*model.SearchParams) ([]*model.Post, *model.AppError) {
|
||||
ret := _m.Called(teamId, paramsList)
|
||||
|
||||
var r0 []*model.Post
|
||||
if rf, ok := ret.Get(0).(func(string, []*model.SearchParams) []*model.Post); ok {
|
||||
r0 = rf(teamId, paramsList)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).([]*model.Post)
|
||||
}
|
||||
}
|
||||
|
||||
var r1 *model.AppError
|
||||
if rf, ok := ret.Get(1).(func(string, []*model.SearchParams) *model.AppError); ok {
|
||||
r1 = rf(teamId, paramsList)
|
||||
} else {
|
||||
if ret.Get(1) != nil {
|
||||
r1 = ret.Get(1).(*model.AppError)
|
||||
}
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// SearchTeams provides a mock function with given fields: term
|
||||
func (_m *API) SearchTeams(term string) ([]*model.Team, *model.AppError) {
|
||||
ret := _m.Called(term)
|
||||
|
||||
@@ -808,6 +808,11 @@ func (s *SqlPostStore) Search(teamId string, userId string, params *model.Search
|
||||
deletedQueryPart = ""
|
||||
}
|
||||
|
||||
userIdPart := "AND UserId = :UserId"
|
||||
if params.SearchWithoutUserId {
|
||||
userIdPart = ""
|
||||
}
|
||||
|
||||
searchQuery := `
|
||||
SELECT
|
||||
*
|
||||
@@ -826,7 +831,7 @@ func (s *SqlPostStore) Search(teamId string, userId string, params *model.Search
|
||||
WHERE
|
||||
Id = ChannelId
|
||||
AND (TeamId = :TeamId OR TeamId = '')
|
||||
AND UserId = :UserId
|
||||
` + userIdPart + `
|
||||
` + deletedQueryPart + `
|
||||
CHANNEL_FILTER)
|
||||
CREATEDATE_CLAUSE
|
||||
|
||||
Reference in New Issue
Block a user