From 5b6b425cfc110890b1cc9792ef0790c138401e65 Mon Sep 17 00:00:00 2001 From: Ben Schumacher Date: Mon, 11 Dec 2023 10:27:51 +0100 Subject: [PATCH] [MM-56061] Only render where field in model.AppError when it's present (#25648) * Only render where field in model.AppError when it's present * Remove trailing comma from permission error --- server/channels/api4/group.go | 6 +-- server/channels/api4/notify_admin_test.go | 14 ++--- server/channels/api4/post_test.go | 2 +- server/channels/api4/user.go | 2 +- server/channels/api4/user_test.go | 10 ++-- server/channels/app/app_iface.go | 1 - server/channels/app/authorization.go | 13 +---- .../app/opentracing/opentracing_layer.go | 22 -------- server/channels/app/post.go | 4 +- server/channels/web/context.go | 2 +- server/cmd/mmctl/commands/bot_e2e_test.go | 2 +- server/cmd/mmctl/commands/channel_e2e_test.go | 4 +- .../mmctl/commands/channel_users_e2e_test.go | 2 +- server/cmd/mmctl/commands/command_e2e_test.go | 4 +- server/cmd/mmctl/commands/export_e2e_test.go | 16 +++--- server/cmd/mmctl/commands/extract_e2e_test.go | 8 +-- server/cmd/mmctl/commands/group_e2e_test.go | 4 +- server/cmd/mmctl/commands/import_e2e_test.go | 12 ++--- server/cmd/mmctl/commands/plugin_e2e_test.go | 6 +-- .../commands/plugin_marketplace_e2e_test.go | 2 +- server/cmd/mmctl/commands/team_e2e_test.go | 10 ++-- server/cmd/mmctl/commands/token_e2e_test.go | 2 +- server/cmd/mmctl/commands/user_e2e_test.go | 28 +++++----- server/public/model/permission.go | 15 ++++++ server/public/model/permission_test.go | 53 +++++++++++++++++++ server/public/model/utils.go | 7 ++- server/public/model/utils_test.go | 5 ++ 27 files changed, 150 insertions(+), 106 deletions(-) create mode 100644 server/public/model/permission_test.go diff --git a/server/channels/api4/group.go b/server/channels/api4/group.go index d053f18a56..681f4cad43 100644 --- a/server/channels/api4/group.go +++ b/server/channels/api4/group.go @@ -634,7 +634,7 @@ func verifyLinkUnlinkPermission(c *Context, syncableType model.GroupSyncableType switch syncableType { case model.GroupSyncableTypeTeam: if !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), syncableID, model.PermissionManageTeam) { - return c.App.MakePermissionError(c.AppContext.Session(), []*model.Permission{model.PermissionManageTeam}) + return model.MakePermissionError(c.AppContext.Session(), []*model.Permission{model.PermissionManageTeam}) } case model.GroupSyncableTypeChannel: channel, err := c.App.GetChannel(c.AppContext, syncableID) @@ -650,7 +650,7 @@ func verifyLinkUnlinkPermission(c *Context, syncableType model.GroupSyncableType } if !c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), syncableID, permission) { - return c.App.MakePermissionError(c.AppContext.Session(), []*model.Permission{permission}) + return model.MakePermissionError(c.AppContext.Session(), []*model.Permission{permission}) } } @@ -876,7 +876,7 @@ func getGroupsByChannelCommon(c *Context, r *http.Request) ([]byte, *model.AppEr permission = model.PermissionReadPublicChannelGroups } if !c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), c.Params.ChannelId, permission) { - return nil, c.App.MakePermissionError(c.AppContext.Session(), []*model.Permission{permission}) + return nil, model.MakePermissionError(c.AppContext.Session(), []*model.Permission{permission}) } opts := model.GroupSearchOpts{ diff --git a/server/channels/api4/notify_admin_test.go b/server/channels/api4/notify_admin_test.go index 46b1362562..94f3c71670 100644 --- a/server/channels/api4/notify_admin_test.go +++ b/server/channels/api4/notify_admin_test.go @@ -33,7 +33,7 @@ func TestNotifyAdmin(t *testing.T) { }) require.Error(t, err) - require.Equal(t, ": Unable to save notify data.", err.Error()) + require.Equal(t, "Unable to save notify data.", err.Error()) require.Equal(t, http.StatusInternalServerError, statusCode) }) @@ -48,7 +48,7 @@ func TestNotifyAdmin(t *testing.T) { }) require.Error(t, err) - require.Equal(t, ": Unable to save notify data.", err.Error()) + require.Equal(t, "Unable to save notify data.", err.Error()) require.Equal(t, http.StatusInternalServerError, statusCode) }) @@ -62,7 +62,7 @@ func TestNotifyAdmin(t *testing.T) { }) require.Error(t, err) - require.Equal(t, ": Unable to save notify data.", err.Error()) + require.Equal(t, "Unable to save notify data.", err.Error()) require.Equal(t, http.StatusInternalServerError, statusCode) }) @@ -77,7 +77,7 @@ func TestNotifyAdmin(t *testing.T) { }) require.Error(t, err) - require.Equal(t, ": Unable to save notify data.", err.Error()) + require.Equal(t, "Unable to save notify data.", err.Error()) require.Equal(t, http.StatusInternalServerError, statusCode) }) @@ -99,7 +99,7 @@ func TestNotifyAdmin(t *testing.T) { }) require.Error(t, err) - require.Equal(t, ": Already notified admin", err.Error()) + require.Equal(t, "Already notified admin", err.Error()) require.Equal(t, http.StatusForbidden, statusCode) }) @@ -127,7 +127,7 @@ func TestTriggerNotifyAdmin(t *testing.T) { statusCode, err := th.SystemAdminClient.TriggerNotifyAdmin(context.Background(), &model.NotifyAdminToUpgradeRequest{}) require.Error(t, err) - require.Equal(t, ": Internal error during cloud api request.", err.Error()) + require.Equal(t, "Internal error during cloud api request.", err.Error()) require.Equal(t, http.StatusForbidden, statusCode) }) @@ -140,7 +140,7 @@ func TestTriggerNotifyAdmin(t *testing.T) { statusCode, err := th.Client.TriggerNotifyAdmin(context.Background(), &model.NotifyAdminToUpgradeRequest{}) require.Error(t, err) - require.Equal(t, ": You do not have the appropriate permissions.", err.Error()) + require.Equal(t, "You do not have the appropriate permissions.", err.Error()) require.Equal(t, http.StatusForbidden, statusCode) }) diff --git a/server/channels/api4/post_test.go b/server/channels/api4/post_test.go index 720b721247..7a5a751b4a 100644 --- a/server/channels/api4/post_test.go +++ b/server/channels/api4/post_test.go @@ -1270,7 +1270,7 @@ func TestPatchPost(t *testing.T) { t.Run("invalid requests", func(t *testing.T) { r, err := client.DoAPIPut(context.Background(), "/posts/"+post.Id+"/patch", "garbage") - require.EqualError(t, err, ": Invalid or missing post in request body., invalid character 'g' looking for beginning of value") + require.EqualError(t, err, "Invalid or missing post in request body., invalid character 'g' looking for beginning of value") require.Equal(t, http.StatusBadRequest, r.StatusCode, "wrong status code") patch := &model.PostPatch{} diff --git a/server/channels/api4/user.go b/server/channels/api4/user.go index 8a9770a8ef..94333fa28b 100644 --- a/server/channels/api4/user.go +++ b/server/channels/api4/user.go @@ -947,7 +947,7 @@ func requireGroupAccess(c *web.Context, groupID string) *model.AppError { if group.Source == model.GroupSourceLdap { if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PermissionSysconsoleReadUserManagementGroups) { - return c.App.MakePermissionError(c.AppContext.Session(), []*model.Permission{model.PermissionSysconsoleReadUserManagementGroups}) + return model.MakePermissionError(c.AppContext.Session(), []*model.Permission{model.PermissionSysconsoleReadUserManagementGroups}) } } diff --git a/server/channels/api4/user_test.go b/server/channels/api4/user_test.go index 9b702a2713..73eae7c4dd 100644 --- a/server/channels/api4/user_test.go +++ b/server/channels/api4/user_test.go @@ -2283,7 +2283,7 @@ func TestDeleteBotUser(t *testing.T) { _, err := th.Client.DeleteUser(context.Background(), bot.UserId) require.Error(t, err) - require.Equal(t, err.Error(), ": You do not have the appropriate permissions.") + require.Equal(t, err.Error(), "You do not have the appropriate permissions.") } func TestPermanentDeleteUser(t *testing.T) { @@ -2630,16 +2630,16 @@ func TestGetUsers(t *testing.T) { // Check role params validity _, _, err = client.GetUsersWithCustomQueryParameters(context.Background(), 0, 5, "in_channel=random_channel_id&channel_roles=random_role_doesnt_exist", "") require.Error(t, err) - require.Equal(t, err.Error(), ": Invalid or missing channelRoles in request body.") + require.Equal(t, err.Error(), "Invalid or missing channelRoles in request body.") _, _, err = client.GetUsersWithCustomQueryParameters(context.Background(), 0, 5, "in_team=random_channel_id&team_roles=random_role_doesnt_exist", "") require.Error(t, err) - require.Equal(t, err.Error(), ": Invalid or missing teamRoles in request body.") + require.Equal(t, err.Error(), "Invalid or missing teamRoles in request body.") _, _, err = client.GetUsersWithCustomQueryParameters(context.Background(), 0, 5, "roles=random_role_doesnt_exist%2Csystem_user", "") require.Error(t, err) - require.Equal(t, err.Error(), ": Invalid or missing roles in request body.") + require.Equal(t, err.Error(), "Invalid or missing roles in request body.") _, _, err = client.GetUsersWithCustomQueryParameters(context.Background(), 0, 5, "role=random_role_doesnt_exist", "") require.Error(t, err) - require.Equal(t, err.Error(), ": Invalid or missing role in request body.") + require.Equal(t, err.Error(), "Invalid or missing role in request body.") }) th.Client.Logout(context.Background()) diff --git a/server/channels/app/app_iface.go b/server/channels/app/app_iface.go index 1b261582e2..171749156a 100644 --- a/server/channels/app/app_iface.go +++ b/server/channels/app/app_iface.go @@ -911,7 +911,6 @@ type AppIface interface { ListTeamCommands(teamID string) ([]*model.Command, *model.AppError) Log() *mlog.Logger LoginByOAuth(c request.CTX, service string, userData io.Reader, teamID string, tokenUser *model.User) (*model.User, *model.AppError) - MakePermissionError(s *model.Session, permissions []*model.Permission) *model.AppError MarkChannelsAsViewed(c request.CTX, channelIDs []string, userID string, currentSessionId string, collapsedThreadsSupported, isCRTEnabled bool) (map[string]int64, *model.AppError) MaxPostSize() int MessageExport() einterfaces.MessageExportInterface diff --git a/server/channels/app/authorization.go b/server/channels/app/authorization.go index 2f762c7e02..95a61a7e7b 100644 --- a/server/channels/app/authorization.go +++ b/server/channels/app/authorization.go @@ -14,15 +14,6 @@ import ( "github.com/mattermost/mattermost/server/public/shared/request" ) -func (a *App) MakePermissionError(s *model.Session, permissions []*model.Permission) *model.AppError { - permissionsStr := "permission=" - for _, permission := range permissions { - permissionsStr += permission.Id - permissionsStr += "," - } - return model.NewAppError("Permissions", "api.context.permissions.app_error", nil, "userId="+s.UserId+", "+permissionsStr, http.StatusForbidden) -} - func (a *App) SessionHasPermissionTo(session model.Session, permission *model.Permission) bool { if session.IsUnrestricted() { return true @@ -360,7 +351,7 @@ func (a *App) SessionHasPermissionToManageBot(session model.Session, botUserId s // the bot doesn't exist at all. return model.MakeBotNotFoundError("permissions", botUserId) } - return a.MakePermissionError(&session, []*model.Permission{model.PermissionManageBots}) + return model.MakePermissionError(&session, []*model.Permission{model.PermissionManageBots}) } } else { if !a.SessionHasPermissionTo(session, model.PermissionManageOthersBots) { @@ -369,7 +360,7 @@ func (a *App) SessionHasPermissionToManageBot(session model.Session, botUserId s // pretend as if the bot doesn't exist at all. return model.MakeBotNotFoundError("permissions", botUserId) } - return a.MakePermissionError(&session, []*model.Permission{model.PermissionManageOthersBots}) + return model.MakePermissionError(&session, []*model.Permission{model.PermissionManageOthersBots}) } } diff --git a/server/channels/app/opentracing/opentracing_layer.go b/server/channels/app/opentracing/opentracing_layer.go index 1dcec6f0e6..35595ff1a5 100644 --- a/server/channels/app/opentracing/opentracing_layer.go +++ b/server/channels/app/opentracing/opentracing_layer.go @@ -12464,28 +12464,6 @@ func (a *OpenTracingAppLayer) MakeAuditRecord(rctx request.CTX, event string, in return resultVar0 } -func (a *OpenTracingAppLayer) MakePermissionError(s *model.Session, permissions []*model.Permission) *model.AppError { - origCtx := a.ctx - span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.MakePermissionError") - - a.ctx = newCtx - a.app.Srv().Store().SetContext(newCtx) - defer func() { - a.app.Srv().Store().SetContext(origCtx) - a.ctx = origCtx - }() - - defer span.Finish() - resultVar0 := a.app.MakePermissionError(s, permissions) - - if resultVar0 != nil { - span.LogFields(spanlog.Error(resultVar0)) - ext.Error.Set(span, true) - } - - return resultVar0 -} - func (a *OpenTracingAppLayer) MarkChannelAsUnreadFromPost(c request.CTX, postID string, userID string, collapsedThreadsSupported bool) (*model.ChannelUnreadAt, *model.AppError) { origCtx := a.ctx span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.MarkChannelAsUnreadFromPost") diff --git a/server/channels/app/post.go b/server/channels/app/post.go index 3bc7fd1365..2d9613204f 100644 --- a/server/channels/app/post.go +++ b/server/channels/app/post.go @@ -2055,10 +2055,10 @@ func (a *App) GetPostIfAuthorized(c request.CTX, postID string, session *model.S if !a.SessionHasPermissionToChannel(c, *session, channel.Id, model.PermissionReadChannelContent) { if channel.Type == model.ChannelTypeOpen && !*a.Config().ComplianceSettings.Enable { if !a.SessionHasPermissionToTeam(*session, channel.TeamId, model.PermissionReadPublicChannel) { - return nil, a.MakePermissionError(session, []*model.Permission{model.PermissionReadPublicChannel}) + return nil, model.MakePermissionError(session, []*model.Permission{model.PermissionReadPublicChannel}) } } else { - return nil, a.MakePermissionError(session, []*model.Permission{model.PermissionReadChannelContent}) + return nil, model.MakePermissionError(session, []*model.Permission{model.PermissionReadChannelContent}) } } diff --git a/server/channels/web/context.go b/server/channels/web/context.go index bc4132a71c..9793620ef0 100644 --- a/server/channels/web/context.go +++ b/server/channels/web/context.go @@ -305,7 +305,7 @@ func NewJSONEncodingError(err error) *model.AppError { } func (c *Context) SetPermissionError(permissions ...*model.Permission) { - c.Err = c.App.MakePermissionError(c.AppContext.Session(), permissions) + c.Err = model.MakePermissionError(c.AppContext.Session(), permissions) } func (c *Context) SetSiteURLHeader(url string) { diff --git a/server/cmd/mmctl/commands/bot_e2e_test.go b/server/cmd/mmctl/commands/bot_e2e_test.go index 05091052e5..30e926bbaa 100644 --- a/server/cmd/mmctl/commands/bot_e2e_test.go +++ b/server/cmd/mmctl/commands/bot_e2e_test.go @@ -151,7 +151,7 @@ func (s *MmctlE2ETestSuite) TestListBotCmdF() { err := botListCmdF(s.th.Client, cmd, []string{}) s.Require().Error(err) - s.Require().Equal("Failed to fetch bots: : You do not have the appropriate permissions.", err.Error()) + s.Require().Equal("Failed to fetch bots: You do not have the appropriate permissions.", err.Error()) }) } diff --git a/server/cmd/mmctl/commands/channel_e2e_test.go b/server/cmd/mmctl/commands/channel_e2e_test.go index 3da8db96d3..21ac67c134 100644 --- a/server/cmd/mmctl/commands/channel_e2e_test.go +++ b/server/cmd/mmctl/commands/channel_e2e_test.go @@ -144,7 +144,7 @@ func (s *MmctlE2ETestSuite) TestSearchChannelCmd() { err := searchChannelCmdF(c, cmd, []string{s.th.BasicChannel.Name}) s.Require().NotNil(err) - s.Require().ErrorContains(err, `: Channel does not exist.`) + s.Require().ErrorContains(err, `Channel does not exist.`) s.Require().Len(printer.GetLines(), 0) s.Require().Len(printer.GetErrorLines(), 0) }) @@ -475,7 +475,7 @@ func (s *MmctlE2ETestSuite) TestChannelRenameCmd() { s.Require().NotNil(err) s.Require().Len(printer.GetLines(), 0) s.Require().Len(printer.GetErrorLines(), 0) - s.Require().Equal(fmt.Sprintf("cannot rename channel \"%s\", error: : You do not have the appropriate permissions.", channelInit.Name), err.Error()) + s.Require().Equal(fmt.Sprintf("cannot rename channel \"%s\", error: You do not have the appropriate permissions.", channelInit.Name), err.Error()) rchannel, err := s.th.App.GetChannel(s.th.Context, channel.Id) s.Require().Nil(err) diff --git a/server/cmd/mmctl/commands/channel_users_e2e_test.go b/server/cmd/mmctl/commands/channel_users_e2e_test.go index 30e11f65b8..a01ad8b332 100644 --- a/server/cmd/mmctl/commands/channel_users_e2e_test.go +++ b/server/cmd/mmctl/commands/channel_users_e2e_test.go @@ -98,7 +98,7 @@ func (s *MmctlE2ETestSuite) TestChannelUsersAddCmdF() { s.Require().Nil(err) s.Require().Len(printer.GetLines(), 0) s.Require().Len(printer.GetErrorLines(), 1) - s.Require().Equal(fmt.Sprintf("Unable to add '%s' to %s. Error: : You do not have the appropriate permissions.", user.Id, channelName), printer.GetErrorLines()[0]) + s.Require().Equal(fmt.Sprintf("Unable to add '%s' to %s. Error: You do not have the appropriate permissions.", user.Id, channelName), printer.GetErrorLines()[0]) }) s.Run("Add user to channel/Client", func() { diff --git a/server/cmd/mmctl/commands/command_e2e_test.go b/server/cmd/mmctl/commands/command_e2e_test.go index de1fc8afdd..883c24613a 100644 --- a/server/cmd/mmctl/commands/command_e2e_test.go +++ b/server/cmd/mmctl/commands/command_e2e_test.go @@ -183,7 +183,7 @@ func (s *MmctlE2ETestSuite) TestArchiveCommandCmdF() { err := archiveCommandCmdF(c, &cobra.Command{}, []string{nonexistentCommandID}) s.Require().NotNil(err) - s.Require().Equal(fmt.Sprintf("Unable to archive command '%s' error: : Sorry, we could not find the page., There doesn't appear to be an api call for the url='/api/v4/commands/nonexistent-command-id'. Typo? are you missing a team_id or user_id as part of the url?", nonexistentCommandID), err.Error()) + s.Require().Equal(fmt.Sprintf("Unable to archive command '%s' error: Sorry, we could not find the page., There doesn't appear to be an api call for the url='/api/v4/commands/nonexistent-command-id'. Typo? are you missing a team_id or user_id as part of the url?", nonexistentCommandID), err.Error()) s.Require().Len(printer.GetLines(), 0) s.Require().Len(printer.GetErrorLines(), 0) }) @@ -242,7 +242,7 @@ func (s *MmctlE2ETestSuite) TestArchiveCommandCmdF() { err := archiveCommandCmdF(s.th.Client, &cobra.Command{}, []string{command.Id}) s.Require().NotNil(err) - s.Require().Equal(fmt.Sprintf("Unable to archive command '%s' error: : Unable to get the command.", command.Id), err.Error()) + s.Require().Equal(fmt.Sprintf("Unable to archive command '%s' error: Unable to get the command.", command.Id), err.Error()) rcommand, err := s.th.App.GetCommand(command.Id) s.Require().Nil(err) diff --git a/server/cmd/mmctl/commands/export_e2e_test.go b/server/cmd/mmctl/commands/export_e2e_test.go index 7e8c8f620d..52660c75c9 100644 --- a/server/cmd/mmctl/commands/export_e2e_test.go +++ b/server/cmd/mmctl/commands/export_e2e_test.go @@ -30,7 +30,7 @@ func (s *MmctlE2ETestSuite) TestExportListCmdF() { printer.Clean() err := exportListCmdF(s.th.Client, &cobra.Command{}, nil) - s.Require().EqualError(err, "failed to list exports: : You do not have the appropriate permissions.") + s.Require().EqualError(err, "failed to list exports: You do not have the appropriate permissions.") s.Require().Empty(printer.GetLines()) s.Require().Empty(printer.GetErrorLines()) }) @@ -84,7 +84,7 @@ func (s *MmctlE2ETestSuite) TestExportDeleteCmdF() { printer.Clean() err := exportDeleteCmdF(s.th.Client, &cobra.Command{}, []string{exportName}) - s.Require().EqualError(err, "failed to delete export: : You do not have the appropriate permissions.") + s.Require().EqualError(err, "failed to delete export: You do not have the appropriate permissions.") s.Require().Empty(printer.GetLines()) s.Require().Empty(printer.GetErrorLines()) }) @@ -130,7 +130,7 @@ func (s *MmctlE2ETestSuite) TestExportCreateCmdF() { printer.Clean() err := exportCreateCmdF(s.th.Client, &cobra.Command{}, nil) - s.Require().EqualError(err, "failed to create export process job: : You do not have the appropriate permissions.") + s.Require().EqualError(err, "failed to create export process job: You do not have the appropriate permissions.") s.Require().Empty(printer.GetLines()) s.Require().Empty(printer.GetErrorLines()) }) @@ -291,7 +291,7 @@ func (s *MmctlE2ETestSuite) TestExportJobShowCmdF() { s.Require().Nil(appErr) err := exportJobShowCmdF(s.th.Client, &cobra.Command{}, []string{job1.Id}) - s.Require().EqualError(err, "failed to get export job: : You do not have the appropriate permissions.") + s.Require().EqualError(err, "failed to get export job: You do not have the appropriate permissions.") s.Require().Empty(printer.GetLines()) s.Require().Empty(printer.GetErrorLines()) }) @@ -300,7 +300,7 @@ func (s *MmctlE2ETestSuite) TestExportJobShowCmdF() { printer.Clean() err := exportJobShowCmdF(c, &cobra.Command{}, []string{model.NewId()}) - s.Require().ErrorContains(err, "failed to get export job: : Unable to get the job.") + s.Require().ErrorContains(err, "failed to get export job: Unable to get the job.") s.Require().Empty(printer.GetLines()) s.Require().Empty(printer.GetErrorLines()) }) @@ -328,7 +328,7 @@ func (s *MmctlE2ETestSuite) TestExportJobListCmdF() { cmd.Flags().Bool("all", false, "") err := exportJobListCmdF(s.th.Client, cmd, nil) - s.Require().EqualError(err, "failed to get jobs: : You do not have the appropriate permissions.") + s.Require().EqualError(err, "failed to get jobs: You do not have the appropriate permissions.") s.Require().Empty(printer.GetLines()) s.Require().Empty(printer.GetErrorLines()) }) @@ -401,7 +401,7 @@ func (s *MmctlE2ETestSuite) TestExportJobCancelCmdF() { time.Sleep(time.Millisecond) err := exportJobCancelCmdF(s.th.Client, cmd, []string{job.Id}) - s.Require().EqualError(err, "failed to get export job: : You do not have the appropriate permissions.") + s.Require().EqualError(err, "failed to get export job: You do not have the appropriate permissions.") s.Require().Empty(printer.GetLines()) s.Require().Empty(printer.GetErrorLines()) }) @@ -412,7 +412,7 @@ func (s *MmctlE2ETestSuite) TestExportJobCancelCmdF() { cmd := &cobra.Command{} err := exportJobCancelCmdF(c, cmd, []string{model.NewId()}) - s.Require().ErrorContains(err, "failed to get export job: : Unable to get the job.") + s.Require().ErrorContains(err, "failed to get export job: Unable to get the job.") s.Require().Empty(printer.GetLines()) s.Require().Empty(printer.GetErrorLines()) }) diff --git a/server/cmd/mmctl/commands/extract_e2e_test.go b/server/cmd/mmctl/commands/extract_e2e_test.go index 2b6798e7fc..983dcb30fd 100644 --- a/server/cmd/mmctl/commands/extract_e2e_test.go +++ b/server/cmd/mmctl/commands/extract_e2e_test.go @@ -31,7 +31,7 @@ func (s *MmctlE2ETestSuite) TestExtractRunCmdF() { err := extractRunCmdF(s.th.Client, cmd, []string{}) s.Require().NotNil(err) - s.Require().Equal("failed to create content extraction job: : You do not have the appropriate permissions.", err.Error()) + s.Require().Equal("failed to create content extraction job: You do not have the appropriate permissions.", err.Error()) s.Require().Empty(printer.GetLines()) s.Require().Empty(printer.GetErrorLines()) }) @@ -88,7 +88,7 @@ func (s *MmctlE2ETestSuite) TestExtractJobShowCmdF() { err := extractJobShowCmdF(s.th.Client, &cobra.Command{}, []string{job1.Id}) s.Require().NotNil(err) - s.Require().Equal("failed to get content extraction job: : You do not have the appropriate permissions.", err.Error()) + s.Require().Equal("failed to get content extraction job: You do not have the appropriate permissions.", err.Error()) s.Require().Empty(printer.GetLines()) s.Require().Empty(printer.GetErrorLines()) }) @@ -98,7 +98,7 @@ func (s *MmctlE2ETestSuite) TestExtractJobShowCmdF() { err := extractJobShowCmdF(c, &cobra.Command{}, []string{model.NewId()}) s.Require().NotNil(err) - s.Require().ErrorContains(err, "failed to get content extraction job: : Unable to get the job.") + s.Require().ErrorContains(err, "failed to get content extraction job: Unable to get the job.") s.Require().Empty(printer.GetLines()) s.Require().Empty(printer.GetErrorLines()) }) @@ -127,7 +127,7 @@ func (s *MmctlE2ETestSuite) TestExtractJobListCmdF() { err := extractJobListCmdF(s.th.Client, cmd, nil) s.Require().NotNil(err) - s.Require().Equal("failed to get jobs: : You do not have the appropriate permissions.", err.Error()) + s.Require().Equal("failed to get jobs: You do not have the appropriate permissions.", err.Error()) s.Require().Empty(printer.GetLines()) s.Require().Empty(printer.GetErrorLines()) }) diff --git a/server/cmd/mmctl/commands/group_e2e_test.go b/server/cmd/mmctl/commands/group_e2e_test.go index a359c0e6f5..ce5b1749dc 100644 --- a/server/cmd/mmctl/commands/group_e2e_test.go +++ b/server/cmd/mmctl/commands/group_e2e_test.go @@ -537,7 +537,7 @@ func (s *MmctlE2ETestSuite) TestUserGroupRestoreCmd() { s.th.RemovePermissionFromRole(model.PermissionRestoreCustomGroup.Id, model.SystemUserRoleId) err := userGroupRestoreCmdF(s.th.Client, &cobra.Command{}, []string{group.Id}) s.Require().NotNil(err) - s.Require().Equal(err.Error(), ": You do not have the appropriate permissions.") + s.Require().Equal(err.Error(), "You do not have the appropriate permissions.") s.th.AddPermissionToRole(model.PermissionRestoreCustomGroup.Id, model.SystemUserRoleId) err = userGroupRestoreCmdF(s.th.Client, &cobra.Command{}, []string{group.Id}) @@ -550,7 +550,7 @@ func (s *MmctlE2ETestSuite) TestUserGroupRestoreCmd() { printer.Clean() err = userGroupRestoreCmdF(s.th.Client, &cobra.Command{}, []string{group.Id}) s.Require().NotNil(err) - s.Require().Equal(err.Error(), ": no matching group found") + s.Require().Equal(err.Error(), "no matching group found") s.Require().Len(printer.GetLines(), 0) s.Require().Len(printer.GetErrorLines(), 0) }) diff --git a/server/cmd/mmctl/commands/import_e2e_test.go b/server/cmd/mmctl/commands/import_e2e_test.go index 6af9df9183..3bed4e4a9c 100644 --- a/server/cmd/mmctl/commands/import_e2e_test.go +++ b/server/cmd/mmctl/commands/import_e2e_test.go @@ -27,7 +27,7 @@ func (s *MmctlE2ETestSuite) TestImportUploadCmdF() { err := importUploadCmdF(s.th.Client, &cobra.Command{}, []string{importFilePath}) s.Require().NotNil(err) - s.Require().Equal("failed to create upload session: : You do not have the appropriate permissions.", err.Error()) + s.Require().Equal("failed to create upload session: You do not have the appropriate permissions.", err.Error()) s.Require().Empty(printer.GetLines()) s.Require().Empty(printer.GetErrorLines()) }) @@ -98,7 +98,7 @@ func (s *MmctlE2ETestSuite) TestImportProcessCmdF() { err := importProcessCmdF(s.th.Client, &cobra.Command{}, []string{"importName"}) s.Require().NotNil(err) - s.Require().Equal("failed to create import process job: : You do not have the appropriate permissions.", err.Error()) + s.Require().Equal("failed to create import process job: You do not have the appropriate permissions.", err.Error()) s.Require().Empty(printer.GetLines()) s.Require().Empty(printer.GetErrorLines()) }) @@ -138,7 +138,7 @@ func (s *MmctlE2ETestSuite) TestImportListAvailableCmdF() { err := importListAvailableCmdF(s.th.Client, &cobra.Command{}, nil) s.Require().NotNil(err) - s.Require().ErrorContains(err, "failed to list imports: : You do not have the appropriate permissions.") + s.Require().ErrorContains(err, "failed to list imports: You do not have the appropriate permissions.") s.Require().Empty(printer.GetLines()) s.Require().Empty(printer.GetErrorLines()) }) @@ -268,7 +268,7 @@ func (s *MmctlE2ETestSuite) TestImportJobShowCmdF() { err := importJobShowCmdF(s.th.Client, &cobra.Command{}, []string{job1.Id}) s.Require().NotNil(err) - s.Require().ErrorContains(err, "failed to get import job: : You do not have the appropriate permissions.") + s.Require().ErrorContains(err, "failed to get import job: You do not have the appropriate permissions.") s.Require().Empty(printer.GetLines()) s.Require().Empty(printer.GetErrorLines()) }) @@ -278,7 +278,7 @@ func (s *MmctlE2ETestSuite) TestImportJobShowCmdF() { err := importJobShowCmdF(c, &cobra.Command{}, []string{model.NewId()}) s.Require().NotNil(err) - s.Require().ErrorContains(err, "failed to get import job: : Unable to get the job.") + s.Require().ErrorContains(err, "failed to get import job: Unable to get the job.") s.Require().Empty(printer.GetLines()) s.Require().Empty(printer.GetErrorLines()) }) @@ -307,7 +307,7 @@ func (s *MmctlE2ETestSuite) TestImportJobListCmdF() { err := importJobListCmdF(s.th.Client, cmd, nil) s.Require().NotNil(err) - s.Require().ErrorContains(err, "failed to get jobs: : You do not have the appropriate permissions.") + s.Require().ErrorContains(err, "failed to get jobs: You do not have the appropriate permissions.") s.Require().Empty(printer.GetLines()) s.Require().Empty(printer.GetErrorLines()) }) diff --git a/server/cmd/mmctl/commands/plugin_e2e_test.go b/server/cmd/mmctl/commands/plugin_e2e_test.go index 21fee105a5..e881a957e0 100644 --- a/server/cmd/mmctl/commands/plugin_e2e_test.go +++ b/server/cmd/mmctl/commands/plugin_e2e_test.go @@ -199,7 +199,7 @@ func (s *MmctlE2ETestSuite) TestPluginInstallURLCmd() { defer removePluginIfInstalled(s.th.Client, s, jiraPluginID) var expected error - expected = multierror.Append(expected, errors.New(": You do not have the appropriate permissions.")) //nolint:revive + expected = multierror.Append(expected, errors.New("You do not have the appropriate permissions.")) //nolint:revive err := pluginInstallURLCmdF(s.th.Client, &cobra.Command{}, []string{jiraURL}) s.Require().EqualError(err, expected.Error()) s.Require().Len(printer.GetLines(), 0) @@ -218,7 +218,7 @@ func (s *MmctlE2ETestSuite) TestPluginInstallURLCmd() { const pluginURL = "https://plugins-store.test.mattermost.com/release/mattermost-nonexistent-plugin-v2.0.0.tar.gz" var expected error - expected = multierror.Append(expected, errors.New(": An error occurred while downloading the plugin.")) //nolint:revive + expected = multierror.Append(expected, errors.New("An error occurred while downloading the plugin.")) //nolint:revive err := pluginInstallURLCmdF(c, &cobra.Command{}, []string{pluginURL}) s.Require().EqualError(err, expected.Error()) @@ -244,7 +244,7 @@ func (s *MmctlE2ETestSuite) TestPluginInstallURLCmd() { s.Require().Equal(jiraPluginID, printer.GetLines()[0].(*model.Manifest).Id) var expected error - expected = multierror.Append(expected, errors.New(": Unable to install plugin. A plugin with the same ID is already installed.")) //nolint:revive + expected = multierror.Append(expected, errors.New("Unable to install plugin. A plugin with the same ID is already installed.")) //nolint:revive err = pluginInstallURLCmdF(c, &cobra.Command{}, []string{jiraURL}) s.Require().EqualError(err, expected.Error()) s.Require().Len(printer.GetLines(), 1) diff --git a/server/cmd/mmctl/commands/plugin_marketplace_e2e_test.go b/server/cmd/mmctl/commands/plugin_marketplace_e2e_test.go index 3c8ede33e6..6806e64f5c 100644 --- a/server/cmd/mmctl/commands/plugin_marketplace_e2e_test.go +++ b/server/cmd/mmctl/commands/plugin_marketplace_e2e_test.go @@ -119,7 +119,7 @@ func (s *MmctlE2ETestSuite) TestPluginMarketplaceListCmd() { err := pluginMarketplaceListCmdF(s.th.Client, &cobra.Command{}, nil) - s.Require().ErrorContains(err, "Failed to fetch plugins: : You do not have the appropriate permissions.") + s.Require().ErrorContains(err, "Failed to fetch plugins: You do not have the appropriate permissions.") s.Require().Empty(printer.GetErrorLines()) s.Require().Empty(printer.GetLines()) }) diff --git a/server/cmd/mmctl/commands/team_e2e_test.go b/server/cmd/mmctl/commands/team_e2e_test.go index ce6004fafc..a37e1899d4 100644 --- a/server/cmd/mmctl/commands/team_e2e_test.go +++ b/server/cmd/mmctl/commands/team_e2e_test.go @@ -55,7 +55,7 @@ func (s *MmctlE2ETestSuite) TestRenameTeamCmdF() { err := renameTeamCmdF(s.th.Client, cmd, args) s.Require().Error(err) s.Len(printer.GetLines(), 0) - s.ErrorContains(err, "Cannot rename team '"+s.th.BasicTeam.Name+"', error : : You do not have the appropriate permissions.") + s.ErrorContains(err, "Cannot rename team '"+s.th.BasicTeam.Name+"', error : You do not have the appropriate permissions.") }) } @@ -86,7 +86,7 @@ func (s *MmctlE2ETestSuite) TestDeleteTeamsCmdF() { _ = deleteTeamsCmdF(s.th.Client, cmd, args) s.Len(printer.GetLines(), 0) s.Len(printer.GetErrorLines(), 1) - s.Require().Equal("Unable to delete team '"+s.th.BasicTeam.Name+"' error: : You do not have the appropriate permissions.", printer.GetErrorLines()[0]) + s.Require().Equal("Unable to delete team '"+s.th.BasicTeam.Name+"' error: You do not have the appropriate permissions.", printer.GetErrorLines()[0]) team, _ := s.th.App.GetTeam(s.th.BasicTeam.Id) s.Equal(team.Name, s.th.BasicTeam.Name) }) @@ -140,7 +140,7 @@ func (s *MmctlE2ETestSuite) TestDeleteTeamsCmdF() { s.Require().Error(err) s.Len(printer.GetLines(), 0) s.Len(printer.GetErrorLines(), 1) - s.Equal("Unable to delete team '"+s.th.BasicTeam.Name+"' error: : Permanent team deletion feature is not enabled. Please contact your System Administrator.", printer.GetErrorLines()[0]) + s.Equal("Unable to delete team '"+s.th.BasicTeam.Name+"' error: Permanent team deletion feature is not enabled. Please contact your System Administrator.", printer.GetErrorLines()[0]) // verify team still exists team, _ := s.th.App.GetTeam(s.th.BasicTeam.Id) @@ -185,7 +185,7 @@ func (s *MmctlE2ETestSuite) TestModifyTeamsCmdF() { s.Require().NoError(err) s.Require().Contains( printer.GetErrorLines()[0], - fmt.Sprintf("Unable to modify team '%s' error: : You do not have the appropriate permissions.", s.th.BasicTeam.Name), + fmt.Sprintf("Unable to modify team '%s' error: You do not have the appropriate permissions.", s.th.BasicTeam.Name), ) t, appErr := s.th.App.GetTeam(teamID) s.Require().Nil(appErr) @@ -202,7 +202,7 @@ func (s *MmctlE2ETestSuite) TestModifyTeamsCmdF() { s.Require().NoError(err) s.Require().Contains( printer.GetErrorLines()[0], - fmt.Sprintf("Unable to modify team '%s' error: : You do not have the appropriate permissions.", s.th.BasicTeam.Name), + fmt.Sprintf("Unable to modify team '%s' error: You do not have the appropriate permissions.", s.th.BasicTeam.Name), ) t, appErr := s.th.App.GetTeam(teamID) s.Require().Nil(appErr) diff --git a/server/cmd/mmctl/commands/token_e2e_test.go b/server/cmd/mmctl/commands/token_e2e_test.go index 85da6d9964..8f3579ec10 100644 --- a/server/cmd/mmctl/commands/token_e2e_test.go +++ b/server/cmd/mmctl/commands/token_e2e_test.go @@ -70,7 +70,7 @@ func (s *MmctlE2ETestSuite) TestTokenGenerateForUserCmd() { s.Require().Len(printer.GetErrorLines(), 0) s.Require().ErrorContains( err, - fmt.Sprintf(`could not create token for %q: : You do not have the appropriate permissions.`, user.Email), + fmt.Sprintf(`could not create token for %q: You do not have the appropriate permissions.`, user.Email), ) userTokens, appErr := s.th.App.GetUserAccessTokensForUser(user.Id, 0, 1) s.Require().Nil(appErr) diff --git a/server/cmd/mmctl/commands/user_e2e_test.go b/server/cmd/mmctl/commands/user_e2e_test.go index 8fce57b9c6..e66b5946c2 100644 --- a/server/cmd/mmctl/commands/user_e2e_test.go +++ b/server/cmd/mmctl/commands/user_e2e_test.go @@ -242,7 +242,7 @@ func (s *MmctlE2ETestSuite) TestUserInviteCmdf() { s.Require().Len(printer.GetLines(), 0) s.Require().Len(printer.GetErrorLines(), 1) s.Require().Equal( - fmt.Sprintf("Unable to invite user with email %s to team %s. Error: : Email invitations are disabled.", + fmt.Sprintf("Unable to invite user with email %s to team %s. Error: Email invitations are disabled.", s.th.BasicUser.Email, s.th.BasicTeam.Name, ), @@ -270,7 +270,7 @@ func (s *MmctlE2ETestSuite) TestUserInviteCmdf() { s.Require().Len(printer.GetLines(), 0) s.Require().Len(printer.GetErrorLines(), 1) s.Require().Equal( - fmt.Sprintf(`Unable to invite user with email %s to team %s. Error: : The following email addresses do not belong to an accepted domain: %s. Please contact your System Administrator for details.`, + fmt.Sprintf(`Unable to invite user with email %s to team %s. Error: The following email addresses do not belong to an accepted domain: %s. Please contact your System Administrator for details.`, user.Email, team.Name, user.Email, @@ -337,7 +337,7 @@ func (s *MmctlE2ETestSuite) TestResetUserMfaCmd() { var expected error expected = multierror.Append( - expected, fmt.Errorf(`unable to reset user %q MFA. Error: : You do not have the appropriate permissions.`, user.Id), //nolint:revive + expected, fmt.Errorf(`unable to reset user %q MFA. Error: You do not have the appropriate permissions.`, user.Id), //nolint:revive ) @@ -368,7 +368,7 @@ func (s *MmctlE2ETestSuite) TestVerifyUserEmailWithoutTokenCmd() { var expected error expected = multierror.Append( - expected, fmt.Errorf("unable to verify user "+user.Id+" email: : You do not have the appropriate permissions."), + expected, fmt.Errorf("unable to verify user "+user.Id+" email: You do not have the appropriate permissions."), ) s.Require().EqualError(err, expected.Error()) @@ -452,7 +452,7 @@ func (s *MmctlE2ETestSuite) TestCreateUserCmd() { cmd.Flags().Bool("system-admin", true, "") err := userCreateCmdF(s.th.Client, cmd, []string{}) - s.EqualError(err, "Unable to update user roles. Error: : You do not have the appropriate permissions.") + s.EqualError(err, "Unable to update user roles. Error: You do not have the appropriate permissions.") s.Require().Empty(printer.GetLines()) user, err := s.th.App.GetUserByEmail(email) s.Require().Nil(err) @@ -541,7 +541,7 @@ func (s *MmctlE2ETestSuite) TestUpdateUserEmailCmd() { printer.Clean() newEmail := "basicuser2-change@fakedomain.com" err := updateUserEmailCmdF(s.th.Client, &cobra.Command{}, []string{s.th.BasicUser2.Id, newEmail}) - s.Require().EqualError(err, ": You do not have the appropriate permissions.") + s.Require().EqualError(err, "You do not have the appropriate permissions.") u, err := s.th.App.GetUser(s.th.BasicUser2.Id) s.Require().Nil(err) @@ -553,7 +553,7 @@ func (s *MmctlE2ETestSuite) TestUpdateUserEmailCmd() { newEmail := "basicuser-change@fakedomain.com" err := updateUserEmailCmdF(s.th.Client, &cobra.Command{}, []string{s.th.BasicUser.Id, newEmail}) - s.Require().EqualError(err, ": Invalid or missing password in request body.") + s.Require().EqualError(err, "Invalid or missing password in request body.") }) } @@ -580,7 +580,7 @@ func (s *MmctlE2ETestSuite) TestUpdateUsernameCmd() { printer.Clean() newUsername := "basicusernamechange" err := updateUsernameCmdF(s.th.Client, &cobra.Command{}, []string{s.th.BasicUser2.Id, newUsername}) - s.Require().EqualError(err, ": You do not have the appropriate permissions.") + s.Require().EqualError(err, "You do not have the appropriate permissions.") u, err := s.th.App.GetUser(s.th.BasicUser2.Id) s.Require().Nil(err) @@ -675,7 +675,7 @@ func (s *MmctlE2ETestSuite) TestDeleteUsersCmd() { s.Require().Nil(err) s.Len(printer.GetLines(), 0) s.Len(printer.GetErrorLines(), 1) - s.Require().Equal(fmt.Sprintf("Unable to delete user '%s' error: : You do not have the appropriate permissions.", newUser.Username), printer.GetErrorLines()[0]) + s.Require().Equal(fmt.Sprintf("Unable to delete user '%s' error: You do not have the appropriate permissions.", newUser.Username), printer.GetErrorLines()[0]) // expect user not deleted user, err := s.th.App.GetUser(newUser.Id) @@ -701,7 +701,7 @@ func (s *MmctlE2ETestSuite) TestDeleteUsersCmd() { s.Require().Nil(err) s.Len(printer.GetLines(), 0) s.Len(printer.GetErrorLines(), 1) - s.Require().Equal(fmt.Sprintf("Unable to delete user '%s' error: : Permanent user deletion feature is not enabled. Please contact your System Administrator.", newUser.Username), printer.GetErrorLines()[0]) + s.Require().Equal(fmt.Sprintf("Unable to delete user '%s' error: Permanent user deletion feature is not enabled. Please contact your System Administrator.", newUser.Username), printer.GetErrorLines()[0]) // expect user not deleted user, err := s.th.App.GetUser(newUser.Id) @@ -793,7 +793,7 @@ func (s *MmctlE2ETestSuite) TestUserConvertCmdF() { _ = userConvertCmdF(s.th.Client, cmd, []string{email}) s.Require().Len(printer.GetLines(), 0) s.Require().Len(printer.GetErrorLines(), 1) - s.Equal(": You do not have the appropriate permissions.", printer.GetErrorLines()[0]) + s.Equal("You do not have the appropriate permissions.", printer.GetErrorLines()[0]) }) s.RunForSystemAdminAndLocal("Valid bot to user convert", func(c client.Client) { @@ -826,7 +826,7 @@ func (s *MmctlE2ETestSuite) TestUserConvertCmdF() { err := userConvertCmdF(s.th.Client, cmd, []string{bot.Username}) s.Require().Error(err) - s.EqualError(err, ": You do not have the appropriate permissions.") + s.EqualError(err, "You do not have the appropriate permissions.") s.Require().Len(printer.GetLines(), 0) s.Require().Len(printer.GetErrorLines(), 0) }) @@ -940,7 +940,7 @@ func (s *MmctlE2ETestSuite) TestPromoteGuestToUserCmd() { s.Require().Nil(err) s.Require().Len(printer.GetLines(), 0) s.Require().Len(printer.GetErrorLines(), 1) - s.Require().Equal(fmt.Sprintf("unable to promote guest %s: %s", user.Email, ": You do not have the appropriate permissions."), printer.GetErrorLines()[0]) + s.Require().Equal(fmt.Sprintf("unable to promote guest %s: You do not have the appropriate permissions.", user.Email), printer.GetErrorLines()[0]) }) } @@ -970,7 +970,7 @@ func (s *MmctlE2ETestSuite) TestDemoteUserToGuestCmd() { s.Require().NotNil(err) s.Require().Len(printer.GetLines(), 0) s.Require().Len(printer.GetErrorLines(), 1) - s.Require().Equal(fmt.Sprintf("unable to demote user %s: %s", user.Email, ": You do not have the appropriate permissions."), printer.GetErrorLines()[0]) + s.Require().Equal(fmt.Sprintf("unable to demote user %s: You do not have the appropriate permissions.", user.Email), printer.GetErrorLines()[0]) }) } diff --git a/server/public/model/permission.go b/server/public/model/permission.go index db68995d64..ad34ae8760 100644 --- a/server/public/model/permission.go +++ b/server/public/model/permission.go @@ -3,6 +3,10 @@ package model +import ( + "net/http" +) + const ( PermissionScopeSystem = "system_scope" PermissionScopeTeam = "team_scope" @@ -2455,3 +2459,14 @@ func initializePermissions() { func init() { initializePermissions() } + +func MakePermissionError(s *Session, permissions []*Permission) *AppError { + permissionsStr := "permission=" + for i, permission := range permissions { + permissionsStr += permission.Id + if i != len(permissions)-1 { + permissionsStr += "," + } + } + return NewAppError("Permissions", "api.context.permissions.app_error", nil, "userId="+s.UserId+", "+permissionsStr, http.StatusForbidden) +} diff --git a/server/public/model/permission_test.go b/server/public/model/permission_test.go new file mode 100644 index 0000000000..8a6beeebf4 --- /dev/null +++ b/server/public/model/permission_test.go @@ -0,0 +1,53 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +package model + +import ( + "fmt" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestMakePermissionError(t *testing.T) { + userID := NewId() + for name, tc := range map[string]struct { + s *Session + permissions []*Permission + expectedError string + }{ + "nil permissions, nil session": { + s: &Session{}, + permissions: nil, + expectedError: "Permissions: api.context.permissions.app_error, userId=, permission=", + }, + "nil permissions": { + s: &Session{UserId: userID}, + permissions: nil, + expectedError: fmt.Sprintf("Permissions: api.context.permissions.app_error, userId=%s, permission=", userID), + }, + "empty permissions": { + s: &Session{UserId: userID}, + permissions: []*Permission{}, + expectedError: fmt.Sprintf("Permissions: api.context.permissions.app_error, userId=%s, permission=", userID), + }, + "one permission": { + s: &Session{UserId: userID}, + permissions: []*Permission{PermissionManageSystem}, + expectedError: fmt.Sprintf("Permissions: api.context.permissions.app_error, userId=%s, permission=manage_system", userID), + }, + "two permissions": { + s: &Session{UserId: userID}, + permissions: []*Permission{PermissionManageSystem, PermissionAssignSystemAdminRole}, + expectedError: fmt.Sprintf("Permissions: api.context.permissions.app_error, userId=%s, permission=manage_system,assign_system_admin_role", userID), + }, + } { + t.Run(name, func(t *testing.T) { + appErr := MakePermissionError(tc.s, tc.permissions) + require.NotNil(t, appErr) + assert.Equal(t, tc.expectedError, appErr.Error()) + }) + } +} diff --git a/server/public/model/utils.go b/server/public/model/utils.go index 347cbaf09f..01559feabf 100644 --- a/server/public/model/utils.go +++ b/server/public/model/utils.go @@ -246,8 +246,11 @@ func (er *AppError) Error() string { var sb strings.Builder // render the error information - sb.WriteString(er.Where) - sb.WriteString(": ") + if er.Where != "" { + sb.WriteString(er.Where) + sb.WriteString(": ") + } + if er.Message != NoTranslation { sb.WriteString(er.Message) } diff --git a/server/public/model/utils_test.go b/server/public/model/utils_test.go index bea7b55b9d..d2ac34dca3 100644 --- a/server/public/model/utils_test.go +++ b/server/public/model/utils_test.go @@ -97,6 +97,11 @@ func TestAppErrorRender(t *testing.T) { assert.EqualError(t, aerr, "here: message") }) + t.Run("Without where", func(t *testing.T) { + aerr := NewAppError("", "message", nil, "details", http.StatusTeapot) + assert.EqualError(t, aerr, "message, details") + }) + t.Run("Detailed", func(t *testing.T) { aerr := NewAppError("here", "message", nil, "details", http.StatusTeapot) assert.EqualError(t, aerr, "here: message, details")