mirror of
https://github.com/mattermost/mattermost.git
synced 2026-08-26 21:27:40 -05:00
* Added base fr report generation * WIP * implemented UI flow * implemented UI flow * restructured the modal code into sub components * Refactoring and cleanup * lint fixes, added new tests * i18n fix * test fix * Updated test * CI * Several improvements * WIP * Added tests * Addressed some security enhancements * Created zip writer entery later * Improved a test to check for file content * Improved error handling * Made a geneeric function * Updated classes * accepting comment in report API * Added more tests * Integrated new API param * Removed an unnecessary check * Made a geneeric function * Made a geneeric function * Made the comment body not required and updated API docs * Updated report generation API call in download report button * Included decision in report and removed confirmation when keeping message * Updated test * Add explicit wait for removeWithoutReportButton visibility in test Prevent race condition by waiting for the button to be visible after UI transitions to skip-confirm step before clicking it. Co-authored-by: Maria A Nunez <maria.nunez@mattermost.com> * PR Feedback * explicitelly added return statement * Included actor details in report * Updated tests --------- Co-authored-by: maria.nunez <maria.nunez@mattermost.com> Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: Mattermost Build <build@mattermost.com>
104 lines
3.0 KiB
Go
104 lines
3.0 KiB
Go
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
|
// See LICENSE.txt for license information.
|
|
|
|
package api4
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
"net/http"
|
|
"os"
|
|
|
|
"github.com/mattermost/mattermost/server/v8/channels/app"
|
|
|
|
"github.com/mattermost/mattermost/server/public/model"
|
|
"github.com/mattermost/mattermost/server/public/shared/mlog"
|
|
)
|
|
|
|
func generateFlaggedPostReport(c *Context, w http.ResponseWriter, r *http.Request) {
|
|
if c.Err != nil {
|
|
return
|
|
}
|
|
|
|
c.RequirePostId()
|
|
if c.Err != nil {
|
|
return
|
|
}
|
|
|
|
var actionRequest model.FlagContentActionRequest
|
|
if err := json.NewDecoder(r.Body).Decode(&actionRequest); err != nil && !errors.Is(err, io.EOF) {
|
|
c.SetInvalidParamWithErr("flagContentActionRequestBody", err)
|
|
return
|
|
}
|
|
|
|
postId := c.Params.PostId
|
|
userId := c.AppContext.Session().UserId
|
|
|
|
auditRec := c.MakeAuditRecord(model.AuditEventGenerateFlaggedPostReport, model.AuditStatusFail)
|
|
defer c.LogAuditRecWithLevel(auditRec, app.LevelContent)
|
|
model.AddEventParameterToAuditRec(auditRec, "flaggedPostId", postId)
|
|
model.AddEventParameterToAuditRec(auditRec, "userId", userId)
|
|
model.AddEventParameterToAuditRec(auditRec, "comment", actionRequest.Comment)
|
|
model.AddEventParameterToAuditRec(auditRec, "action", actionRequest.Action)
|
|
|
|
post, appErr := c.App.GetSinglePost(c.AppContext, postId, true)
|
|
if appErr != nil {
|
|
c.Err = appErr
|
|
return
|
|
}
|
|
|
|
channel, appErr := c.App.GetChannel(c.AppContext, post.ChannelId)
|
|
if appErr != nil {
|
|
c.Err = appErr
|
|
return
|
|
}
|
|
|
|
requireTeamContentReviewer(c, userId, channel.TeamId)
|
|
if c.Err != nil {
|
|
return
|
|
}
|
|
|
|
// This validates that the post is flagged
|
|
requireFlaggedPost(c, postId)
|
|
if c.Err != nil {
|
|
return
|
|
}
|
|
|
|
reportPath, appErr := c.App.GenerateFlaggedPostReport(c.AppContext, postId, userId, actionRequest.Comment, actionRequest.Action)
|
|
if appErr != nil {
|
|
c.Err = appErr
|
|
return
|
|
}
|
|
defer func() {
|
|
if err := os.Remove(reportPath); err != nil && !os.IsNotExist(err) {
|
|
c.Logger.Warn("Failed to remove flagged post report temp file", mlog.String("path", reportPath), mlog.Err(err))
|
|
}
|
|
}()
|
|
|
|
f, err := os.Open(reportPath)
|
|
if err != nil {
|
|
c.Err = model.NewAppError("generateFlaggedPostReport", "api.data_spillage.report.open.app_error", nil, "", http.StatusInternalServerError).Wrap(err)
|
|
return
|
|
}
|
|
defer f.Close()
|
|
|
|
stat, err := f.Stat()
|
|
if err != nil {
|
|
c.Err = model.NewAppError("generateFlaggedPostReport", "api.data_spillage.report.stat.app_error", nil, "", http.StatusInternalServerError).Wrap(err)
|
|
return
|
|
}
|
|
|
|
// Notify all team reviewers that a report has been generated. Best-effort:
|
|
// must run before http.ServeContent (which writes the response and may block).
|
|
c.App.NotifyReviewersOfFlaggedPostReportGeneration(c.AppContext, postId, userId)
|
|
|
|
filename := fmt.Sprintf("flagged-post-%s-%d.zip", postId, model.GetMillis())
|
|
w.Header().Set("Content-Type", "application/zip")
|
|
w.Header().Set("Content-Disposition", fmt.Sprintf(`attachment; filename="%s"`, filename))
|
|
http.ServeContent(w, r, filename, stat.ModTime(), f)
|
|
|
|
auditRec.Success()
|
|
}
|