mirror of
https://github.com/mattermost/mattermost.git
synced 2026-04-13 04:57:45 -04:00
* ci: enable fullyparallel mode for server tests Replace os.Setenv, os.Chdir, and global state mutations with parallel-safe alternatives (t.Setenv, t.Chdir, test hooks) across 37 files. Refactor GetLogRootPath and MM_INSTALL_TYPE to use package-level test hooks instead of environment variables. This enables gotestsum --fullparallel, allowing all test packages to run with maximum parallelism within each shard. Co-authored-by: Claude <claude@anthropic.com> * ci: split fullyparallel from continue-on-error in workflow template - Add new boolean input 'allow-failure' separate from 'fullyparallel' - Change continue-on-error to use allow-failure instead of fullyparallel - Update server-ci.yml to pass allow-failure: true for test coverage job - Allows independent control of parallel execution and failure tolerance Co-authored-by: Claude <claude@anthropic.com> * fix: protect TestOverrideLogRootPath with sync.Mutex for parallel tests - Replace global var TestOverrideLogRootPath with mutex-protected functions - Add SetTestOverrideLogRootPath() and getTestOverrideLogRootPath() functions - Update GetLogRootPath() to use thread-safe getter - Update all test files to use SetTestOverrideLogRootPath() with t.Cleanup() - Fixes race condition when running tests with t.Parallel() Co-authored-by: Claude <claude@anthropic.com> * fix: configure audit settings before server setup in tests - Move ExperimentalAuditSettings from UpdateConfig() to config defaults - Pass audit config via app.Config() option in SetupWithServerOptions() - Fixes audit test setup ordering to configure BEFORE server initialization - Resolves CodeRabbit's audit config timing issue in api4 tests Co-authored-by: Claude <claude@anthropic.com> * fix: implement SetTestOverrideLogRootPath mutex in logger.go The previous commit updated test callers to use SetTestOverrideLogRootPath() but didn't actually create the function in config/logger.go, causing build failures across all CI shards. This commit: - Replaces the exported var TestOverrideLogRootPath with mutex-protected unexported state (testOverrideLogRootPath + testOverrideLogRootMu) - Adds exported SetTestOverrideLogRootPath() setter - Adds unexported getTestOverrideLogRootPath() getter - Updates GetLogRootPath() to use the thread-safe getter - Fixes log_test.go callers that were missed in the previous commit Co-authored-by: Claude <claude@anthropic.com> * fix(test): use SetupConfig for access_control feature flag registration InitAccessControlPolicy() checks FeatureFlags.AttributeBasedAccessControl at route registration time during server startup. Setting the flag via UpdateConfig after Setup() is too late — routes are never registered and API calls return 404. Use SetupConfig() to pass the feature flag in the initial config before server startup, ensuring routes are properly registered. Co-authored-by: Claude <claude@anthropic.com> * fix(test): restore BurnOnRead flag state in TestRevealPost subtest The 'feature not enabled' subtest disables BurnOnRead without restoring it via t.Cleanup. Subsequent subtests inherit the disabled state, which can cause 501 errors when they expect the feature to be available. Add t.Cleanup to restore FeatureFlags.BurnOnRead = true after the subtest completes. Co-authored-by: Claude <claude@anthropic.com> * fix(test): restore EnableSharedChannelsMemberSync flag via t.Cleanup The test disables EnableSharedChannelsMemberSync without restoring it. If the subtest exits early (e.g., require failure), later sibling subtests inherit a disabled flag and become flaky. Add t.Cleanup to restore the flag after the subtest completes. Co-authored-by: Claude <claude@anthropic.com> * Fix test parallelism: use instance-scoped overrides and init-time audit config Replace package-level test globals (TestOverrideInstallType, SetTestOverrideLogRootPath) with fields on PlatformService so each test gets its own instance without process-wide mutation. Fix three audit tests (TestUserLoginAudit, TestLogoutAuditAuthStatus, TestUpdatePasswordAudit) that configured the audit logger after server init — the audit logger only reads config at startup, so pass audit settings via app.Config() at init time instead. Also revert the Go 1.24.13 downgrade and bump mattermost-govet to v2.0.2 for Go 1.25.8 compatibility. * Fix audit unit tests * Fix MMCLOUDURL unit tests * Fixed unit tests using MM_NOTIFY_ADMIN_COOL_OFF_DAYS * Make app migrations idempotent for parallel test safety Change System().Save() to System().SaveOrUpdate() in all migration completion markers. When two parallel tests share a database pool entry, both may race through the check-then-insert migration pattern. Save() causes a duplicate key fatal crash; SaveOrUpdate() makes the second write a harmless no-op. * test: address review feedback on fullyparallel PR - Use SetLogRootPathOverride() setter instead of direct field access in platform/support_packet_test.go and platform/log_test.go (pvev) - Restore TestGetLogRootPath in config/logger_test.go to keep MM_LOG_PATH env var coverage; test uses t.Setenv so it runs serially which is fine (pvev) - Fix misleading comment in config_test.go: code uses t.Setenv, not os.Setenv (jgheithcock) Co-authored-by: Claude <claude@anthropic.com> * fix: add missing os import in post_test.go The os import was dropped during a merge conflict resolution while burn-on-read shared channel tests from master still use os.Setenv. Co-authored-by: Claude <claude@anthropic.com> --------- Co-authored-by: Claude <claude@anthropic.com> Co-authored-by: wiggin77 <wiggin77@warpmail.net> Co-authored-by: Mattermost Build <build@mattermost.com>
1245 lines
43 KiB
Go
1245 lines
43 KiB
Go
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
|
// See LICENSE.txt for license information.
|
|
|
|
package api4
|
|
|
|
import (
|
|
"context"
|
|
"net/http"
|
|
"testing"
|
|
|
|
"github.com/mattermost/mattermost/server/public/model"
|
|
"github.com/mattermost/mattermost/server/v8/channels/utils/testutils"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func setBasicCommonReviewerConfig(th *TestHelper) *model.AppError {
|
|
config := model.ContentFlaggingSettingsRequest{
|
|
ContentFlaggingSettingsBase: model.ContentFlaggingSettingsBase{
|
|
EnableContentFlagging: model.NewPointer(true),
|
|
},
|
|
ReviewerSettings: &model.ReviewSettingsRequest{
|
|
ReviewerSettings: model.ReviewerSettings{
|
|
CommonReviewers: model.NewPointer(true),
|
|
},
|
|
ReviewerIDsSettings: model.ReviewerIDsSettings{
|
|
CommonReviewerIds: []string{th.BasicUser.Id},
|
|
},
|
|
},
|
|
}
|
|
config.SetDefaults()
|
|
return th.App.SaveContentFlaggingConfig(config)
|
|
}
|
|
|
|
func setNonReviewerConfig(th *TestHelper) *model.AppError {
|
|
config := model.ContentFlaggingSettingsRequest{
|
|
ContentFlaggingSettingsBase: model.ContentFlaggingSettingsBase{
|
|
EnableContentFlagging: model.NewPointer(true),
|
|
},
|
|
ReviewerSettings: &model.ReviewSettingsRequest{
|
|
ReviewerSettings: model.ReviewerSettings{
|
|
CommonReviewers: model.NewPointer(false),
|
|
},
|
|
ReviewerIDsSettings: model.ReviewerIDsSettings{
|
|
TeamReviewersSetting: map[string]*model.TeamReviewerSetting{
|
|
th.BasicTeam.Id: {
|
|
Enabled: model.NewPointer(true),
|
|
ReviewerIds: []string{},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
config.SetDefaults()
|
|
return th.App.SaveContentFlaggingConfig(config)
|
|
}
|
|
|
|
func setBasicTeamReviewerConfig(th *TestHelper, extraReviewerIds ...string) *model.AppError {
|
|
ids := []string{th.BasicUser.Id}
|
|
ids = append(ids, extraReviewerIds...)
|
|
config := model.ContentFlaggingSettingsRequest{
|
|
ContentFlaggingSettingsBase: model.ContentFlaggingSettingsBase{
|
|
EnableContentFlagging: model.NewPointer(true),
|
|
},
|
|
ReviewerSettings: &model.ReviewSettingsRequest{
|
|
ReviewerSettings: model.ReviewerSettings{
|
|
CommonReviewers: model.NewPointer(false),
|
|
},
|
|
ReviewerIDsSettings: model.ReviewerIDsSettings{
|
|
TeamReviewersSetting: map[string]*model.TeamReviewerSetting{
|
|
th.BasicTeam.Id: {
|
|
Enabled: model.NewPointer(true),
|
|
ReviewerIds: ids,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
config.SetDefaults()
|
|
return th.App.SaveContentFlaggingConfig(config)
|
|
}
|
|
|
|
func setCommonReviewerWithRequiredCommentConfig(th *TestHelper) *model.AppError {
|
|
config := model.ContentFlaggingSettingsRequest{
|
|
ContentFlaggingSettingsBase: model.ContentFlaggingSettingsBase{
|
|
EnableContentFlagging: model.NewPointer(true),
|
|
AdditionalSettings: &model.AdditionalContentFlaggingSettings{
|
|
ReviewerCommentRequired: model.NewPointer(true),
|
|
},
|
|
},
|
|
ReviewerSettings: &model.ReviewSettingsRequest{
|
|
ReviewerSettings: model.ReviewerSettings{
|
|
CommonReviewers: model.NewPointer(true),
|
|
},
|
|
ReviewerIDsSettings: model.ReviewerIDsSettings{
|
|
CommonReviewerIds: []string{th.BasicUser.Id},
|
|
},
|
|
},
|
|
}
|
|
config.SetDefaults()
|
|
return th.App.SaveContentFlaggingConfig(config)
|
|
}
|
|
|
|
func flagPostViaAPI(t *testing.T, client *model.Client4, postId string) {
|
|
t.Helper()
|
|
flagRequest := &model.FlagContentRequest{
|
|
Reason: "Classification mismatch",
|
|
Comment: "This is sensitive content",
|
|
}
|
|
resp, err := client.FlagPostForContentReview(context.Background(), postId, flagRequest)
|
|
require.NoError(t, err)
|
|
require.Equal(t, http.StatusOK, resp.StatusCode)
|
|
}
|
|
|
|
func uploadFileAndCreatePost(t *testing.T, th *TestHelper, client *model.Client4) (*model.Post, *model.FileInfo) {
|
|
t.Helper()
|
|
data, err := testutils.ReadTestFile("test.png")
|
|
require.NoError(t, err)
|
|
|
|
fileResponse, _, err := client.UploadFile(context.Background(), data, th.BasicChannel.Id, "test.png")
|
|
require.NoError(t, err)
|
|
require.Equal(t, 1, len(fileResponse.FileInfos))
|
|
fileInfo := fileResponse.FileInfos[0]
|
|
|
|
post := th.CreatePostInChannelWithFiles(t, th.BasicChannel, fileInfo)
|
|
return post, fileInfo
|
|
}
|
|
|
|
func TestRequireContentFlaggingEnabled(t *testing.T) {
|
|
th := Setup(t).InitBasic(t)
|
|
|
|
t.Run("Should set error when license is not valid", func(t *testing.T) {
|
|
th.RemoveLicense(t)
|
|
c := &Context{
|
|
App: th.App,
|
|
Logger: th.App.Log(),
|
|
}
|
|
|
|
requireContentFlaggingEnabled(c)
|
|
require.NotNil(t, c.Err)
|
|
require.Equal(t, "api.data_spillage.error.license", c.Err.Id)
|
|
require.Equal(t, http.StatusNotImplemented, c.Err.StatusCode)
|
|
})
|
|
|
|
t.Run("Should set error when feature is disabled in config", func(t *testing.T) {
|
|
th.App.Srv().SetLicense(model.NewTestLicenseSKU(model.LicenseShortSkuEnterpriseAdvanced))
|
|
defer th.RemoveLicense(t)
|
|
|
|
th.App.UpdateConfig(func(config *model.Config) {
|
|
config.ContentFlaggingSettings.EnableContentFlagging = model.NewPointer(false)
|
|
config.ContentFlaggingSettings.SetDefaults()
|
|
})
|
|
|
|
c := &Context{
|
|
App: th.App,
|
|
Logger: th.App.Log(),
|
|
}
|
|
|
|
requireContentFlaggingEnabled(c)
|
|
require.NotNil(t, c.Err)
|
|
require.Equal(t, "api.data_spillage.error.disabled", c.Err.Id)
|
|
require.Equal(t, http.StatusNotImplemented, c.Err.StatusCode)
|
|
})
|
|
|
|
t.Run("Should not set error when license is valid and feature is enabled", func(t *testing.T) {
|
|
th.App.Srv().SetLicense(model.NewTestLicenseSKU(model.LicenseShortSkuEnterpriseAdvanced))
|
|
defer th.RemoveLicense(t)
|
|
|
|
th.App.UpdateConfig(func(config *model.Config) {
|
|
config.ContentFlaggingSettings.EnableContentFlagging = model.NewPointer(true)
|
|
config.ContentFlaggingSettings.SetDefaults()
|
|
})
|
|
|
|
c := &Context{
|
|
App: th.App,
|
|
Logger: th.App.Log(),
|
|
}
|
|
|
|
requireContentFlaggingEnabled(c)
|
|
require.Nil(t, c.Err)
|
|
})
|
|
}
|
|
|
|
func TestGetFlaggingConfiguration(t *testing.T) {
|
|
th := Setup(t).InitBasic(t)
|
|
|
|
client := th.Client
|
|
|
|
t.Run("Should return 501 when feature is disabled", func(t *testing.T) {
|
|
th.App.Srv().SetLicense(model.NewTestLicenseSKU(model.LicenseShortSkuEnterpriseAdvanced))
|
|
defer th.RemoveLicense(t)
|
|
|
|
th.App.UpdateConfig(func(config *model.Config) {
|
|
config.ContentFlaggingSettings.EnableContentFlagging = model.NewPointer(false)
|
|
config.ContentFlaggingSettings.SetDefaults()
|
|
})
|
|
|
|
status, resp, err := client.GetFlaggingConfiguration(context.Background())
|
|
require.Error(t, err)
|
|
require.Equal(t, http.StatusNotImplemented, resp.StatusCode)
|
|
require.Nil(t, status)
|
|
})
|
|
|
|
t.Run("Should successfully return configuration without team_id for any authenticated user", func(t *testing.T) {
|
|
th.App.Srv().SetLicense(model.NewTestLicenseSKU(model.LicenseShortSkuEnterpriseAdvanced))
|
|
defer th.RemoveLicense(t)
|
|
|
|
th.App.UpdateConfig(func(config *model.Config) {
|
|
config.ContentFlaggingSettings.EnableContentFlagging = model.NewPointer(true)
|
|
config.ContentFlaggingSettings.SetDefaults()
|
|
})
|
|
|
|
config, resp, err := client.GetFlaggingConfiguration(context.Background())
|
|
require.NoError(t, err)
|
|
require.Equal(t, http.StatusOK, resp.StatusCode)
|
|
require.NotNil(t, config)
|
|
require.NotEmpty(t, config.Reasons)
|
|
require.NotNil(t, config.ReporterCommentRequired)
|
|
require.NotNil(t, config.ReviewerCommentRequired)
|
|
// Reviewer-only fields should be nil when not requesting as a reviewer
|
|
require.Nil(t, config.NotifyReporterOnRemoval)
|
|
require.Nil(t, config.NotifyReporterOnDismissal)
|
|
})
|
|
|
|
t.Run("Should return 403 when team_id is provided but user is not a reviewer", func(t *testing.T) {
|
|
th.App.Srv().SetLicense(model.NewTestLicenseSKU(model.LicenseShortSkuEnterpriseAdvanced))
|
|
defer th.RemoveLicense(t)
|
|
|
|
appErr := setNonReviewerConfig(th)
|
|
require.Nil(t, appErr)
|
|
|
|
flagConfig, resp, err := client.GetFlaggingConfigurationForTeam(context.Background(), th.BasicTeam.Id)
|
|
require.Error(t, err)
|
|
require.Equal(t, http.StatusForbidden, resp.StatusCode)
|
|
require.Nil(t, flagConfig)
|
|
})
|
|
|
|
t.Run("Should successfully return configuration with reviewer fields when user is a reviewer", func(t *testing.T) {
|
|
th.App.Srv().SetLicense(model.NewTestLicenseSKU(model.LicenseShortSkuEnterpriseAdvanced))
|
|
defer th.RemoveLicense(t)
|
|
|
|
appErr := setBasicCommonReviewerConfig(th)
|
|
require.Nil(t, appErr)
|
|
|
|
config, resp, err := client.GetFlaggingConfigurationForTeam(context.Background(), th.BasicTeam.Id)
|
|
require.NoError(t, err)
|
|
require.Equal(t, http.StatusOK, resp.StatusCode)
|
|
require.NotNil(t, config)
|
|
require.NotEmpty(t, config.Reasons)
|
|
require.NotNil(t, config.ReporterCommentRequired)
|
|
require.NotNil(t, config.ReviewerCommentRequired)
|
|
// Reviewer-only fields should be present when requesting as a reviewer
|
|
require.NotNil(t, config.NotifyReporterOnRemoval)
|
|
require.NotNil(t, config.NotifyReporterOnDismissal)
|
|
})
|
|
|
|
t.Run("Should successfully return configuration with reviewer fields when user is a team reviewer", func(t *testing.T) {
|
|
th.App.Srv().SetLicense(model.NewTestLicenseSKU(model.LicenseShortSkuEnterpriseAdvanced))
|
|
defer th.RemoveLicense(t)
|
|
|
|
appErr := setBasicTeamReviewerConfig(th)
|
|
require.Nil(t, appErr)
|
|
|
|
flagConfig, resp, err := client.GetFlaggingConfigurationForTeam(context.Background(), th.BasicTeam.Id)
|
|
require.NoError(t, err)
|
|
require.Equal(t, http.StatusOK, resp.StatusCode)
|
|
require.NotNil(t, flagConfig)
|
|
require.NotEmpty(t, flagConfig.Reasons)
|
|
require.NotNil(t, flagConfig.ReporterCommentRequired)
|
|
require.NotNil(t, flagConfig.ReviewerCommentRequired)
|
|
// Reviewer-only fields should be present when requesting as a team reviewer
|
|
require.NotNil(t, flagConfig.NotifyReporterOnRemoval)
|
|
require.NotNil(t, flagConfig.NotifyReporterOnDismissal)
|
|
})
|
|
}
|
|
|
|
func TestSaveContentFlaggingSettings(t *testing.T) {
|
|
th := Setup(t).InitBasic(t)
|
|
|
|
client := th.Client
|
|
|
|
t.Run("Should return 403 when user does not have manage system permission", func(t *testing.T) {
|
|
th.App.Srv().SetLicense(model.NewTestLicenseSKU(model.LicenseShortSkuEnterpriseAdvanced))
|
|
defer th.RemoveLicense(t)
|
|
|
|
config := model.ContentFlaggingSettingsRequest{
|
|
ContentFlaggingSettingsBase: model.ContentFlaggingSettingsBase{
|
|
EnableContentFlagging: model.NewPointer(true),
|
|
},
|
|
ReviewerSettings: &model.ReviewSettingsRequest{
|
|
ReviewerSettings: model.ReviewerSettings{
|
|
CommonReviewers: model.NewPointer(true),
|
|
},
|
|
ReviewerIDsSettings: model.ReviewerIDsSettings{
|
|
CommonReviewerIds: []string{th.BasicUser.Id},
|
|
},
|
|
},
|
|
}
|
|
|
|
// Use basic user who doesn't have manage system permission
|
|
th.LoginBasic(t)
|
|
resp, err := client.SaveContentFlaggingSettings(context.Background(), &config)
|
|
require.Error(t, err)
|
|
require.Equal(t, http.StatusForbidden, resp.StatusCode)
|
|
})
|
|
|
|
t.Run("Should return 400 when config is invalid", func(t *testing.T) {
|
|
th.App.Srv().SetLicense(model.NewTestLicenseSKU(model.LicenseShortSkuEnterpriseAdvanced))
|
|
defer th.RemoveLicense(t)
|
|
|
|
// Invalid config - missing required fields
|
|
config := model.ContentFlaggingSettingsRequest{
|
|
ReviewerSettings: &model.ReviewSettingsRequest{
|
|
ReviewerSettings: model.ReviewerSettings{
|
|
CommonReviewers: model.NewPointer(true),
|
|
TeamAdminsAsReviewers: model.NewPointer(false),
|
|
},
|
|
ReviewerIDsSettings: model.ReviewerIDsSettings{
|
|
CommonReviewerIds: []string{},
|
|
},
|
|
},
|
|
}
|
|
config.SetDefaults()
|
|
|
|
th.LoginSystemAdmin(t)
|
|
resp, err := th.SystemAdminClient.SaveContentFlaggingSettings(context.Background(), &config)
|
|
require.Error(t, err)
|
|
require.Equal(t, http.StatusBadRequest, resp.StatusCode)
|
|
})
|
|
|
|
t.Run("Should successfully save content flagging settings when user has manage system permission", func(t *testing.T) {
|
|
th.App.Srv().SetLicense(model.NewTestLicenseSKU(model.LicenseShortSkuEnterpriseAdvanced))
|
|
defer th.RemoveLicense(t)
|
|
|
|
config := model.ContentFlaggingSettingsRequest{
|
|
ContentFlaggingSettingsBase: model.ContentFlaggingSettingsBase{
|
|
EnableContentFlagging: model.NewPointer(true),
|
|
},
|
|
ReviewerSettings: &model.ReviewSettingsRequest{
|
|
ReviewerSettings: model.ReviewerSettings{
|
|
CommonReviewers: model.NewPointer(true),
|
|
},
|
|
ReviewerIDsSettings: model.ReviewerIDsSettings{
|
|
CommonReviewerIds: []string{th.BasicUser.Id},
|
|
},
|
|
},
|
|
}
|
|
|
|
// Use system admin who has manage system permission
|
|
resp, err := th.SystemAdminClient.SaveContentFlaggingSettings(context.Background(), &config)
|
|
require.NoError(t, err)
|
|
require.Equal(t, http.StatusOK, resp.StatusCode)
|
|
})
|
|
}
|
|
|
|
func TestGetContentFlaggingSettings(t *testing.T) {
|
|
th := Setup(t).InitBasic(t)
|
|
|
|
t.Run("Should return 403 when user does not have manage system permission", func(t *testing.T) {
|
|
th.App.Srv().SetLicense(model.NewTestLicenseSKU(model.LicenseShortSkuEnterpriseAdvanced))
|
|
defer th.RemoveLicense(t)
|
|
|
|
// Use basic user who doesn't have manage system permission
|
|
th.LoginBasic(t)
|
|
settings, resp, err := th.Client.GetContentFlaggingSettings(context.Background())
|
|
require.Error(t, err)
|
|
require.Equal(t, http.StatusForbidden, resp.StatusCode)
|
|
require.Nil(t, settings)
|
|
})
|
|
|
|
t.Run("Should successfully get content flagging settings when user has manage system permission", func(t *testing.T) {
|
|
th.App.Srv().SetLicense(model.NewTestLicenseSKU(model.LicenseShortSkuEnterpriseAdvanced))
|
|
defer th.RemoveLicense(t)
|
|
|
|
// First save some settings
|
|
appErr := setBasicCommonReviewerConfig(th)
|
|
require.Nil(t, appErr)
|
|
|
|
// Use system admin who has manage system permission
|
|
settings, resp, err := th.SystemAdminClient.GetContentFlaggingSettings(context.Background())
|
|
require.NoError(t, err)
|
|
require.Equal(t, http.StatusOK, resp.StatusCode)
|
|
require.NotNil(t, settings)
|
|
require.NotNil(t, settings.EnableContentFlagging)
|
|
require.True(t, *settings.EnableContentFlagging)
|
|
require.NotNil(t, settings.ReviewerSettings)
|
|
require.NotNil(t, settings.ReviewerSettings.CommonReviewers)
|
|
require.True(t, *settings.ReviewerSettings.CommonReviewers)
|
|
require.NotNil(t, settings.ReviewerSettings.CommonReviewerIds)
|
|
require.Contains(t, settings.ReviewerSettings.CommonReviewerIds, th.BasicUser.Id)
|
|
})
|
|
}
|
|
|
|
func TestGetPostPropertyValues(t *testing.T) {
|
|
th := Setup(t).InitBasic(t)
|
|
|
|
client := th.Client
|
|
|
|
t.Run("Should return 501 when feature is disabled", func(t *testing.T) {
|
|
th.App.Srv().SetLicense(model.NewTestLicenseSKU(model.LicenseShortSkuEnterpriseAdvanced))
|
|
th.App.UpdateConfig(func(config *model.Config) {
|
|
config.ContentFlaggingSettings.EnableContentFlagging = model.NewPointer(false)
|
|
config.ContentFlaggingSettings.SetDefaults()
|
|
})
|
|
|
|
post := th.CreatePost(t)
|
|
propertyValues, resp, err := client.GetPostPropertyValues(context.Background(), post.Id)
|
|
require.Error(t, err)
|
|
require.Equal(t, http.StatusNotImplemented, resp.StatusCode)
|
|
require.Nil(t, propertyValues)
|
|
})
|
|
|
|
t.Run("Should return 403 when user is not a reviewer", func(t *testing.T) {
|
|
th.App.Srv().SetLicense(model.NewTestLicenseSKU(model.LicenseShortSkuEnterpriseAdvanced))
|
|
th.App.UpdateConfig(func(config *model.Config) {
|
|
config.ContentFlaggingSettings.EnableContentFlagging = model.NewPointer(true)
|
|
config.ContentFlaggingSettings.SetDefaults()
|
|
})
|
|
|
|
post := th.CreatePost(t)
|
|
propertyValues, resp, err := client.GetPostPropertyValues(context.Background(), post.Id)
|
|
require.Error(t, err)
|
|
require.Equal(t, http.StatusForbidden, resp.StatusCode)
|
|
require.Nil(t, propertyValues)
|
|
})
|
|
|
|
t.Run("Should successfully get property values when user is a reviewer", func(t *testing.T) {
|
|
th.App.Srv().SetLicense(model.NewTestLicenseSKU(model.LicenseShortSkuEnterpriseAdvanced))
|
|
appErr := setBasicCommonReviewerConfig(th)
|
|
require.Nil(t, appErr)
|
|
|
|
post := th.CreatePost(t)
|
|
flagPostViaAPI(t, client, post.Id)
|
|
|
|
// Now get the property values
|
|
propertyValues, resp, err := client.GetPostPropertyValues(context.Background(), post.Id)
|
|
require.NoError(t, err)
|
|
require.Equal(t, http.StatusOK, resp.StatusCode)
|
|
require.NotNil(t, propertyValues)
|
|
require.Len(t, propertyValues, 6)
|
|
})
|
|
}
|
|
|
|
func TestGetFlaggedPost(t *testing.T) {
|
|
th := Setup(t).InitBasic(t)
|
|
|
|
client := th.Client
|
|
|
|
t.Run("Should return 501 when feature is disabled", func(t *testing.T) {
|
|
th.App.Srv().SetLicense(model.NewTestLicenseSKU(model.LicenseShortSkuEnterpriseAdvanced))
|
|
th.App.UpdateConfig(func(config *model.Config) {
|
|
config.ContentFlaggingSettings.EnableContentFlagging = model.NewPointer(false)
|
|
config.ContentFlaggingSettings.SetDefaults()
|
|
})
|
|
|
|
post := th.CreatePost(t)
|
|
flaggedPost, resp, err := client.GetContentFlaggedPost(context.Background(), post.Id)
|
|
require.Error(t, err)
|
|
require.Equal(t, http.StatusNotImplemented, resp.StatusCode)
|
|
require.Nil(t, flaggedPost)
|
|
})
|
|
|
|
t.Run("Should return 403 when user is not a reviewer", func(t *testing.T) {
|
|
th.App.Srv().SetLicense(model.NewTestLicenseSKU(model.LicenseShortSkuEnterpriseAdvanced))
|
|
|
|
appErr := setNonReviewerConfig(th)
|
|
require.Nil(t, appErr)
|
|
|
|
post := th.CreatePost(t)
|
|
flaggedPost, resp, err := client.GetContentFlaggedPost(context.Background(), post.Id)
|
|
require.Error(t, err)
|
|
require.Equal(t, http.StatusForbidden, resp.StatusCode)
|
|
require.Nil(t, flaggedPost)
|
|
})
|
|
|
|
t.Run("Should return 404 when post is not flagged", func(t *testing.T) {
|
|
th.App.Srv().SetLicense(model.NewTestLicenseSKU(model.LicenseShortSkuEnterpriseAdvanced))
|
|
|
|
appErr := setBasicCommonReviewerConfig(th)
|
|
require.Nil(t, appErr)
|
|
|
|
post := th.CreatePost(t)
|
|
flaggedPost, resp, err := client.GetContentFlaggedPost(context.Background(), post.Id)
|
|
require.Error(t, err)
|
|
require.Equal(t, http.StatusNotFound, resp.StatusCode)
|
|
require.Nil(t, flaggedPost)
|
|
})
|
|
|
|
t.Run("Should successfully get flagged post when user is a reviewer and post is flagged", func(t *testing.T) {
|
|
th.App.Srv().SetLicense(model.NewTestLicenseSKU(model.LicenseShortSkuEnterpriseAdvanced))
|
|
|
|
appErr := setBasicCommonReviewerConfig(th)
|
|
require.Nil(t, appErr)
|
|
|
|
post := th.CreatePost(t)
|
|
flagPostViaAPI(t, client, post.Id)
|
|
|
|
// Now get the flagged post
|
|
flaggedPost, resp, err := client.GetContentFlaggedPost(context.Background(), post.Id)
|
|
require.NoError(t, err)
|
|
require.Equal(t, http.StatusOK, resp.StatusCode)
|
|
require.NotNil(t, flaggedPost)
|
|
require.Equal(t, post.Id, flaggedPost.Id)
|
|
})
|
|
|
|
t.Run("Should return flagged post's file info", func(t *testing.T) {
|
|
th.App.Srv().SetLicense(model.NewTestLicenseSKU(model.LicenseShortSkuEnterpriseAdvanced))
|
|
|
|
appErr := setBasicCommonReviewerConfig(th)
|
|
require.Nil(t, appErr)
|
|
|
|
post, fileInfo := uploadFileAndCreatePost(t, th, client)
|
|
flagPostViaAPI(t, client, post.Id)
|
|
|
|
flaggedPost, resp, err := client.GetContentFlaggedPost(context.Background(), post.Id)
|
|
require.NoError(t, err)
|
|
require.Equal(t, http.StatusOK, resp.StatusCode)
|
|
require.Equal(t, 1, len(flaggedPost.Metadata.Files))
|
|
require.Equal(t, fileInfo.Id, flaggedPost.Metadata.Files[0].Id)
|
|
})
|
|
}
|
|
|
|
func TestFlagPost(t *testing.T) {
|
|
th := Setup(t).InitBasic(t)
|
|
|
|
// Enable BurnOnRead feature flag
|
|
th.App.UpdateConfig(func(cfg *model.Config) { cfg.FeatureFlags.BurnOnRead = true })
|
|
|
|
client := th.Client
|
|
|
|
t.Run("Should return 501 when feature is disabled", func(t *testing.T) {
|
|
th.App.Srv().SetLicense(model.NewTestLicenseSKU(model.LicenseShortSkuEnterpriseAdvanced))
|
|
defer th.RemoveLicense(t)
|
|
|
|
th.App.UpdateConfig(func(config *model.Config) {
|
|
config.ContentFlaggingSettings.EnableContentFlagging = model.NewPointer(false)
|
|
config.ContentFlaggingSettings.SetDefaults()
|
|
})
|
|
|
|
post := th.CreatePost(t)
|
|
flagRequest := &model.FlagContentRequest{
|
|
Reason: "spam",
|
|
Comment: "This is spam content",
|
|
}
|
|
|
|
resp, err := client.FlagPostForContentReview(context.Background(), post.Id, flagRequest)
|
|
require.Error(t, err)
|
|
require.Equal(t, http.StatusNotImplemented, resp.StatusCode)
|
|
})
|
|
|
|
t.Run("Should return 403 when user does not have permission to view post", func(t *testing.T) {
|
|
th.App.Srv().SetLicense(model.NewTestLicenseSKU(model.LicenseShortSkuEnterpriseAdvanced))
|
|
defer th.RemoveLicense(t)
|
|
|
|
th.App.UpdateConfig(func(config *model.Config) {
|
|
config.ContentFlaggingSettings.EnableContentFlagging = model.NewPointer(true)
|
|
config.ContentFlaggingSettings.SetDefaults()
|
|
})
|
|
|
|
// Create a private channel and post
|
|
privateChannel := th.CreatePrivateChannel(t)
|
|
post := th.CreatePostWithClient(t, th.Client, privateChannel)
|
|
th.RemoveUserFromChannel(t, th.BasicUser, privateChannel)
|
|
|
|
flagRequest := &model.FlagContentRequest{
|
|
Reason: "spam",
|
|
Comment: "This is spam content",
|
|
}
|
|
|
|
resp, err := client.FlagPostForContentReview(context.Background(), post.Id, flagRequest)
|
|
require.Error(t, err)
|
|
require.Equal(t, http.StatusForbidden, resp.StatusCode)
|
|
})
|
|
|
|
t.Run("Should return 400 when content flagging is not enabled for the team", func(t *testing.T) {
|
|
th.App.Srv().SetLicense(model.NewTestLicenseSKU(model.LicenseShortSkuEnterpriseAdvanced))
|
|
defer th.RemoveLicense(t)
|
|
|
|
config := model.ContentFlaggingSettingsRequest{
|
|
ContentFlaggingSettingsBase: model.ContentFlaggingSettingsBase{
|
|
EnableContentFlagging: model.NewPointer(true),
|
|
},
|
|
ReviewerSettings: &model.ReviewSettingsRequest{
|
|
ReviewerSettings: model.ReviewerSettings{
|
|
CommonReviewers: model.NewPointer(false),
|
|
},
|
|
ReviewerIDsSettings: model.ReviewerIDsSettings{
|
|
TeamReviewersSetting: map[string]*model.TeamReviewerSetting{
|
|
th.BasicTeam.Id: {Enabled: model.NewPointer(false)},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
config.SetDefaults()
|
|
appErr := th.App.SaveContentFlaggingConfig(config)
|
|
require.Nil(t, appErr)
|
|
|
|
post := th.CreatePost(t)
|
|
flagRequest := &model.FlagContentRequest{
|
|
Reason: "spam",
|
|
Comment: "This is spam content",
|
|
}
|
|
|
|
resp, err := client.FlagPostForContentReview(context.Background(), post.Id, flagRequest)
|
|
require.Error(t, err)
|
|
require.Equal(t, http.StatusBadRequest, resp.StatusCode)
|
|
})
|
|
|
|
t.Run("Should successfully flag a post when all conditions are met", func(t *testing.T) {
|
|
th.App.Srv().SetLicense(model.NewTestLicenseSKU(model.LicenseShortSkuEnterpriseAdvanced))
|
|
defer th.RemoveLicense(t)
|
|
|
|
appErr := setBasicCommonReviewerConfig(th)
|
|
require.Nil(t, appErr)
|
|
|
|
post := th.CreatePost(t)
|
|
flagRequest := &model.FlagContentRequest{
|
|
Reason: "Classification mismatch",
|
|
Comment: "This is sensitive data",
|
|
}
|
|
|
|
resp, err := client.FlagPostForContentReview(context.Background(), post.Id, flagRequest)
|
|
require.NoError(t, err)
|
|
require.Equal(t, http.StatusOK, resp.StatusCode)
|
|
})
|
|
|
|
t.Run("Should not allow flagging a burn on read post", func(t *testing.T) {
|
|
enableBurnOnReadFeature(th)
|
|
defer th.RemoveLicense(t)
|
|
|
|
th.App.UpdateConfig(func(config *model.Config) {
|
|
config.ContentFlaggingSettings.EnableContentFlagging = model.NewPointer(true)
|
|
config.ContentFlaggingSettings.SetDefaults()
|
|
})
|
|
|
|
post := &model.Post{
|
|
UserId: th.BasicUser.Id,
|
|
ChannelId: th.BasicChannel.Id,
|
|
Message: "This is a burn on read post",
|
|
Type: model.PostTypeBurnOnRead,
|
|
}
|
|
|
|
createdPost, response, err := client.CreatePost(context.Background(), post)
|
|
require.NoError(t, err)
|
|
CheckCreatedStatus(t, response)
|
|
|
|
flagRequest := &model.FlagContentRequest{
|
|
Reason: "spam",
|
|
Comment: "This is spam content",
|
|
}
|
|
|
|
response, err = client.FlagPostForContentReview(context.Background(), createdPost.Id, flagRequest)
|
|
require.Error(t, err)
|
|
CheckBadRequestStatus(t, response)
|
|
})
|
|
}
|
|
|
|
func TestGetTeamPostReportingFeatureStatus(t *testing.T) {
|
|
th := Setup(t)
|
|
|
|
client := th.Client
|
|
|
|
t.Run("Should return 501 when feature is disabled", func(t *testing.T) {
|
|
th.App.Srv().SetLicense(model.NewTestLicenseSKU(model.LicenseShortSkuEnterpriseAdvanced))
|
|
defer th.RemoveLicense(t)
|
|
|
|
th.App.UpdateConfig(func(config *model.Config) {
|
|
config.ContentFlaggingSettings.EnableContentFlagging = model.NewPointer(false)
|
|
config.ContentFlaggingSettings.SetDefaults()
|
|
})
|
|
|
|
status, resp, err := client.GetTeamPostFlaggingFeatureStatus(context.Background(), model.NewId())
|
|
require.Error(t, err)
|
|
require.Equal(t, http.StatusNotImplemented, resp.StatusCode)
|
|
require.Nil(t, status)
|
|
})
|
|
|
|
t.Run("Should return Forbidden error when calling for a team without the team membership", func(t *testing.T) {
|
|
th.App.Srv().SetLicense(model.NewTestLicenseSKU(model.LicenseShortSkuEnterpriseAdvanced))
|
|
defer th.RemoveLicense(t)
|
|
|
|
config := model.ContentFlaggingSettingsRequest{
|
|
ContentFlaggingSettingsBase: model.ContentFlaggingSettingsBase{
|
|
EnableContentFlagging: model.NewPointer(true),
|
|
},
|
|
ReviewerSettings: &model.ReviewSettingsRequest{
|
|
ReviewerSettings: model.ReviewerSettings{
|
|
CommonReviewers: model.NewPointer(true),
|
|
},
|
|
ReviewerIDsSettings: model.ReviewerIDsSettings{
|
|
CommonReviewerIds: []string{"reviewer_user_id_1", "reviewer_user_id_2"},
|
|
},
|
|
},
|
|
}
|
|
config.SetDefaults()
|
|
appErr := th.App.SaveContentFlaggingConfig(config)
|
|
require.Nil(t, appErr)
|
|
|
|
// using basic user because the default user is a system admin, and they have
|
|
// access to all teams even without being an explicit team member
|
|
th.LoginBasic(t)
|
|
team := th.CreateTeam(t)
|
|
// unlinking from the created team as by default the team's creator is
|
|
// a team member, so we need to leave the team explicitly
|
|
th.UnlinkUserFromTeam(t, th.BasicUser, team)
|
|
|
|
status, resp, err := client.GetTeamPostFlaggingFeatureStatus(context.Background(), team.Id)
|
|
require.Error(t, err)
|
|
require.Equal(t, http.StatusForbidden, resp.StatusCode)
|
|
require.Nil(t, status)
|
|
|
|
// now we will join the team and that will allow us to call the endpoint without error
|
|
th.LinkUserToTeam(t, th.BasicUser, team)
|
|
status, resp, err = client.GetTeamPostFlaggingFeatureStatus(context.Background(), team.Id)
|
|
require.NoError(t, err)
|
|
require.Equal(t, http.StatusOK, resp.StatusCode)
|
|
require.True(t, status["enabled"])
|
|
})
|
|
}
|
|
|
|
func TestSearchReviewers(t *testing.T) {
|
|
th := Setup(t).InitBasic(t)
|
|
|
|
client := th.Client
|
|
|
|
t.Run("Should return 501 when feature is disabled", func(t *testing.T) {
|
|
th.App.Srv().SetLicense(model.NewTestLicenseSKU(model.LicenseShortSkuEnterpriseAdvanced))
|
|
defer th.RemoveLicense(t)
|
|
|
|
th.App.UpdateConfig(func(config *model.Config) {
|
|
config.ContentFlaggingSettings.EnableContentFlagging = model.NewPointer(false)
|
|
config.ContentFlaggingSettings.SetDefaults()
|
|
})
|
|
|
|
reviewers, resp, err := client.SearchContentFlaggingReviewers(context.Background(), th.BasicTeam.Id, "test")
|
|
require.Error(t, err)
|
|
require.Equal(t, http.StatusNotImplemented, resp.StatusCode)
|
|
require.Nil(t, reviewers)
|
|
})
|
|
|
|
t.Run("Should return 403 when user is not a reviewer", func(t *testing.T) {
|
|
th.App.Srv().SetLicense(model.NewTestLicenseSKU(model.LicenseShortSkuEnterpriseAdvanced))
|
|
defer th.RemoveLicense(t)
|
|
|
|
appErr := setNonReviewerConfig(th)
|
|
require.Nil(t, appErr)
|
|
|
|
reviewers, resp, err := client.SearchContentFlaggingReviewers(context.Background(), th.BasicTeam.Id, "test")
|
|
require.Error(t, err)
|
|
require.Equal(t, http.StatusForbidden, resp.StatusCode)
|
|
require.Nil(t, reviewers)
|
|
})
|
|
|
|
t.Run("Should successfully search reviewers when user is a reviewer", func(t *testing.T) {
|
|
th.App.Srv().SetLicense(model.NewTestLicenseSKU(model.LicenseShortSkuEnterpriseAdvanced))
|
|
defer th.RemoveLicense(t)
|
|
|
|
appErr := setBasicCommonReviewerConfig(th)
|
|
require.Nil(t, appErr)
|
|
|
|
reviewers, resp, err := client.SearchContentFlaggingReviewers(context.Background(), th.BasicTeam.Id, "basic")
|
|
require.NoError(t, err)
|
|
require.Equal(t, http.StatusOK, resp.StatusCode)
|
|
require.NotNil(t, reviewers)
|
|
})
|
|
|
|
t.Run("Should successfully search reviewers when user is a team reviewer", func(t *testing.T) {
|
|
th.App.Srv().SetLicense(model.NewTestLicenseSKU(model.LicenseShortSkuEnterpriseAdvanced))
|
|
defer th.RemoveLicense(t)
|
|
|
|
appErr := setBasicTeamReviewerConfig(th)
|
|
require.Nil(t, appErr)
|
|
|
|
reviewers, resp, err := client.SearchContentFlaggingReviewers(context.Background(), th.BasicTeam.Id, "basic")
|
|
require.NoError(t, err)
|
|
require.Equal(t, http.StatusOK, resp.StatusCode)
|
|
require.NotNil(t, reviewers)
|
|
})
|
|
}
|
|
|
|
func TestAssignContentFlaggingReviewer(t *testing.T) {
|
|
th := Setup(t).InitBasic(t)
|
|
|
|
client := th.Client
|
|
|
|
t.Run("Should return 501 when feature is disabled", func(t *testing.T) {
|
|
th.App.Srv().SetLicense(model.NewTestLicenseSKU(model.LicenseShortSkuEnterpriseAdvanced))
|
|
defer th.RemoveLicense(t)
|
|
|
|
th.App.UpdateConfig(func(config *model.Config) {
|
|
config.ContentFlaggingSettings.EnableContentFlagging = model.NewPointer(false)
|
|
config.ContentFlaggingSettings.SetDefaults()
|
|
})
|
|
|
|
post := th.CreatePost(t)
|
|
resp, err := client.AssignContentFlaggingReviewer(context.Background(), post.Id, th.BasicUser.Id)
|
|
require.Error(t, err)
|
|
require.Equal(t, http.StatusNotImplemented, resp.StatusCode)
|
|
})
|
|
|
|
t.Run("Should return 400 when user ID is invalid", func(t *testing.T) {
|
|
th.App.Srv().SetLicense(model.NewTestLicenseSKU(model.LicenseShortSkuEnterpriseAdvanced))
|
|
defer th.RemoveLicense(t)
|
|
|
|
appErr := setBasicCommonReviewerConfig(th)
|
|
require.Nil(t, appErr)
|
|
|
|
post := th.CreatePost(t)
|
|
resp, err := client.AssignContentFlaggingReviewer(context.Background(), post.Id, "invalidUserId")
|
|
require.Error(t, err)
|
|
require.Equal(t, http.StatusBadRequest, resp.StatusCode)
|
|
})
|
|
|
|
t.Run("Should return 403 when assigning user is not a reviewer", func(t *testing.T) {
|
|
th.App.Srv().SetLicense(model.NewTestLicenseSKU(model.LicenseShortSkuEnterpriseAdvanced))
|
|
defer th.RemoveLicense(t)
|
|
|
|
appErr := setNonReviewerConfig(th)
|
|
require.Nil(t, appErr)
|
|
|
|
post := th.CreatePost(t)
|
|
resp, err := client.AssignContentFlaggingReviewer(context.Background(), post.Id, th.BasicUser.Id)
|
|
require.Error(t, err)
|
|
require.Equal(t, http.StatusForbidden, resp.StatusCode)
|
|
})
|
|
|
|
t.Run("Should return 400 when assignee is not a reviewer", func(t *testing.T) {
|
|
th.App.Srv().SetLicense(model.NewTestLicenseSKU(model.LicenseShortSkuEnterpriseAdvanced))
|
|
defer th.RemoveLicense(t)
|
|
|
|
// Create another user who will not be a reviewer
|
|
nonReviewerUser := th.CreateUser(t)
|
|
th.LinkUserToTeam(t, nonReviewerUser, th.BasicTeam)
|
|
|
|
config := model.ContentFlaggingSettingsRequest{
|
|
ContentFlaggingSettingsBase: model.ContentFlaggingSettingsBase{
|
|
EnableContentFlagging: model.NewPointer(true),
|
|
},
|
|
ReviewerSettings: &model.ReviewSettingsRequest{
|
|
ReviewerSettings: model.ReviewerSettings{
|
|
CommonReviewers: model.NewPointer(true),
|
|
},
|
|
ReviewerIDsSettings: model.ReviewerIDsSettings{
|
|
CommonReviewerIds: []string{th.BasicUser.Id}, // Only BasicUser is a reviewer
|
|
},
|
|
},
|
|
}
|
|
config.SetDefaults()
|
|
appErr := th.App.SaveContentFlaggingConfig(config)
|
|
require.Nil(t, appErr)
|
|
|
|
post := th.CreatePost(t)
|
|
// Try to assign non-reviewer user
|
|
resp, err := client.AssignContentFlaggingReviewer(context.Background(), post.Id, nonReviewerUser.Id)
|
|
require.Error(t, err)
|
|
require.Equal(t, http.StatusForbidden, resp.StatusCode)
|
|
})
|
|
|
|
t.Run("Should successfully assign reviewer when all conditions are met", func(t *testing.T) {
|
|
th.App.Srv().SetLicense(model.NewTestLicenseSKU(model.LicenseShortSkuEnterpriseAdvanced))
|
|
defer th.RemoveLicense(t)
|
|
|
|
// Create another reviewer user
|
|
reviewerUser := th.CreateUser(t)
|
|
th.LinkUserToTeam(t, reviewerUser, th.BasicTeam)
|
|
|
|
appErr := setBasicCommonReviewerConfig(th)
|
|
require.Nil(t, appErr)
|
|
|
|
// Also add reviewerUser as a common reviewer
|
|
config := model.ContentFlaggingSettingsRequest{
|
|
ContentFlaggingSettingsBase: model.ContentFlaggingSettingsBase{
|
|
EnableContentFlagging: model.NewPointer(true),
|
|
},
|
|
ReviewerSettings: &model.ReviewSettingsRequest{
|
|
ReviewerSettings: model.ReviewerSettings{
|
|
CommonReviewers: model.NewPointer(true),
|
|
},
|
|
ReviewerIDsSettings: model.ReviewerIDsSettings{
|
|
CommonReviewerIds: []string{th.BasicUser.Id, reviewerUser.Id},
|
|
},
|
|
},
|
|
}
|
|
config.SetDefaults()
|
|
appErr = th.App.SaveContentFlaggingConfig(config)
|
|
require.Nil(t, appErr)
|
|
|
|
post := th.CreatePost(t)
|
|
flagPostViaAPI(t, client, post.Id)
|
|
|
|
// Now assign the reviewer
|
|
resp, err := client.AssignContentFlaggingReviewer(context.Background(), post.Id, reviewerUser.Id)
|
|
require.NoError(t, err)
|
|
require.Equal(t, http.StatusOK, resp.StatusCode)
|
|
})
|
|
|
|
t.Run("Should successfully assign reviewer when user is team reviewer", func(t *testing.T) {
|
|
th.App.Srv().SetLicense(model.NewTestLicenseSKU(model.LicenseShortSkuEnterpriseAdvanced))
|
|
defer th.RemoveLicense(t)
|
|
|
|
// Create another reviewer user
|
|
reviewerUser := th.CreateUser(t)
|
|
th.LinkUserToTeam(t, reviewerUser, th.BasicTeam)
|
|
|
|
appErr := setBasicTeamReviewerConfig(th, reviewerUser.Id)
|
|
require.Nil(t, appErr)
|
|
|
|
post := th.CreatePost(t)
|
|
flagPostViaAPI(t, client, post.Id)
|
|
|
|
// Now assign the reviewer
|
|
resp, err := client.AssignContentFlaggingReviewer(context.Background(), post.Id, reviewerUser.Id)
|
|
require.NoError(t, err)
|
|
require.Equal(t, http.StatusOK, resp.StatusCode)
|
|
})
|
|
}
|
|
|
|
func TestRemoveFlaggedPost(t *testing.T) {
|
|
th := Setup(t).InitBasic(t)
|
|
|
|
client := th.Client
|
|
|
|
t.Run("Should return 501 when feature is disabled", func(t *testing.T) {
|
|
th.App.Srv().SetLicense(model.NewTestLicenseSKU(model.LicenseShortSkuEnterpriseAdvanced))
|
|
defer th.RemoveLicense(t)
|
|
|
|
th.App.UpdateConfig(func(config *model.Config) {
|
|
config.ContentFlaggingSettings.EnableContentFlagging = model.NewPointer(false)
|
|
config.ContentFlaggingSettings.SetDefaults()
|
|
})
|
|
|
|
post := th.CreatePost(t)
|
|
actionRequest := &model.FlagContentActionRequest{
|
|
Comment: "Removing this post",
|
|
}
|
|
|
|
resp, err := client.RemoveFlaggedPost(context.Background(), post.Id, actionRequest)
|
|
require.Error(t, err)
|
|
require.Equal(t, http.StatusNotImplemented, resp.StatusCode)
|
|
})
|
|
|
|
t.Run("Should return 403 when user is not a reviewer", func(t *testing.T) {
|
|
th.App.Srv().SetLicense(model.NewTestLicenseSKU(model.LicenseShortSkuEnterpriseAdvanced))
|
|
defer th.RemoveLicense(t)
|
|
|
|
appErr := setNonReviewerConfig(th)
|
|
require.Nil(t, appErr)
|
|
|
|
post := th.CreatePost(t)
|
|
actionRequest := &model.FlagContentActionRequest{
|
|
Comment: "Removing this post",
|
|
}
|
|
|
|
resp, err := client.RemoveFlaggedPost(context.Background(), post.Id, actionRequest)
|
|
require.Error(t, err)
|
|
require.Equal(t, http.StatusForbidden, resp.StatusCode)
|
|
})
|
|
|
|
t.Run("Should return 400 when comment is required but not provided", func(t *testing.T) {
|
|
th.App.Srv().SetLicense(model.NewTestLicenseSKU(model.LicenseShortSkuEnterpriseAdvanced))
|
|
defer th.RemoveLicense(t)
|
|
|
|
appErr := setCommonReviewerWithRequiredCommentConfig(th)
|
|
require.Nil(t, appErr)
|
|
|
|
post := th.CreatePost(t)
|
|
flagPostViaAPI(t, client, post.Id)
|
|
|
|
// Try to remove without comment
|
|
actionRequest := &model.FlagContentActionRequest{
|
|
Comment: "", // Empty comment when required
|
|
}
|
|
|
|
resp, err := client.RemoveFlaggedPost(context.Background(), post.Id, actionRequest)
|
|
require.Error(t, err)
|
|
require.Equal(t, http.StatusBadRequest, resp.StatusCode)
|
|
})
|
|
|
|
t.Run("Should successfully remove flagged post when all conditions are met", func(t *testing.T) {
|
|
th.App.Srv().SetLicense(model.NewTestLicenseSKU(model.LicenseShortSkuEnterpriseAdvanced))
|
|
defer th.RemoveLicense(t)
|
|
|
|
appErr := setBasicCommonReviewerConfig(th)
|
|
require.Nil(t, appErr)
|
|
|
|
post := th.CreatePost(t)
|
|
flagPostViaAPI(t, client, post.Id)
|
|
|
|
// Now remove the flagged post
|
|
actionRequest := &model.FlagContentActionRequest{
|
|
Comment: "Removing this post due to policy violation",
|
|
}
|
|
|
|
resp, err := client.RemoveFlaggedPost(context.Background(), post.Id, actionRequest)
|
|
require.NoError(t, err)
|
|
require.Equal(t, http.StatusOK, resp.StatusCode)
|
|
|
|
// Verify the post was deleted
|
|
_, resp, err = client.GetPost(context.Background(), post.Id, "")
|
|
require.Error(t, err)
|
|
require.Equal(t, http.StatusNotFound, resp.StatusCode)
|
|
})
|
|
|
|
t.Run("Should successfully remove flagged post when user is team reviewer", func(t *testing.T) {
|
|
th.App.Srv().SetLicense(model.NewTestLicenseSKU(model.LicenseShortSkuEnterpriseAdvanced))
|
|
defer th.RemoveLicense(t)
|
|
|
|
appErr := setBasicTeamReviewerConfig(th)
|
|
require.Nil(t, appErr)
|
|
|
|
post := th.CreatePost(t)
|
|
flagPostViaAPI(t, client, post.Id)
|
|
|
|
// Now remove the flagged post
|
|
actionRequest := &model.FlagContentActionRequest{
|
|
Comment: "Removing this post due to policy violation",
|
|
}
|
|
|
|
resp, err := client.RemoveFlaggedPost(context.Background(), post.Id, actionRequest)
|
|
require.NoError(t, err)
|
|
require.Equal(t, http.StatusOK, resp.StatusCode)
|
|
})
|
|
|
|
t.Run("Should remove file attachments and edit history when removing flagged post", func(t *testing.T) {
|
|
th.App.Srv().SetLicense(model.NewTestLicenseSKU(model.LicenseShortSkuEnterpriseAdvanced))
|
|
defer th.RemoveLicense(t)
|
|
|
|
appErr := setBasicCommonReviewerConfig(th)
|
|
require.Nil(t, appErr)
|
|
|
|
post, fileInfo := uploadFileAndCreatePost(t, th, client)
|
|
|
|
// Verify file info exists for the post
|
|
fileInfos, err2 := th.App.Srv().Store().FileInfo().GetForPost(post.Id, true, false, false)
|
|
require.NoError(t, err2)
|
|
require.Len(t, fileInfos, 1)
|
|
require.Equal(t, fileInfo.Id, fileInfos[0].Id)
|
|
|
|
// Update the post to create edit history
|
|
post.Message = "Updated message to create edit history"
|
|
updatedPost, _, err := client.UpdatePost(context.Background(), post.Id, post)
|
|
require.NoError(t, err)
|
|
require.NotNil(t, updatedPost)
|
|
require.Equal(t, "Updated message to create edit history", updatedPost.Message)
|
|
|
|
// Verify edit history exists
|
|
editHistory, appErr := th.App.GetEditHistoryForPost(post.Id)
|
|
require.Nil(t, appErr)
|
|
require.NotEmpty(t, editHistory)
|
|
editHistoryPostId := editHistory[0].Id
|
|
|
|
flagPostViaAPI(t, client, post.Id)
|
|
|
|
// Remove the flagged post
|
|
actionRequest := &model.FlagContentActionRequest{
|
|
Comment: "Removing this post due to policy violation",
|
|
}
|
|
|
|
resp, err := client.RemoveFlaggedPost(context.Background(), post.Id, actionRequest)
|
|
require.NoError(t, err)
|
|
require.Equal(t, http.StatusOK, resp.StatusCode)
|
|
|
|
// Verify file attachments are removed from database
|
|
fileInfosAfter, err2 := th.App.Srv().Store().FileInfo().GetForPost(post.Id, true, true, false)
|
|
require.NoError(t, err2)
|
|
require.Empty(t, fileInfosAfter, "File attachments should be removed from database after removing flagged post")
|
|
|
|
// Verify edit history posts are removed from database
|
|
editHistoryAfter, appErr := th.App.GetEditHistoryForPost(post.Id)
|
|
require.NotNil(t, appErr)
|
|
require.Equal(t, http.StatusNotFound, appErr.StatusCode, "Edit history should be removed from database after removing flagged post")
|
|
require.Empty(t, editHistoryAfter)
|
|
|
|
// Verify the edit history post is also permanently deleted
|
|
_, err2 = th.App.Srv().Store().Post().GetSingle(th.Context, editHistoryPostId, true)
|
|
require.Error(t, err2, "Edit history post should be permanently deleted")
|
|
})
|
|
}
|
|
|
|
func TestKeepFlaggedPost(t *testing.T) {
|
|
th := Setup(t).InitBasic(t)
|
|
|
|
client := th.Client
|
|
|
|
t.Run("Should return 501 when feature is disabled", func(t *testing.T) {
|
|
th.App.Srv().SetLicense(model.NewTestLicenseSKU(model.LicenseShortSkuEnterpriseAdvanced))
|
|
defer th.RemoveLicense(t)
|
|
|
|
th.App.UpdateConfig(func(config *model.Config) {
|
|
config.ContentFlaggingSettings.EnableContentFlagging = model.NewPointer(false)
|
|
config.ContentFlaggingSettings.SetDefaults()
|
|
})
|
|
|
|
post := th.CreatePost(t)
|
|
actionRequest := &model.FlagContentActionRequest{
|
|
Comment: "Keeping this post",
|
|
}
|
|
|
|
resp, err := client.KeepFlaggedPost(context.Background(), post.Id, actionRequest)
|
|
require.Error(t, err)
|
|
require.Equal(t, http.StatusNotImplemented, resp.StatusCode)
|
|
})
|
|
|
|
t.Run("Should return 403 when user is not a reviewer", func(t *testing.T) {
|
|
th.App.Srv().SetLicense(model.NewTestLicenseSKU(model.LicenseShortSkuEnterpriseAdvanced))
|
|
defer th.RemoveLicense(t)
|
|
|
|
appErr := setNonReviewerConfig(th)
|
|
require.Nil(t, appErr)
|
|
|
|
post := th.CreatePost(t)
|
|
actionRequest := &model.FlagContentActionRequest{
|
|
Comment: "Keeping this post",
|
|
}
|
|
|
|
resp, err := client.KeepFlaggedPost(context.Background(), post.Id, actionRequest)
|
|
require.Error(t, err)
|
|
require.Equal(t, http.StatusForbidden, resp.StatusCode)
|
|
})
|
|
|
|
t.Run("Should return 400 when comment is required but not provided", func(t *testing.T) {
|
|
th.App.Srv().SetLicense(model.NewTestLicenseSKU(model.LicenseShortSkuEnterpriseAdvanced))
|
|
defer th.RemoveLicense(t)
|
|
|
|
appErr := setCommonReviewerWithRequiredCommentConfig(th)
|
|
require.Nil(t, appErr)
|
|
|
|
post := th.CreatePost(t)
|
|
flagPostViaAPI(t, client, post.Id)
|
|
|
|
// Try to keep without comment
|
|
actionRequest := &model.FlagContentActionRequest{
|
|
Comment: "", // Empty comment when required
|
|
}
|
|
|
|
resp, err := client.KeepFlaggedPost(context.Background(), post.Id, actionRequest)
|
|
require.Error(t, err)
|
|
require.Equal(t, http.StatusBadRequest, resp.StatusCode)
|
|
})
|
|
|
|
t.Run("Should successfully keep flagged post when all conditions are met", func(t *testing.T) {
|
|
th.App.Srv().SetLicense(model.NewTestLicenseSKU(model.LicenseShortSkuEnterpriseAdvanced))
|
|
defer th.RemoveLicense(t)
|
|
|
|
appErr := setBasicCommonReviewerConfig(th)
|
|
require.Nil(t, appErr)
|
|
|
|
post := th.CreatePost(t)
|
|
flagPostViaAPI(t, client, post.Id)
|
|
|
|
// Now keep the flagged post
|
|
actionRequest := &model.FlagContentActionRequest{
|
|
Comment: "Keeping this post after review",
|
|
}
|
|
|
|
resp, err := client.KeepFlaggedPost(context.Background(), post.Id, actionRequest)
|
|
require.NoError(t, err)
|
|
require.Equal(t, http.StatusOK, resp.StatusCode)
|
|
|
|
// Verify the post still exists
|
|
fetchedPost, resp, err := client.GetPost(context.Background(), post.Id, "")
|
|
require.NoError(t, err)
|
|
require.Equal(t, http.StatusOK, resp.StatusCode)
|
|
require.NotNil(t, fetchedPost)
|
|
require.Equal(t, post.Id, fetchedPost.Id)
|
|
})
|
|
|
|
t.Run("Should successfully keep flagged post when user is team reviewer", func(t *testing.T) {
|
|
th.App.Srv().SetLicense(model.NewTestLicenseSKU(model.LicenseShortSkuEnterpriseAdvanced))
|
|
defer th.RemoveLicense(t)
|
|
|
|
appErr := setBasicTeamReviewerConfig(th)
|
|
require.Nil(t, appErr)
|
|
|
|
post := th.CreatePost(t)
|
|
flagPostViaAPI(t, client, post.Id)
|
|
|
|
// Now keep the flagged post
|
|
actionRequest := &model.FlagContentActionRequest{
|
|
Comment: "Keeping this post after review",
|
|
}
|
|
|
|
resp, err := client.KeepFlaggedPost(context.Background(), post.Id, actionRequest)
|
|
require.NoError(t, err)
|
|
require.Equal(t, http.StatusOK, resp.StatusCode)
|
|
})
|
|
|
|
t.Run("Should preserve file attachments and edit history when keeping flagged post", func(t *testing.T) {
|
|
th.App.Srv().SetLicense(model.NewTestLicenseSKU(model.LicenseShortSkuEnterpriseAdvanced))
|
|
defer th.RemoveLicense(t)
|
|
|
|
appErr := setBasicCommonReviewerConfig(th)
|
|
require.Nil(t, appErr)
|
|
|
|
post, fileInfo := uploadFileAndCreatePost(t, th, client)
|
|
|
|
// Verify file info exists for the post
|
|
fileInfos, err2 := th.App.Srv().Store().FileInfo().GetForPost(post.Id, true, false, false)
|
|
require.NoError(t, err2)
|
|
require.Len(t, fileInfos, 1)
|
|
require.Equal(t, fileInfo.Id, fileInfos[0].Id)
|
|
|
|
// Update the post to create edit history
|
|
post.Message = "Updated message to create edit history"
|
|
updatedPost, _, err := client.UpdatePost(context.Background(), post.Id, post)
|
|
require.NoError(t, err)
|
|
require.NotNil(t, updatedPost)
|
|
require.Equal(t, "Updated message to create edit history", updatedPost.Message)
|
|
|
|
// Verify edit history exists
|
|
editHistory, appErr := th.App.GetEditHistoryForPost(post.Id)
|
|
require.Nil(t, appErr)
|
|
require.NotEmpty(t, editHistory)
|
|
editHistoryPostId := editHistory[0].Id
|
|
|
|
flagPostViaAPI(t, client, post.Id)
|
|
|
|
// Keep the flagged post
|
|
actionRequest := &model.FlagContentActionRequest{
|
|
Comment: "Keeping this post after review - content is acceptable",
|
|
}
|
|
|
|
resp, err := client.KeepFlaggedPost(context.Background(), post.Id, actionRequest)
|
|
require.NoError(t, err)
|
|
require.Equal(t, http.StatusOK, resp.StatusCode)
|
|
|
|
// Verify file attachments are still present in database
|
|
fileInfosAfter, err2 := th.App.Srv().Store().FileInfo().GetForPost(post.Id, true, false, false)
|
|
require.NoError(t, err2)
|
|
require.Len(t, fileInfosAfter, 1, "File attachments should be preserved after keeping flagged post")
|
|
require.Equal(t, fileInfo.Id, fileInfosAfter[0].Id)
|
|
|
|
// Verify edit history is still present in database
|
|
editHistoryAfter, appErr := th.App.GetEditHistoryForPost(post.Id)
|
|
require.Nil(t, appErr, "Edit history should be preserved after keeping flagged post")
|
|
require.NotEmpty(t, editHistoryAfter)
|
|
require.Equal(t, editHistoryPostId, editHistoryAfter[0].Id)
|
|
|
|
// Verify the post still exists and is accessible
|
|
fetchedPost, resp, err := client.GetPost(context.Background(), post.Id, "")
|
|
require.NoError(t, err)
|
|
require.Equal(t, http.StatusOK, resp.StatusCode)
|
|
require.NotNil(t, fetchedPost)
|
|
require.Equal(t, post.Id, fetchedPost.Id)
|
|
})
|
|
}
|