From 565c8aa42d4d646d009bf16e03038e755372a94c Mon Sep 17 00:00:00 2001 From: Doug Lauder Date: Tue, 28 Jan 2025 22:21:05 -0500 Subject: [PATCH] Audit usage of the searchPosts API (#29909) * Audit calls to searchPosts API * Update server/public/model/post_search_results.go Co-authored-by: Ben Schumacher * Update server/public/model/post_search_results.go * Update server/public/model/post_search_results.go --------- Co-authored-by: Ben Schumacher Co-authored-by: Mattermost Build --- server/channels/api4/post.go | 6 ++++++ server/public/model/post.go | 15 +++++++++++++++ server/public/model/post_search_results.go | 15 +++++++++++++++ 3 files changed, 36 insertions(+) diff --git a/server/channels/api4/post.go b/server/channels/api4/post.go index 455760a5ee..4e0a5c69cb 100644 --- a/server/channels/api4/post.go +++ b/server/channels/api4/post.go @@ -790,6 +790,10 @@ func searchPosts(c *Context, w http.ResponseWriter, r *http.Request, teamId stri includeDeletedChannels = *params.IncludeDeletedChannels } + auditRec := c.MakeAuditRecord("searchPosts", audit.Fail) + defer c.LogAuditRecWithLevel(auditRec, app.LevelAPI) + audit.AddEventParameterAuditable(auditRec, "search_params", params) + startTime := time.Now() results, err := c.App.SearchPostsForUser(c.AppContext, terms, c.AppContext.Session().UserId, teamId, isOrSearch, includeDeletedChannels, timeZoneOffset, page, perPage) @@ -814,6 +818,8 @@ func searchPosts(c *Context, w http.ResponseWriter, r *http.Request, teamId stri } results = model.MakePostSearchResults(clientPostList, results.Matches) + audit.AddEventParameterAuditable(auditRec, "search_results", results) + auditRec.Success() w.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate") if err := results.EncodeJSON(w); err != nil { diff --git a/server/public/model/post.go b/server/public/model/post.go index 9f2f740f88..b7a544e140 100644 --- a/server/public/model/post.go +++ b/server/public/model/post.go @@ -207,6 +207,21 @@ type SearchParameter struct { IncludeDeletedChannels *bool `json:"include_deleted_channels"` } +func (sp SearchParameter) Auditable() map[string]interface{} { + return map[string]interface{}{ + "terms": sp.Terms, + "is_or_search": sp.IsOrSearch, + "time_zone_offset": sp.TimeZoneOffset, + "page": sp.Page, + "per_page": sp.PerPage, + "include_deleted_channels": sp.IncludeDeletedChannels, + } +} + +func (sp SearchParameter) LogClone() any { + return sp.Auditable() +} + type AnalyticsPostCountsOptions struct { TeamId string BotsOnly bool diff --git a/server/public/model/post_search_results.go b/server/public/model/post_search_results.go index 3de3e817b7..782e7db76b 100644 --- a/server/public/model/post_search_results.go +++ b/server/public/model/post_search_results.go @@ -39,3 +39,18 @@ func (o *PostSearchResults) ForPlugin() *PostSearchResults { plCopy.PostList = plCopy.PostList.ForPlugin() return &plCopy } + +func (o *PostSearchResults) Auditable() map[string]interface{} { + var numResults int + var hasNext bool + + if o.PostList != nil { + numResults = len(o.PostList.Posts) + hasNext = SafeDereference(o.PostList.HasNext) + } + + return map[string]any{ + "num_results": numResults, + "has_next": hasNext, + } +}