Merge branch 'master' into mpa-playbooks

Этот коммит содержится в:
Giorgi Bochorishvili
2023-01-05 12:23:26 +04:00
родитель 084c30bbc1 6b41f914cc
Коммит bc304ef9ef
33 изменённых файлов: 597 добавлений и 396 удалений

Просмотреть файл

@@ -21,6 +21,10 @@ executors:
jobs:
setup-multi-product-repositories:
parameters:
target-branch:
type: string
default: '$(curl -s -H "Authorization: token ${GITHUB_TOKEN}" $(echo https://api.github.com/repos/${CIRCLE_PULL_REQUEST:19} | sed "s/\/pull\//\/pulls\//") | jq ".base.ref" | tr -d "\042" )'
working_directory: /mnt/ramdisk/mattermost-server
docker:
- image: cimg/go:1.18
@@ -31,7 +35,7 @@ jobs:
cd ..
git clone --depth=1 --no-single-branch https://github.com/mattermost/focalboard.git
cd focalboard
git checkout $CIRCLE_BRANCH || git checkout rolling-stable
git checkout $CIRCLE_BRANCH || git checkout <<parameters.target-branch>> || git checkout rolling-stable
echo $(git rev-parse HEAD)
cd ../mattermost-server
make setup-go-work
@@ -487,6 +491,8 @@ workflows:
untagged-build:
jobs:
- setup-multi-product-repositories:
context:
- matterbuild-github-token
filters:
branches:
ignore:
@@ -652,6 +658,8 @@ workflows:
release-build:
jobs:
- setup-multi-product-repositories:
context:
- matterbuild-github-token
filters:
branches:
only:

Просмотреть файл

@@ -8,7 +8,6 @@ import (
"encoding/json"
"fmt"
"net/http"
"os"
"sort"
"strings"
"sync"
@@ -4584,8 +4583,6 @@ func TestViewChannelWithoutCollapsedThreads(t *testing.T) {
th := Setup(t).InitBasic()
defer th.TearDown()
os.Setenv("MM_FEATUREFLAGS_COLLAPSEDTHREADS", "true")
defer os.Unsetenv("MM_FEATUREFLAGS_COLLAPSEDTHREADS")
th.App.UpdateConfig(func(cfg *model.Config) {
*cfg.ServiceSettings.ThreadAutoFollow = true
*cfg.ServiceSettings.CollapsedThreads = model.CollapsedThreadsDefaultOn

Просмотреть файл

@@ -124,7 +124,6 @@ func deleteDraft(c *Context, w http.ResponseWriter, r *http.Request) {
switch {
case err.StatusCode == http.StatusNotFound:
// If the draft doesn't exist in the server, we don't need to delete.
mlog.Debug("Unable to find the draft", mlog.Err(err))
ReturnStatusOK(w)
default:
c.Err = err

Просмотреть файл

@@ -12,7 +12,6 @@ import (
"net/http"
"net/http/httptest"
"net/url"
"os"
"reflect"
"sort"
"strings"
@@ -2954,8 +2953,6 @@ func TestSetChannelUnread(t *testing.T) {
}
func TestSetPostUnreadWithoutCollapsedThreads(t *testing.T) {
os.Setenv("MM_FEATUREFLAGS_COLLAPSEDTHREADS", "true")
defer os.Unsetenv("MM_FEATUREFLAGS_COLLAPSEDTHREADS")
th := Setup(t).InitBasic()
defer th.TearDown()
th.App.UpdateConfig(func(cfg *model.Config) {

Просмотреть файл

@@ -2017,9 +2017,15 @@ func loginCWS(c *Context, w http.ResponseWriter, r *http.Request) {
redirectURL := *c.App.Config().ServiceSettings.SiteURL
if campaign != "" {
if url, ok := campaignToURL[campaign]; ok {
properties := map[string]any{
"category": "acquisition",
"redirect_to": strings.TrimSuffix(url, "/"),
}
c.App.Srv().GetTelemetryService().SendTelemetry("product_start_redirect", properties)
redirectURL += url
}
}
http.Redirect(w, r, redirectURL, http.StatusFound)
}

Просмотреть файл

@@ -5794,8 +5794,6 @@ func TestUpdatePassword(t *testing.T) {
func TestGetThreadsForUser(t *testing.T) {
os.Setenv("MM_FEATUREFLAGS_POSTPRIORITY", "true")
defer os.Unsetenv("MM_FEATUREFLAGS_POSTPRIORITY")
os.Setenv("MM_FEATUREFLAGS_COLLAPSEDTHREADS", "true")
defer os.Unsetenv("MM_FEATUREFLAGS_COLLAPSEDTHREADS")
th := Setup(t).InitBasic()
defer th.TearDown()
@@ -6151,8 +6149,6 @@ func TestGetThreadsForUser(t *testing.T) {
func TestThreadSocketEvents(t *testing.T) {
th := Setup(t).InitBasic()
defer th.TearDown()
os.Setenv("MM_FEATUREFLAGS_COLLAPSEDTHREADS", "true")
defer os.Unsetenv("MM_FEATUREFLAGS_COLLAPSEDTHREADS")
th.ConfigStore.SetReadOnlyFF(false)
defer th.ConfigStore.SetReadOnlyFF(true)
@@ -6533,8 +6529,6 @@ func TestMaintainUnreadRepliesInThread(t *testing.T) {
defer th.UnlinkUserFromTeam(th.SystemAdminUser, th.BasicTeam)
th.AddUserToChannel(th.SystemAdminUser, th.BasicChannel)
defer th.RemoveUserFromChannel(th.SystemAdminUser, th.BasicChannel)
os.Setenv("MM_FEATUREFLAGS_COLLAPSEDTHREADS", "true")
defer os.Unsetenv("MM_FEATUREFLAGS_COLLAPSEDTHREADS")
th.App.UpdateConfig(func(cfg *model.Config) {
*cfg.ServiceSettings.ThreadAutoFollow = true
*cfg.ServiceSettings.CollapsedThreads = model.CollapsedThreadsDefaultOn
@@ -6590,8 +6584,7 @@ func TestMaintainUnreadRepliesInThread(t *testing.T) {
func TestThreadCounts(t *testing.T) {
th := Setup(t).InitBasic()
defer th.TearDown()
os.Setenv("MM_FEATUREFLAGS_COLLAPSEDTHREADS", "true")
defer os.Unsetenv("MM_FEATUREFLAGS_COLLAPSEDTHREADS")
th.App.UpdateConfig(func(cfg *model.Config) {
*cfg.ServiceSettings.ThreadAutoFollow = true
*cfg.ServiceSettings.CollapsedThreads = model.CollapsedThreadsDefaultOn
@@ -6633,8 +6626,6 @@ func TestThreadCounts(t *testing.T) {
func TestSingleThreadGet(t *testing.T) {
os.Setenv("MM_FEATUREFLAGS_POSTPRIORITY", "true")
defer os.Unsetenv("MM_FEATUREFLAGS_POSTPRIORITY")
os.Setenv("MM_FEATUREFLAGS_COLLAPSEDTHREADS", "true")
defer os.Unsetenv("MM_FEATUREFLAGS_COLLAPSEDTHREADS")
th := Setup(t).InitBasic()
defer th.TearDown()
@@ -6704,8 +6695,7 @@ func TestMaintainUnreadMentionsInThread(t *testing.T) {
th.AddUserToChannel(th.SystemAdminUser, th.BasicChannel)
defer th.RemoveUserFromChannel(th.SystemAdminUser, th.BasicChannel)
client := th.Client
os.Setenv("MM_FEATUREFLAGS_COLLAPSEDTHREADS", "true")
defer os.Unsetenv("MM_FEATUREFLAGS_COLLAPSEDTHREADS")
th.App.UpdateConfig(func(cfg *model.Config) {
*cfg.ServiceSettings.ThreadAutoFollow = true
*cfg.ServiceSettings.CollapsedThreads = model.CollapsedThreadsDefaultOn
@@ -6768,8 +6758,7 @@ func TestMaintainUnreadMentionsInThread(t *testing.T) {
func TestReadThreads(t *testing.T) {
th := Setup(t).InitBasic()
defer th.TearDown()
os.Setenv("MM_FEATUREFLAGS_COLLAPSEDTHREADS", "true")
defer os.Unsetenv("MM_FEATUREFLAGS_COLLAPSEDTHREADS")
th.App.UpdateConfig(func(cfg *model.Config) {
*cfg.ServiceSettings.ThreadAutoFollow = true
*cfg.ServiceSettings.CollapsedThreads = model.CollapsedThreadsDefaultOn
@@ -6872,8 +6861,7 @@ func TestReadThreads(t *testing.T) {
func TestMarkThreadUnreadMentionCount(t *testing.T) {
th := Setup(t).InitBasic()
defer th.TearDown()
os.Setenv("MM_FEATUREFLAGS_COLLAPSEDTHREADS", "true")
defer os.Unsetenv("MM_FEATUREFLAGS_COLLAPSEDTHREADS")
th.App.UpdateConfig(func(cfg *model.Config) {
*cfg.ServiceSettings.ThreadAutoFollow = true
*cfg.ServiceSettings.CollapsedThreads = model.CollapsedThreadsDefaultOn

Просмотреть файл

@@ -8,7 +8,6 @@ import (
"errors"
"fmt"
"net/http"
"os"
"sort"
"strings"
"sync"
@@ -2127,8 +2126,7 @@ func TestViewChannelCollapsedThreadsTurnedOff(t *testing.T) {
th.AddUserToChannel(u2, c1)
// Enable CRT
os.Setenv("MM_FEATUREFLAGS_COLLAPSEDTHREADS", "true")
defer os.Unsetenv("MM_FEATUREFLAGS_COLLAPSEDTHREADS")
th.App.UpdateConfig(func(cfg *model.Config) {
*cfg.ServiceSettings.ThreadAutoFollow = true
*cfg.ServiceSettings.CollapsedThreads = model.CollapsedThreadsDefaultOn
@@ -2198,8 +2196,6 @@ func TestViewChannelCollapsedThreadsTurnedOff(t *testing.T) {
func TestMarkChannelAsUnreadFromPostCollapsedThreadsTurnedOff(t *testing.T) {
// Enable CRT
os.Setenv("MM_FEATUREFLAGS_COLLAPSEDTHREADS", "true")
defer os.Unsetenv("MM_FEATUREFLAGS_COLLAPSEDTHREADS")
th := Setup(t).InitBasic()
defer th.TearDown()
@@ -2286,8 +2282,7 @@ func TestMarkChannelAsUnreadFromPostCollapsedThreadsTurnedOff(t *testing.T) {
}
func TestMarkUnreadCRTOffUpdatesThreads(t *testing.T) {
os.Setenv("MM_FEATUREFLAGS_COLLAPSEDTHREADS", "true")
defer os.Unsetenv("MM_FEATUREFLAGS_COLLAPSEDTHREADS")
th := Setup(t).InitBasic()
defer th.TearDown()
th.App.UpdateConfig(func(cfg *model.Config) {

Просмотреть файл

@@ -46,7 +46,7 @@ func (s *Server) doAdvancedPermissionsMigration() {
// If this failed for reasons other than the role already existing, don't mark the migration as done.
fetchedRole, err := s.Store().Role().GetByName(context.Background(), role.Name)
if err != nil {
mlog.Critical("Failed to migrate role to database.", mlog.Err(err))
mlog.Fatal("Failed to migrate role to database.", mlog.Err(err))
allSucceeded = false
continue
}
@@ -59,7 +59,7 @@ func (s *Server) doAdvancedPermissionsMigration() {
role.Id = fetchedRole.Id
if _, err = s.Store().Role().Save(role); err != nil {
// Role is not the same, but failed to update.
mlog.Critical("Failed to migrate role to database.", mlog.Err(err))
mlog.Fatal("Failed to migrate role to database.", mlog.Err(err))
allSucceeded = false
}
}
@@ -81,7 +81,7 @@ func (s *Server) doAdvancedPermissionsMigration() {
}
if err := s.Store().System().Save(&system); err != nil {
mlog.Critical("Failed to mark advanced permissions migration as completed.", mlog.Err(err))
mlog.Fatal("Failed to mark advanced permissions migration as completed.", mlog.Err(err))
}
}
@@ -114,21 +114,21 @@ func (s *Server) doEmojisPermissionsMigration() {
// Emoji creation is set to all by default
role, err = s.GetRoleByName(context.Background(), model.SystemUserRoleId)
if err != nil {
mlog.Critical("Failed to migrate emojis creation permissions from mattermost config.", mlog.Err(err))
mlog.Fatal("Failed to migrate emojis creation permissions from mattermost config.", mlog.Err(err))
return
}
if role != nil {
role.Permissions = append(role.Permissions, model.PermissionCreateEmojis.Id, model.PermissionDeleteEmojis.Id)
if _, nErr := s.Store().Role().Save(role); nErr != nil {
mlog.Critical("Failed to migrate emojis creation permissions from mattermost config.", mlog.Err(nErr))
mlog.Fatal("Failed to migrate emojis creation permissions from mattermost config.", mlog.Err(nErr))
return
}
}
systemAdminRole, err = s.GetRoleByName(context.Background(), model.SystemAdminRoleId)
if err != nil {
mlog.Critical("Failed to migrate emojis creation permissions from mattermost config.", mlog.Err(err))
mlog.Fatal("Failed to migrate emojis creation permissions from mattermost config.", mlog.Err(err))
return
}
@@ -138,7 +138,7 @@ func (s *Server) doEmojisPermissionsMigration() {
model.PermissionDeleteOthersEmojis.Id,
)
if _, err := s.Store().Role().Save(systemAdminRole); err != nil {
mlog.Critical("Failed to migrate emojis creation permissions from mattermost config.", mlog.Err(err))
mlog.Fatal("Failed to migrate emojis creation permissions from mattermost config.", mlog.Err(err))
return
}
@@ -148,7 +148,7 @@ func (s *Server) doEmojisPermissionsMigration() {
}
if err := s.Store().System().Save(&system); err != nil {
mlog.Critical("Failed to mark emojis permissions migration as completed.", mlog.Err(err))
mlog.Fatal("Failed to mark emojis permissions migration as completed.", mlog.Err(err))
}
}
@@ -167,26 +167,26 @@ func (s *Server) doGuestRolesCreationMigration() {
allSucceeded := true
if _, err := s.Store().Role().GetByName(context.Background(), model.ChannelGuestRoleId); err != nil {
if _, err := s.Store().Role().Save(roles[model.ChannelGuestRoleId]); err != nil {
mlog.Critical("Failed to create new guest role to database.", mlog.Err(err))
mlog.Fatal("Failed to create new guest role to database.", mlog.Err(err))
allSucceeded = false
}
}
if _, err := s.Store().Role().GetByName(context.Background(), model.TeamGuestRoleId); err != nil {
if _, err := s.Store().Role().Save(roles[model.TeamGuestRoleId]); err != nil {
mlog.Critical("Failed to create new guest role to database.", mlog.Err(err))
mlog.Fatal("Failed to create new guest role to database.", mlog.Err(err))
allSucceeded = false
}
}
if _, err := s.Store().Role().GetByName(context.Background(), model.SystemGuestRoleId); err != nil {
if _, err := s.Store().Role().Save(roles[model.SystemGuestRoleId]); err != nil {
mlog.Critical("Failed to create new guest role to database.", mlog.Err(err))
mlog.Fatal("Failed to create new guest role to database.", mlog.Err(err))
allSucceeded = false
}
}
schemes, err := s.Store().Scheme().GetAllPage("", 0, 1000000)
if err != nil {
mlog.Critical("Failed to get all schemes.", mlog.Err(err))
mlog.Fatal("Failed to get all schemes.", mlog.Err(err))
allSucceeded = false
}
for _, scheme := range schemes {
@@ -201,7 +201,7 @@ func (s *Server) doGuestRolesCreationMigration() {
}
if savedRole, err := s.Store().Role().Save(teamGuestRole); err != nil {
mlog.Critical("Failed to create new guest role for custom scheme.", mlog.Err(err))
mlog.Fatal("Failed to create new guest role for custom scheme.", mlog.Err(err))
allSucceeded = false
} else {
scheme.DefaultTeamGuestRole = savedRole.Name
@@ -217,7 +217,7 @@ func (s *Server) doGuestRolesCreationMigration() {
}
if savedRole, err := s.Store().Role().Save(channelGuestRole); err != nil {
mlog.Critical("Failed to create new guest role for custom scheme.", mlog.Err(err))
mlog.Fatal("Failed to create new guest role for custom scheme.", mlog.Err(err))
allSucceeded = false
} else {
scheme.DefaultChannelGuestRole = savedRole.Name
@@ -225,7 +225,7 @@ func (s *Server) doGuestRolesCreationMigration() {
_, err := s.Store().Scheme().Save(scheme)
if err != nil {
mlog.Critical("Failed to update custom scheme.", mlog.Err(err))
mlog.Fatal("Failed to update custom scheme.", mlog.Err(err))
allSucceeded = false
}
}
@@ -241,7 +241,7 @@ func (s *Server) doGuestRolesCreationMigration() {
}
if err := s.Store().System().Save(&system); err != nil {
mlog.Critical("Failed to mark guest roles creation migration as completed.", mlog.Err(err))
mlog.Fatal("Failed to mark guest roles creation migration as completed.", mlog.Err(err))
}
}
@@ -260,19 +260,19 @@ func (s *Server) doSystemConsoleRolesCreationMigration() {
allSucceeded := true
if _, err := s.Store().Role().GetByName(context.Background(), model.SystemManagerRoleId); err != nil {
if _, err := s.Store().Role().Save(roles[model.SystemManagerRoleId]); err != nil {
mlog.Critical("Failed to create new role.", mlog.Err(err), mlog.String("role", model.SystemManagerRoleId))
mlog.Fatal("Failed to create new role.", mlog.Err(err), mlog.String("role", model.SystemManagerRoleId))
allSucceeded = false
}
}
if _, err := s.Store().Role().GetByName(context.Background(), model.SystemReadOnlyAdminRoleId); err != nil {
if _, err := s.Store().Role().Save(roles[model.SystemReadOnlyAdminRoleId]); err != nil {
mlog.Critical("Failed to create new role.", mlog.Err(err), mlog.String("role", model.SystemReadOnlyAdminRoleId))
mlog.Fatal("Failed to create new role.", mlog.Err(err), mlog.String("role", model.SystemReadOnlyAdminRoleId))
allSucceeded = false
}
}
if _, err := s.Store().Role().GetByName(context.Background(), model.SystemUserManagerRoleId); err != nil {
if _, err := s.Store().Role().Save(roles[model.SystemUserManagerRoleId]); err != nil {
mlog.Critical("Failed to create new role.", mlog.Err(err), mlog.String("role", model.SystemUserManagerRoleId))
mlog.Fatal("Failed to create new role.", mlog.Err(err), mlog.String("role", model.SystemUserManagerRoleId))
allSucceeded = false
}
}
@@ -287,7 +287,7 @@ func (s *Server) doSystemConsoleRolesCreationMigration() {
}
if err := s.Store().System().Save(&system); err != nil {
mlog.Critical("Failed to mark system console roles creation migration as completed.", mlog.Err(err))
mlog.Fatal("Failed to mark system console roles creation migration as completed.", mlog.Err(err))
}
}
@@ -302,7 +302,7 @@ func (s *Server) doCustomGroupAdminRoleCreationMigration() {
allSucceeded := true
if _, err := s.Store().Role().GetByName(context.Background(), model.SystemCustomGroupAdminRoleId); err != nil {
if _, err := s.Store().Role().Save(roles[model.SystemCustomGroupAdminRoleId]); err != nil {
mlog.Critical("Failed to create new role.", mlog.Err(err), mlog.String("role", model.SystemCustomGroupAdminRoleId))
mlog.Fatal("Failed to create new role.", mlog.Err(err), mlog.String("role", model.SystemCustomGroupAdminRoleId))
allSucceeded = false
}
}
@@ -317,7 +317,7 @@ func (s *Server) doCustomGroupAdminRoleCreationMigration() {
}
if err := s.Store().System().Save(&system); err != nil {
mlog.Critical("Failed to mark custom group admin role creation migration as completed.", mlog.Err(err))
mlog.Fatal("Failed to mark custom group admin role creation migration as completed.", mlog.Err(err))
}
}
@@ -337,7 +337,7 @@ func (s *Server) doContentExtractionConfigDefaultTrueMigration() {
}
if err := s.Store().System().Save(&system); err != nil {
mlog.Critical("Failed to mark content extraction config migration as completed.", mlog.Err(err))
mlog.Fatal("Failed to mark content extraction config migration as completed.", mlog.Err(err))
}
}
@@ -352,31 +352,31 @@ func (s *Server) doPlaybooksRolesCreationMigration() {
allSucceeded := true
if _, err := s.Store().Role().GetByName(context.Background(), model.PlaybookAdminRoleId); err != nil {
if _, err := s.Store().Role().Save(roles[model.PlaybookAdminRoleId]); err != nil {
mlog.Critical("Failed to create new playbook admin role to database.", mlog.Err(err))
mlog.Fatal("Failed to create new playbook admin role to database.", mlog.Err(err))
allSucceeded = false
}
}
if _, err := s.Store().Role().GetByName(context.Background(), model.PlaybookMemberRoleId); err != nil {
if _, err := s.Store().Role().Save(roles[model.PlaybookMemberRoleId]); err != nil {
mlog.Critical("Failed to create new playbook member role to database.", mlog.Err(err))
mlog.Fatal("Failed to create new playbook member role to database.", mlog.Err(err))
allSucceeded = false
}
}
if _, err := s.Store().Role().GetByName(context.Background(), model.RunAdminRoleId); err != nil {
if _, err := s.Store().Role().Save(roles[model.RunAdminRoleId]); err != nil {
mlog.Critical("Failed to create new run admin role to database.", mlog.Err(err))
mlog.Fatal("Failed to create new run admin role to database.", mlog.Err(err))
allSucceeded = false
}
}
if _, err := s.Store().Role().GetByName(context.Background(), model.RunMemberRoleId); err != nil {
if _, err := s.Store().Role().Save(roles[model.RunMemberRoleId]); err != nil {
mlog.Critical("Failed to create new run member role to database.", mlog.Err(err))
mlog.Fatal("Failed to create new run member role to database.", mlog.Err(err))
allSucceeded = false
}
}
schemes, err := s.Store().Scheme().GetAllPage(model.SchemeScopeTeam, 0, 1000000)
if err != nil {
mlog.Critical("Failed to get all schemes.", mlog.Err(err))
mlog.Fatal("Failed to get all schemes.", mlog.Err(err))
allSucceeded = false
}
@@ -391,7 +391,7 @@ func (s *Server) doPlaybooksRolesCreationMigration() {
}
if savedRole, err := s.Store().Role().Save(playbookAdminRole); err != nil {
mlog.Critical("Failed to create new playbook admin role for existing custom scheme.", mlog.Err(err))
mlog.Fatal("Failed to create new playbook admin role for existing custom scheme.", mlog.Err(err))
allSucceeded = false
} else {
scheme.DefaultPlaybookAdminRole = savedRole.Name
@@ -406,7 +406,7 @@ func (s *Server) doPlaybooksRolesCreationMigration() {
}
if savedRole, err := s.Store().Role().Save(playbookMember); err != nil {
mlog.Critical("Failed to create new playbook member role for existing custom scheme.", mlog.Err(err))
mlog.Fatal("Failed to create new playbook member role for existing custom scheme.", mlog.Err(err))
allSucceeded = false
} else {
scheme.DefaultPlaybookMemberRole = savedRole.Name
@@ -422,7 +422,7 @@ func (s *Server) doPlaybooksRolesCreationMigration() {
}
if savedRole, err := s.Store().Role().Save(runAdminRole); err != nil {
mlog.Critical("Failed to create new run admin role for existing custom scheme.", mlog.Err(err))
mlog.Fatal("Failed to create new run admin role for existing custom scheme.", mlog.Err(err))
allSucceeded = false
} else {
scheme.DefaultRunAdminRole = savedRole.Name
@@ -438,7 +438,7 @@ func (s *Server) doPlaybooksRolesCreationMigration() {
}
if savedRole, err := s.Store().Role().Save(runMemberRole); err != nil {
mlog.Critical("Failed to create new run member role for existing custom scheme.", mlog.Err(err))
mlog.Fatal("Failed to create new run member role for existing custom scheme.", mlog.Err(err))
allSucceeded = false
} else {
scheme.DefaultRunMemberRole = savedRole.Name
@@ -446,7 +446,7 @@ func (s *Server) doPlaybooksRolesCreationMigration() {
}
_, err := s.Store().Scheme().Save(scheme)
if err != nil {
mlog.Critical("Failed to update custom scheme.", mlog.Err(err))
mlog.Fatal("Failed to update custom scheme.", mlog.Err(err))
allSucceeded = false
}
}
@@ -462,7 +462,7 @@ func (s *Server) doPlaybooksRolesCreationMigration() {
}
if err := s.Store().System().Save(&system); err != nil {
mlog.Critical("Failed to mark playbook roles creation migration as completed.", mlog.Err(err))
mlog.Fatal("Failed to mark playbook roles creation migration as completed.", mlog.Err(err))
}
}
@@ -507,7 +507,7 @@ func (s *Server) doFirstAdminSetupCompleteMigration() {
}
if err := s.Store().System().Save(&system); err != nil {
mlog.Critical("Failed to mark first admin setup migration as completed.", mlog.Err(err))
mlog.Fatal("Failed to mark first admin setup migration as completed.", mlog.Err(err))
}
}
@@ -534,7 +534,7 @@ func (s *Server) doRemainingSchemaMigrations() {
}
if err := s.Store().System().Save(&system); err != nil {
mlog.Critical("Failed to mark the remaining schema migrations as completed.", mlog.Err(err))
mlog.Fatal("Failed to mark the remaining schema migrations as completed.", mlog.Err(err))
}
}
@@ -552,7 +552,7 @@ func (s *Server) doAppMigrations() {
// migrations. For example, it needs the guest roles migration.
err := s.doPermissionsMigrations()
if err != nil {
mlog.Critical("(app.App).DoPermissionsMigrations failed", mlog.Err(err))
mlog.Fatal("(app.App).DoPermissionsMigrations failed", mlog.Err(err))
}
s.doContentExtractionConfigDefaultTrueMigration()
s.doPlaybooksRolesCreationMigration()

Просмотреть файл

@@ -43,7 +43,7 @@ func (a *App) SendNotifications(c request.CTX, post *model.Post, team *model.Tea
return []string{}, nil
}
isCRTAllowed := a.Config().FeatureFlags.CollapsedThreads && *a.Config().ServiceSettings.CollapsedThreads != model.CollapsedThreadsDisabled
isCRTAllowed := *a.Config().ServiceSettings.CollapsedThreads != model.CollapsedThreadsDisabled
pchan := make(chan store.StoreResult, 1)
go func() {

Просмотреть файл

@@ -5,7 +5,6 @@ package app
import (
"fmt"
"os"
"testing"
"github.com/stretchr/testify/assert"
@@ -2734,8 +2733,7 @@ func TestReplyPostNotificationsWithCRT(t *testing.T) {
}()
// Enable CRT
os.Setenv("MM_FEATUREFLAGS_COLLAPSEDTHREADS", "true")
defer os.Unsetenv("MM_FEATUREFLAGS_COLLAPSEDTHREADS")
th.App.UpdateConfig(func(cfg *model.Config) {
*cfg.ServiceSettings.ThreadAutoFollow = true
*cfg.ServiceSettings.CollapsedThreads = model.CollapsedThreadsDefaultOn

Просмотреть файл

@@ -111,7 +111,7 @@ func (pm *platformMetrics) startMetricsServer() error {
go func() {
close(notify)
if err := pm.server.Serve(l); err != nil && err != http.ErrServerClosed {
pm.logger.Critical(err.Error())
pm.logger.Fatal(err.Error())
}
}()

Просмотреть файл

@@ -402,6 +402,8 @@ func (ch *Channels) installExtractedPlugin(manifest *model.Manifest, fromPluginD
manifest = updatedManifest
}
mlog.Debug("Installing plugin", mlog.String("plugin_id", manifest.Id), mlog.String("version", manifest.Version))
return manifest, nil
}

Просмотреть файл

@@ -2357,8 +2357,6 @@ func TestThreadMembership(t *testing.T) {
func TestFollowThreadSkipsParticipants(t *testing.T) {
th := Setup(t).InitBasic()
defer th.TearDown()
os.Setenv("MM_FEATUREFLAGS_COLLAPSEDTHREADS", "true")
defer os.Unsetenv("MM_FEATUREFLAGS_COLLAPSEDTHREADS")
th.App.UpdateConfig(func(cfg *model.Config) {
*cfg.ServiceSettings.ThreadAutoFollow = true
@@ -2410,13 +2408,16 @@ func TestFollowThreadSkipsParticipants(t *testing.T) {
for _, p := range thread.Participants {
require.True(t, p.Id == sysadmin.Id || p.Id == user.Id)
}
threadMembership.PostId = "notfound"
_, err = th.App.GetThreadForUser(threadMembership, false)
require.NotNil(t, err)
assert.Equal(t, http.StatusNotFound, err.StatusCode)
}
func TestAutofollowBasedOnRootPost(t *testing.T) {
th := Setup(t).InitBasic()
defer th.TearDown()
os.Setenv("MM_FEATUREFLAGS_COLLAPSEDTHREADS", "true")
defer os.Unsetenv("MM_FEATUREFLAGS_COLLAPSEDTHREADS")
th.App.UpdateConfig(func(cfg *model.Config) {
*cfg.ServiceSettings.ThreadAutoFollow = true
@@ -2445,8 +2446,6 @@ func TestAutofollowBasedOnRootPost(t *testing.T) {
func TestViewChannelShouldNotUpdateThreads(t *testing.T) {
th := Setup(t).InitBasic()
defer th.TearDown()
os.Setenv("MM_FEATUREFLAGS_COLLAPSEDTHREADS", "true")
defer os.Unsetenv("MM_FEATUREFLAGS_COLLAPSEDTHREADS")
th.App.UpdateConfig(func(cfg *model.Config) {
*cfg.ServiceSettings.ThreadAutoFollow = true
@@ -2528,12 +2527,6 @@ func TestCollapsedThreadFetch(t *testing.T) {
})
t.Run("Should not panic on unexpected db error", func(t *testing.T) {
os.Setenv("MM_FEATUREFLAGS_COLLAPSEDTHREADS", "true")
defer os.Unsetenv("MM_FEATUREFLAGS_COLLAPSEDTHREADS")
th.App.UpdateConfig(func(cfg *model.Config) {
cfg.FeatureFlags.CollapsedThreads = true
})
channel := th.CreateChannel(th.Context, th.BasicTeam)
th.AddUserToChannel(user2, channel)
defer th.App.DeleteChannel(th.Context, channel, user1.Id)
@@ -2765,8 +2758,6 @@ func TestSharedChannelSyncForPostActions(t *testing.T) {
func TestAutofollowOnPostingAfterUnfollow(t *testing.T) {
th := Setup(t).InitBasic()
defer th.TearDown()
os.Setenv("MM_FEATUREFLAGS_COLLAPSEDTHREADS", "true")
defer os.Unsetenv("MM_FEATUREFLAGS_COLLAPSEDTHREADS")
th.App.UpdateConfig(func(cfg *model.Config) {
*cfg.ServiceSettings.ThreadAutoFollow = true
@@ -2834,8 +2825,6 @@ func TestGetPostIfAuthorized(t *testing.T) {
func TestShouldNotRefollowOnOthersReply(t *testing.T) {
th := Setup(t).InitBasic()
defer th.TearDown()
os.Setenv("MM_FEATUREFLAGS_COLLAPSEDTHREADS", "true")
defer os.Unsetenv("MM_FEATUREFLAGS_COLLAPSEDTHREADS")
th.App.UpdateConfig(func(cfg *model.Config) {
*cfg.ServiceSettings.ThreadAutoFollow = true

Просмотреть файл

@@ -598,7 +598,7 @@ func (s *Server) startInterClusterServices(license *model.License) error {
// Shared Channels service
// License check
if !*license.Features.SharedChannels {
if !license.HasSharedChannels() {
mlog.Debug("License does not have shared channels enabled")
return nil
}
@@ -1062,7 +1062,7 @@ func (s *Server) Start() error {
}
if err != nil && err != http.ErrServerClosed {
mlog.Critical("Error starting server", mlog.Err(err))
mlog.Fatal("Error starting server", mlog.Err(err))
time.Sleep(time.Second)
}
@@ -1071,7 +1071,7 @@ func (s *Server) Start() error {
if *s.platform.Config().ServiceSettings.EnableLocalMode {
if err := s.startLocalModeServer(); err != nil {
mlog.Critical(err.Error())
mlog.Fatal(err.Error())
}
}
@@ -1103,7 +1103,7 @@ func (s *Server) startLocalModeServer() error {
go func() {
err = s.localModeServer.Serve(unixListener)
if err != nil && err != http.ErrServerClosed {
mlog.Critical("Error starting unix socket server", mlog.Err(err))
mlog.Fatal("Error starting unix socket server", mlog.Err(err))
}
}()
return nil

Просмотреть файл

@@ -10,7 +10,6 @@ import (
"github.com/mattermost/mattermost-server/v6/app/request"
"github.com/mattermost/mattermost-server/v6/model"
"github.com/mattermost/mattermost-server/v6/shared/i18n"
"github.com/mattermost/mattermost-server/v6/shared/mlog"
)
type InviteProvider struct {
@@ -38,137 +37,177 @@ func (*InviteProvider) GetCommand(a *app.App, T i18n.TranslateFunc) *model.Comma
}
}
func (*InviteProvider) DoCommand(a *app.App, c request.CTX, args *model.CommandArgs, message string) *model.CommandResponse {
func (i *InviteProvider) DoCommand(a *app.App, c request.CTX, args *model.CommandArgs, message string) *model.CommandResponse {
return &model.CommandResponse{
Text: i.doCommand(a, c, args, message),
ResponseType: model.CommandResponseTypeEphemeral,
}
}
func (i *InviteProvider) doCommand(a *app.App, c request.CTX, args *model.CommandArgs, message string) string {
if message == "" {
return &model.CommandResponse{
Text: args.T("api.command_invite.missing_message.app_error"),
ResponseType: model.CommandResponseTypeEphemeral,
return args.T("api.command_invite.missing_message.app_error")
}
resps := &[]string{}
targetUsers, targetChannels, resp := i.parseMessage(a, c, args, resps, message)
if resp != "" {
return resp
}
// Verify that the inviter has permissions to invite users to the every channel.
targetChannels = i.checkPermissions(a, c, args, resps, targetUsers[0], targetChannels)
for _, targetUser := range targetUsers {
for _, targetChannel := range targetChannels {
if resp = i.addUserToChannel(a, c, args, targetUser, targetChannel); resp != "" {
*resps = append(*resps, resp)
continue
}
if args.ChannelId != targetChannel.Id {
*resps = append(*resps, args.T("api.command_invite.success", map[string]any{
"User": targetUser.Username,
"Channel": targetChannel.Name,
}))
}
}
}
splitMessage := strings.SplitN(message, " ", 2)
targetUsername := splitMessage[0]
targetUsername = strings.TrimPrefix(targetUsername, "@")
if len(*resps) > 0 {
return strings.Join(*resps, "\n")
}
userProfile, nErr := a.Srv().Store().User().GetByUsername(targetUsername)
if nErr != nil {
mlog.Error(nErr.Error())
return &model.CommandResponse{
Text: args.T("api.command_invite.missing_user.app_error"),
ResponseType: model.CommandResponseTypeEphemeral,
return ""
}
func (i *InviteProvider) parseMessage(a *app.App, c request.CTX, args *model.CommandArgs, resps *[]string, message string) ([]*model.User, []*model.Channel, string) {
splitMessage := strings.Split(message, " ")
targetUsers := make([]*model.User, 0, 1)
targetChannels := make([]*model.Channel, 0)
for j, msg := range splitMessage {
if msg == "" {
continue
}
if msg[0] == '@' || (msg[0] != '~' && j == 0) {
targetUsername := strings.TrimPrefix(msg, "@")
userProfile := i.getUserProfile(a, targetUsername)
if userProfile == nil {
*resps = append(*resps, args.T("api.command_invite.missing_user.app_error", map[string]any{
"User": targetUsername,
}))
continue
}
targetUsers = append(targetUsers, userProfile)
} else {
targetChannelName := strings.TrimPrefix(msg, "~")
channelToJoin, err := a.GetChannelByName(c, targetChannelName, args.TeamId, false)
if err != nil {
*resps = append(*resps, args.T("api.command_invite.channel.error", map[string]any{
"Channel": targetChannelName,
}))
continue
}
targetChannels = append(targetChannels, channelToJoin)
}
}
if len(targetUsers) == 0 {
if len(*resps) != 0 {
return nil, nil, strings.Join(*resps, "\n")
}
return nil, nil, args.T("api.command_invite.missing_message.app_error")
}
if len(targetChannels) == 0 {
if len(*resps) != 0 {
return nil, nil, strings.Join(*resps, "\n")
}
channelToJoin, err := a.GetChannel(c, args.ChannelId)
if err != nil {
return nil, nil, args.T("api.command_invite.channel.app_error")
}
targetChannels = append(targetChannels, channelToJoin)
}
return targetUsers, targetChannels, ""
}
func (i *InviteProvider) getUserProfile(a *app.App, username string) *model.User {
userProfile, nErr := a.Srv().Store().User().GetByUsername(username)
if nErr != nil {
return nil
}
if userProfile.DeleteAt != 0 {
return &model.CommandResponse{
Text: args.T("api.command_invite.missing_user.app_error"),
ResponseType: model.CommandResponseTypeEphemeral,
}
return nil
}
var channelToJoin *model.Channel
return userProfile
}
func (i *InviteProvider) checkPermissions(a *app.App, c request.CTX, args *model.CommandArgs, resps *[]string, targetUser *model.User, targetChannels []*model.Channel) []*model.Channel {
var err *model.AppError
// User set a channel to add the invited user
if len(splitMessage) > 1 && splitMessage[1] != "" {
targetChannelName := strings.TrimPrefix(strings.TrimSpace(splitMessage[1]), "~")
if channelToJoin, err = a.GetChannelByName(c, targetChannelName, args.TeamId, false); err != nil {
return &model.CommandResponse{
Text: args.T("api.command_invite.channel.error", map[string]any{
"Channel": targetChannelName,
}),
ResponseType: model.CommandResponseTypeEphemeral,
validChannels := make([]*model.Channel, 0, len(targetChannels))
for _, targetChannel := range targetChannels {
switch targetChannel.Type {
case model.ChannelTypeOpen:
if !a.HasPermissionToChannel(c, args.UserId, targetChannel.Id, model.PermissionManagePublicChannelMembers) {
*resps = append(*resps, args.T("api.command_invite.permission.app_error", map[string]any{
"User": targetUser.Username,
"Channel": targetChannel.Name,
}))
continue
}
}
} else {
channelToJoin, err = a.GetChannel(c, args.ChannelId)
if err != nil {
return &model.CommandResponse{
Text: args.T("api.command_invite.channel.app_error"),
ResponseType: model.CommandResponseTypeEphemeral,
}
}
}
// Permissions Check
switch channelToJoin.Type {
case model.ChannelTypeOpen:
if !a.HasPermissionToChannel(c, args.UserId, channelToJoin.Id, model.PermissionManagePublicChannelMembers) {
return &model.CommandResponse{
Text: args.T("api.command_invite.permission.app_error", map[string]any{
"User": userProfile.Username,
"Channel": channelToJoin.Name,
}),
ResponseType: model.CommandResponseTypeEphemeral,
}
}
case model.ChannelTypePrivate:
if !a.HasPermissionToChannel(c, args.UserId, channelToJoin.Id, model.PermissionManagePrivateChannelMembers) {
if _, err = a.GetChannelMember(c, channelToJoin.Id, args.UserId); err == nil {
// User doing the inviting is a member of the channel.
return &model.CommandResponse{
Text: args.T("api.command_invite.permission.app_error", map[string]any{
"User": userProfile.Username,
"Channel": channelToJoin.Name,
}),
ResponseType: model.CommandResponseTypeEphemeral,
case model.ChannelTypePrivate:
if !a.HasPermissionToChannel(c, args.UserId, targetChannel.Id, model.PermissionManagePrivateChannelMembers) {
if _, err = a.GetChannelMember(c, targetChannel.Id, args.UserId); err == nil {
// User doing the inviting is a member of the channel.
*resps = append(*resps, args.T("api.command_invite.permission.app_error", map[string]any{
"User": targetUser.Username,
"Channel": targetChannel.Name,
}))
continue
}
// User doing the inviting is *not* a member of the channel.
*resps = append(*resps, args.T("api.command_invite.private_channel.app_error", map[string]any{
"Channel": targetChannel.Name,
}))
continue
}
// User doing the inviting is *not* a member of the channel.
return &model.CommandResponse{
Text: args.T("api.command_invite.private_channel.app_error", map[string]any{
"Channel": channelToJoin.Name,
}),
ResponseType: model.CommandResponseTypeEphemeral,
}
}
default:
return &model.CommandResponse{
Text: args.T("api.command_invite.directchannel.app_error"),
ResponseType: model.CommandResponseTypeEphemeral,
default:
*resps = append(*resps, args.T("api.command_invite.directchannel.app_error"))
continue
}
validChannels = append(validChannels, targetChannel)
}
return validChannels
}
func (i *InviteProvider) addUserToChannel(a *app.App, c request.CTX, args *model.CommandArgs, userProfile *model.User, channelToJoin *model.Channel) string {
// Check if user is already in the channel
_, err = a.GetChannelMember(c, channelToJoin.Id, userProfile.Id)
_, err := a.GetChannelMember(c, channelToJoin.Id, userProfile.Id)
if err == nil {
return &model.CommandResponse{
Text: args.T("api.command_invite.user_already_in_channel.app_error", map[string]any{
"User": userProfile.Username,
}),
ResponseType: model.CommandResponseTypeEphemeral,
}
return args.T("api.command_invite.user_already_in_channel.app_error", map[string]any{
"User": userProfile.Username,
})
}
if _, err := a.AddChannelMember(c, userProfile.Id, channelToJoin, app.ChannelMemberOpts{
UserRequestorID: args.UserId,
}); err != nil {
var text string
if _, err = a.AddChannelMember(c, userProfile.Id, channelToJoin, app.ChannelMemberOpts{UserRequestorID: args.UserId}); err != nil {
if err.Id == "api.channel.add_members.user_denied" {
text = args.T("api.command_invite.group_constrained_user_denied")
return args.T("api.command_invite.group_constrained_user_denied")
} else if err.Id == "app.team.get_member.missing.app_error" ||
err.Id == "api.channel.add_user.to.channel.failed.deleted.app_error" {
text = args.T("api.command_invite.user_not_in_team.app_error", map[string]any{
return args.T("api.command_invite.user_not_in_team.app_error", map[string]any{
"Username": userProfile.Username,
})
} else {
text = args.T("api.command_invite.fail.app_error")
}
return &model.CommandResponse{
Text: text,
ResponseType: model.CommandResponseTypeEphemeral,
}
return args.T("api.command_invite.fail.app_error")
}
if args.ChannelId != channelToJoin.Id {
return &model.CommandResponse{
Text: args.T("api.command_invite.success", map[string]any{
"User": userProfile.Username,
"Channel": channelToJoin.Name,
}),
ResponseType: model.CommandResponseTypeEphemeral,
}
}
return &model.CommandResponse{}
return ""
}

Просмотреть файл

@@ -17,46 +17,7 @@ func TestInviteProvider(t *testing.T) {
th := setup(t).initBasic()
defer th.tearDown()
channel := th.createChannel(th.BasicTeam, model.ChannelTypeOpen)
privateChannel := th.createChannel(th.BasicTeam, model.ChannelTypePrivate)
dmChannel := th.createDmChannel(th.BasicUser2)
privateChannel2 := th.createChannelWithAnotherUser(th.BasicTeam, model.ChannelTypePrivate, th.BasicUser2.Id)
basicUser3 := th.createUser()
th.linkUserToTeam(basicUser3, th.BasicTeam)
basicUser4 := th.createUser()
deactivatedUser := th.createUser()
th.App.UpdateActive(th.Context, deactivatedUser, false)
var err *model.AppError
_, err = th.App.CreateBot(th.Context, &model.Bot{
Username: "bot1",
OwnerId: basicUser3.Id,
Description: "a test bot",
})
require.Nil(t, err)
bot2, err := th.App.CreateBot(th.Context, &model.Bot{
Username: "bot2",
OwnerId: basicUser3.Id,
Description: "a test bot",
})
require.Nil(t, err)
_, _, err = th.App.AddUserToTeam(th.Context, th.BasicTeam.Id, bot2.UserId, basicUser3.Id)
require.Nil(t, err)
bot3, err := th.App.CreateBot(th.Context, &model.Bot{
Username: "bot3",
OwnerId: basicUser3.Id,
Description: "a test bot",
})
require.Nil(t, err)
_, _, err = th.App.AddUserToTeam(th.Context, th.BasicTeam.Id, bot3.UserId, basicUser3.Id)
require.Nil(t, err)
err = th.App.RemoveUserFromTeam(th.Context, th.BasicTeam.Id, bot3.UserId, basicUser3.Id)
require.Nil(t, err)
InviteP := InviteProvider{}
inviteProvider := InviteProvider{}
args := &model.CommandArgs{
T: func(s string, args ...any) string { return s },
ChannelId: th.BasicChannel.Id,
@@ -64,115 +25,188 @@ func TestInviteProvider(t *testing.T) {
UserId: th.BasicUser.Id,
}
userAndWrongChannel := "@" + th.BasicUser2.Username + " wrongchannel1"
userAndChannel := "@" + th.BasicUser2.Username + " ~" + channel.Name + " "
userAndDisplayChannel := "@" + th.BasicUser2.Username + " ~" + channel.DisplayName + " "
userAndPrivateChannel := "@" + th.BasicUser2.Username + " ~" + privateChannel.Name
userAndDMChannel := "@" + basicUser3.Username + " ~" + dmChannel.Name
userAndInvalidPrivate := "@" + basicUser3.Username + " ~" + privateChannel2.Name
deactivatedUserPublicChannel := "@" + deactivatedUser.Username + " ~" + channel.Name
groupChannel := th.createChannel(th.BasicTeam, model.ChannelTypePrivate)
_, err = th.App.AddChannelMember(th.Context, th.BasicUser.Id, groupChannel, app.ChannelMemberOpts{})
require.Nil(t, err)
groupChannel.GroupConstrained = model.NewBool(true)
groupChannel, _ = th.App.UpdateChannel(th.Context, groupChannel)
groupChannelNonUser := "@" + th.BasicUser2.Username + " ~" + groupChannel.Name
tests := []struct {
desc string
expected string
msg string
}{
{
desc: "Missing user and channel in the command",
expected: "api.command_invite.missing_message.app_error",
msg: "",
},
{
desc: "User added in the current channel",
expected: "",
msg: th.BasicUser2.Username,
},
{
desc: "Add user to another channel not the current",
expected: "api.command_invite.success",
msg: userAndChannel,
},
{
desc: "try to add a user to a direct channel",
expected: "api.command_invite.directchannel.app_error",
msg: userAndDMChannel,
},
{
desc: "Try to add a user to a invalid channel",
expected: "api.command_invite.channel.error",
msg: userAndWrongChannel,
},
{
desc: "Try to add a user to an private channel",
expected: "api.command_invite.success",
msg: userAndPrivateChannel,
},
{
desc: "Using display channel name which is different form Channel name",
expected: "api.command_invite.channel.error",
msg: userAndDisplayChannel,
},
{
desc: "Invalid user to current channel",
expected: "api.command_invite.missing_user.app_error",
msg: "@invalidUser123",
},
{
desc: "Invalid user to current channel without @",
expected: "api.command_invite.missing_user.app_error",
msg: "invalidUser321",
},
{
desc: "try to add a user which is not part of the team",
expected: "api.command_invite.user_not_in_team.app_error",
msg: basicUser4.Username,
},
{
desc: "try to add a user not part of the group to a group channel",
expected: "api.command_invite.group_constrained_user_denied",
msg: groupChannelNonUser,
},
{
desc: "try to add a user to a private channel with no permission",
expected: "api.command_invite.private_channel.app_error",
msg: userAndInvalidPrivate,
},
{
desc: "try to add a deleted user to a public channel",
expected: "api.command_invite.missing_user.app_error",
msg: deactivatedUserPublicChannel,
},
{
desc: "try to add bot to a public channel",
expected: "api.command_invite.user_not_in_team.app_error",
msg: "@bot1",
},
{
desc: "add bot to a public channel",
expected: "",
msg: "@bot2",
},
{
desc: "try to add bot removed from a team to a public channel",
expected: "api.command_invite.user_not_in_team.app_error",
msg: "@bot3",
},
runCmd := func(msg string, expected string) {
actual := inviteProvider.DoCommand(th.App, th.Context, args, msg).Text
assert.Equal(t, expected, actual)
}
for _, test := range tests {
t.Run(test.desc, func(t *testing.T) {
actual := InviteP.DoCommand(th.App, th.Context, args, test.msg).Text
assert.Equal(t, test.expected, actual)
})
checkIsMember := func(channelID, userID string) {
_, channelMemberErr := th.App.GetChannelMember(th.Context, channelID, userID)
require.Nil(t, channelMemberErr, "Failed to add user to channel")
}
checkIsNotMember := func(channelID, userID string) {
_, channelMemberErr := th.App.GetChannelMember(th.Context, channelID, userID)
require.NotNil(t, channelMemberErr, "Failed to add user to channel")
}
t.Run("try to add missing user and channel in the command", func(t *testing.T) {
msg := ""
runCmd(msg, "api.command_invite.missing_message.app_error")
})
t.Run("user added in the current channel", func(t *testing.T) {
msg := th.BasicUser2.Username
runCmd(msg, "")
checkIsMember(th.BasicChannel.Id, th.BasicUser2.Id)
})
t.Run("add user to another channel not the current", func(t *testing.T) {
channel := th.createChannel(th.BasicTeam, model.ChannelTypeOpen)
msg := "@" + th.BasicUser2.Username + " ~" + channel.Name + " "
runCmd(msg, "api.command_invite.success")
checkIsMember(channel.Id, th.BasicUser2.Id)
})
t.Run("add a user to a private channel", func(t *testing.T) {
privateChannel := th.createChannel(th.BasicTeam, model.ChannelTypePrivate)
msg := "@" + th.BasicUser2.Username + " ~" + privateChannel.Name
runCmd(msg, "api.command_invite.success")
checkIsMember(privateChannel.Id, th.BasicUser2.Id)
})
t.Run("add multiple users to multiple channels", func(t *testing.T) {
anotherUser := th.createUser()
th.linkUserToTeam(anotherUser, th.BasicTeam)
channel1 := th.createChannel(th.BasicTeam, model.ChannelTypeOpen)
channel2 := th.createChannel(th.BasicTeam, model.ChannelTypeOpen)
msg := "@" + th.BasicUser2.Username + " @" + anotherUser.Username + " ~" + channel1.Name + " ~" + channel2.Name
expected := "api.command_invite.success\napi.command_invite.success\napi.command_invite.success\napi.command_invite.success"
runCmd(msg, expected)
checkIsMember(channel1.Id, th.BasicUser2.Id)
checkIsMember(channel2.Id, th.BasicUser2.Id)
checkIsMember(channel1.Id, anotherUser.Id)
checkIsMember(channel2.Id, anotherUser.Id)
})
t.Run("adds multiple users even when some are invalid or already members", func(t *testing.T) {
channel := th.createChannel(th.BasicTeam, model.ChannelTypeOpen)
userAlreadyInChannel := th.createUser()
th.linkUserToTeam(userAlreadyInChannel, th.BasicTeam)
th.addUserToChannel(userAlreadyInChannel, channel)
userInTeam := th.createUser()
th.linkUserToTeam(userInTeam, th.BasicTeam)
userNotInTeam := th.createUser()
msg := "@invalidUser123 @" + userAlreadyInChannel.Username + " @" + userInTeam.Username + " @" + userNotInTeam.Username + " ~" + channel.Name
expected := "api.command_invite.missing_user.app_error\n"
expected += "api.command_invite.user_already_in_channel.app_error\n"
expected += "api.command_invite.success\n"
expected += "api.command_invite.user_not_in_team.app_error"
runCmd(msg, expected)
checkIsMember(channel.Id, userInTeam.Id)
})
t.Run("try to add a user to a direct channel", func(t *testing.T) {
anotherUser := th.createUser()
th.linkUserToTeam(anotherUser, th.BasicTeam)
directChannel := th.createDmChannel(th.BasicUser2)
msg := "@" + anotherUser.Username + " ~" + directChannel.Name
runCmd(msg, "api.command_invite.directchannel.app_error")
checkIsNotMember(directChannel.Id, anotherUser.Id)
})
t.Run("try to add a user to an invalid channel", func(t *testing.T) {
msg := "@" + th.BasicUser2.Username + " wrongchannel1"
runCmd(msg, "api.command_invite.channel.error")
})
t.Run("try to add a user using channel's display name", func(t *testing.T) {
channel := th.createChannel(th.BasicTeam, model.ChannelTypeOpen)
msg := "@" + th.BasicUser2.Username + " ~" + channel.DisplayName
runCmd(msg, "api.command_invite.channel.error")
checkIsNotMember(channel.Id, th.BasicUser2.Id)
})
t.Run("try add invalid user to current channel", func(t *testing.T) {
msg := "@invalidUser123"
runCmd(msg, "api.command_invite.missing_user.app_error")
})
t.Run("invalid user to current channel without @", func(t *testing.T) {
msg := "invalidUser123"
runCmd(msg, "api.command_invite.missing_user.app_error")
})
t.Run("try to add a user which is not part of the team", func(t *testing.T) {
anotherUser := th.createUser()
// Do not add user to the team
msg := anotherUser.Username
runCmd(msg, "api.command_invite.user_not_in_team.app_error")
})
t.Run("try to add a user not part of the group to a group channel", func(t *testing.T) {
groupChannel := th.createChannel(th.BasicTeam, model.ChannelTypePrivate)
_, err := th.App.AddChannelMember(th.Context, th.BasicUser.Id, groupChannel, app.ChannelMemberOpts{})
require.Nil(t, err)
groupChannel.GroupConstrained = model.NewBool(true)
groupChannel, _ = th.App.UpdateChannel(th.Context, groupChannel)
msg := "@" + th.BasicUser2.Username + " ~" + groupChannel.Name
runCmd(msg, "api.command_invite.group_constrained_user_denied")
checkIsNotMember(groupChannel.Id, th.BasicUser2.Id)
})
t.Run("try to add a user to a private channel with no permission", func(t *testing.T) {
anotherUser := th.createUser()
th.linkUserToTeam(anotherUser, th.BasicTeam)
privateChannel := th.createChannelWithAnotherUser(th.BasicTeam, model.ChannelTypePrivate, th.BasicUser2.Id)
msg := "@" + anotherUser.Username + " ~" + privateChannel.Name
runCmd(msg, "api.command_invite.private_channel.app_error")
checkIsNotMember(privateChannel.Id, anotherUser.Id)
})
t.Run("try to add a deleted user to a public channel", func(t *testing.T) {
channel := th.createChannel(th.BasicTeam, model.ChannelTypeOpen)
deactivatedUser := th.createUser()
_, appErr := th.App.UpdateActive(th.Context, deactivatedUser, false)
require.Nil(t, appErr)
msg := "@" + deactivatedUser.Username + " ~" + channel.Name
runCmd(msg, "api.command_invite.missing_user.app_error")
checkIsNotMember(channel.Id, deactivatedUser.Id)
})
t.Run("add bot to a public channel", func(t *testing.T) {
bot, appErr := th.App.CreateBot(th.Context, &model.Bot{Username: "bot_" + model.NewId(), OwnerId: th.BasicUser2.Id})
require.Nil(t, appErr)
_, _, appErr = th.App.AddUserToTeam(th.Context, th.BasicTeam.Id, bot.UserId, th.BasicUser2.Id)
require.Nil(t, appErr)
msg := "@" + bot.Username
runCmd(msg, "")
checkIsMember(th.BasicChannel.Id, bot.UserId)
})
t.Run("try to add bot to a public channel without being a member", func(t *testing.T) {
bot, appErr := th.App.CreateBot(th.Context, &model.Bot{Username: "bot_" + model.NewId(), OwnerId: th.BasicUser2.Id})
require.Nil(t, appErr)
// Do not add to the team
msg := "@" + bot.Username
runCmd(msg, "api.command_invite.user_not_in_team.app_error")
checkIsNotMember(th.BasicChannel.Id, bot.UserId)
})
t.Run("try to add bot removed from a team to a public channel", func(t *testing.T) {
bot, appErr := th.App.CreateBot(th.Context, &model.Bot{Username: "bot_" + model.NewId(), OwnerId: th.BasicUser2.Id})
require.Nil(t, appErr)
_, _, appErr = th.App.AddUserToTeam(th.Context, th.BasicTeam.Id, bot.UserId, th.BasicUser2.Id)
require.Nil(t, appErr)
appErr = th.App.RemoveUserFromTeam(th.Context, th.BasicTeam.Id, bot.UserId, th.BasicUser2.Id)
require.Nil(t, appErr)
msg := "@" + bot.Username
runCmd(msg, "api.command_invite.user_not_in_team.app_error")
checkIsNotMember(th.BasicChannel.Id, bot.UserId)
})
}
func TestInviteGroup(t *testing.T) {

Просмотреть файл

@@ -2484,24 +2484,31 @@ func (a *App) GetThreadsForUser(userID, teamID string, options model.GetUserThre
}
func (a *App) GetThreadMembershipForUser(userId, threadId string) (*model.ThreadMembership, *model.AppError) {
threadMembership, err := a.Srv().Store().Thread().GetMembershipForUser(userId, threadId)
if err != nil {
return nil, model.NewAppError("GetThreadMembershipForUser", "app.user.get_thread_membership_for_user.app_error", nil, "", http.StatusInternalServerError).Wrap(err)
}
if threadMembership == nil {
return nil, model.NewAppError("GetThreadMembershipForUser", "app.user.get_thread_membership_for_user.not_found", nil, "thread membership not found/followed", http.StatusNotFound)
threadMembership, nErr := a.Srv().Store().Thread().GetMembershipForUser(userId, threadId)
if nErr != nil {
var nfErr *store.ErrNotFound
switch {
case errors.As(nErr, &nfErr):
return nil, model.NewAppError("GetThreadMembershipForUser", "app.user.get_thread_membership_for_user.not_found", nil, "", http.StatusNotFound).Wrap(nErr)
default:
return nil, model.NewAppError("GetThreadMembershipForUser", "app.user.get_thread_membership_for_user.app_error", nil, "", http.StatusInternalServerError).Wrap(nErr)
}
}
return threadMembership, nil
}
func (a *App) GetThreadForUser(threadMembership *model.ThreadMembership, extended bool) (*model.ThreadResponse, *model.AppError) {
thread, err := a.Srv().Store().Thread().GetThreadForUser(threadMembership, extended, a.isPostPriorityEnabled())
if err != nil {
return nil, model.NewAppError("GetThreadForUser", "app.user.get_threads_for_user.app_error", nil, "", http.StatusInternalServerError).Wrap(err)
}
if thread == nil {
return nil, model.NewAppError("GetThreadForUser", "app.user.get_threads_for_user.not_found", nil, "thread not found/followed", http.StatusNotFound)
thread, nErr := a.Srv().Store().Thread().GetThreadForUser(threadMembership, extended, a.isPostPriorityEnabled())
if nErr != nil {
var nfErr *store.ErrNotFound
switch {
case errors.As(nErr, &nfErr):
return nil, model.NewAppError("GetThreadForUser", "app.user.get_threads_for_user.not_found", nil, "thread not found/followed", http.StatusNotFound)
default:
return nil, model.NewAppError("GetThreadForUser", "app.user.get_threads_for_user.app_error", nil, "", http.StatusInternalServerError).Wrap(nErr)
}
}
a.sanitizeProfiles(thread.Participants, false)
thread.Post.SanitizeProps()
return thread, nil

Просмотреть файл

@@ -8,7 +8,7 @@ import (
"context"
"encoding/json"
"errors"
"os"
"net/http"
"path/filepath"
"strings"
"testing"
@@ -1673,8 +1673,6 @@ func TestPatchUser(t *testing.T) {
}
func TestUpdateThreadReadForUser(t *testing.T) {
os.Setenv("MM_FEATUREFLAGS_COLLAPSEDTHREADS", "true")
defer os.Unsetenv("MM_FEATUREFLAGS_COLLAPSEDTHREADS")
t.Run("Ensure thread membership is created and followed", func(t *testing.T) {
th := Setup(t).InitBasic()
@@ -1703,6 +1701,10 @@ func TestUpdateThreadReadForUser(t *testing.T) {
require.Nil(t, appErr)
require.NotNil(t, threadMembership)
assert.True(t, threadMembership.Following)
_, appErr = th.App.GetThreadMembershipForUser(th.BasicUser.Id, "notfound")
require.NotNil(t, appErr)
assert.Equal(t, http.StatusNotFound, appErr.StatusCode)
})
t.Run("Ensure no panic on error", func(t *testing.T) {

Просмотреть файл

@@ -196,7 +196,7 @@ func GenerateClientConfig(c *model.Config, telemetryID string, license *model.Li
props["DataRetentionBoardsRetentionDays"] = strconv.FormatInt(int64(*c.DataRetentionSettings.BoardsRetentionDays), 10)
}
if *license.Features.SharedChannels {
if license.HasSharedChannels() {
props["ExperimentalSharedChannels"] = strconv.FormatBool(*c.ExperimentalSettings.EnableSharedChannels)
props["ExperimentalRemoteClusterService"] = strconv.FormatBool(c.FeatureFlags.EnableRemoteClusterService && *c.ExperimentalSettings.EnableRemoteClusterService)
}

Просмотреть файл

@@ -254,6 +254,78 @@ func TestGetClientConfig(t *testing.T) {
"EnableCustomGroups": "false",
},
},
{
"Shared channels other license",
&model.Config{
ExperimentalSettings: model.ExperimentalSettings{
EnableSharedChannels: model.NewBool(true),
},
},
"",
&model.License{
Features: &model.Features{
SharedChannels: model.NewBool(false),
},
SkuShortName: "other",
},
map[string]string{
"ExperimentalSharedChannels": "false",
},
},
{
"licensed for shared channels",
&model.Config{
ExperimentalSettings: model.ExperimentalSettings{
EnableSharedChannels: model.NewBool(true),
},
},
"",
&model.License{
Features: &model.Features{
SharedChannels: model.NewBool(true),
},
SkuShortName: "other",
},
map[string]string{
"ExperimentalSharedChannels": "true",
},
},
{
"Shared channels professional license",
&model.Config{
ExperimentalSettings: model.ExperimentalSettings{
EnableSharedChannels: model.NewBool(true),
},
},
"",
&model.License{
Features: &model.Features{
SharedChannels: model.NewBool(false),
},
SkuShortName: model.LicenseShortSkuProfessional,
},
map[string]string{
"ExperimentalSharedChannels": "true",
},
},
{
"Shared channels enterprise license",
&model.Config{
ExperimentalSettings: model.ExperimentalSettings{
EnableSharedChannels: model.NewBool(true),
},
},
"",
&model.License{
Features: &model.Features{
SharedChannels: model.NewBool(false),
},
SkuShortName: model.LicenseShortSkuEnterprise,
},
map[string]string{
"ExperimentalSharedChannels": "true",
},
},
}
for _, testCase := range testCases {

Просмотреть файл

@@ -900,15 +900,15 @@
},
{
"id": "api.command_invite.hint",
"translation": "@[username] ~[channel]"
"translation": "@[username]... ~[channel]..."
},
{
"id": "api.command_invite.missing_message.app_error",
"translation": "Missing Username and Channel."
"translation": "Missing Username and/or Channel."
},
{
"id": "api.command_invite.missing_user.app_error",
"translation": "We couldn't find the user. They may have been deactivated by the System Administrator."
"translation": "We couldn't find the user {{.User}}. They may have been deactivated by the System Administrator."
},
{
"id": "api.command_invite.name",
@@ -920,7 +920,7 @@
},
{
"id": "api.command_invite.private_channel.app_error",
"translation": "Could not find the channel {{.Channel}}. Please use the channel handle to identify channels."
"translation": "Could not find the channel {{.Channel}}. Please use the [channel handle](https://docs.mattermost.com/messaging/managing-channels.html#naming-a-channel) to identify channels."
},
{
"id": "api.command_invite.success",

Просмотреть файл

@@ -9362,5 +9362,9 @@
{
"id": "model.group.name.reserved_name.app_error",
"translation": "csoport név létezik mint lefoglalt név"
},
{
"id": "api.acknowledgement.delete.archived_channel.app_error",
"translation": "Nem lehet eltávolítani egy archivált csatornában lévő jóváhagyást."
}
]

Просмотреть файл

@@ -1369,11 +1369,11 @@
},
{
"id": "api.post.send_notification_and_forget.push_comment_on_post",
"translation": " 당신의 게시글에 글이 달렸습니다."
"translation": " 당신의 게시글에 글이 달렸습니다."
},
{
"id": "api.post.send_notification_and_forget.push_comment_on_thread",
"translation": " 당신이 참여한 글타래에 글이 달렸습니다."
"translation": " 당신이 참여한 글타래에 글이 달렸습니다."
},
{
"id": "api.post.send_notifications_and_forget.push_explicit_mention",
@@ -4565,7 +4565,7 @@
},
{
"id": "oauth.gitlab.tos.error",
"translation": "GitLab's Terms of Service have updated. Please go to gitlab.com to accept them and then try logging into Mattermost again."
"translation": "GitLab 서비스 약관이 업데이트되었습니다. {{.URL}}으로 이동하여 수락한 다음 Mattermost에 다시 로그인해주세요."
},
{
"id": "plugin.api.update_user_status.bad_status",
@@ -4741,7 +4741,7 @@
},
{
"id": "web.error.unsupported_browser.min_os_version.mac",
"translation": "macOS 10.14 이상"
"translation": "macOS 11 버전 이상"
},
{
"id": "web.error.unsupported_browser.min_browser_version.safari",
@@ -4753,11 +4753,11 @@
},
{
"id": "web.error.unsupported_browser.min_browser_version.edge",
"translation": "44버전 이상"
"translation": "95 버전 이상"
},
{
"id": "web.error.unsupported_browser.min_browser_version.chrome",
"translation": "100 버전 이상"
"translation": "106 버전 이상"
},
{
"id": "web.error.unsupported_browser.learn_more",
@@ -7241,11 +7241,11 @@
},
{
"id": "api.post.send_notification_and_forget.push_comment_on_crt_thread",
"translation": " 지켜보는 중인 글타래에 글을 남겼습니다."
"translation": " 지켜보는 글타래에 글을 남겼습니다."
},
{
"id": "api.post.send_notification_and_forget.push_comment_on_crt_thread_dm",
"translation": " 글타래에 글을 남겼습니다."
"translation": " 글타래에 글을 남겼습니다."
},
{
"id": "api.command_remote.missing_command",
@@ -8034,5 +8034,9 @@
{
"id": "app.user.update_threads_read_for_user.app_error",
"translation": "모든 사용자 글타래들을 읽음 상태로 변경할 수 없습니다"
},
{
"id": "api.admin.syncables_error",
"translation": "구성원을 그룹-팀 및 그룹-채널에 추가하지 못했습니다"
}
]

Просмотреть файл

@@ -16,9 +16,6 @@ type FeatureFlags struct {
// all other values as false.
TestBoolFeature bool
// Toggle on and off support for Collapsed Threads
CollapsedThreads bool
// Enable the remote cluster service for shared channels.
EnableRemoteClusterService bool
@@ -81,7 +78,6 @@ type FeatureFlags struct {
func (f *FeatureFlags) SetDefaults() {
f.TestFeature = "off"
f.TestBoolFeature = false
f.CollapsedThreads = true
f.EnableRemoteClusterService = false
f.AppsEnabled = true
f.PluginApps = ""

Просмотреть файл

@@ -10,6 +10,8 @@ type BootstrapSelfHostedSignupRequest struct {
type BootstrapSelfHostedSignupResponse struct {
Progress string `json:"progress"`
// email listed on the JWT claim
Email string `json:"email"`
}
type BootstrapSelfHostedSignupResponseInternal struct {

Просмотреть файл

@@ -312,6 +312,16 @@ func (l *License) HasEnterpriseMarketplacePlugins() bool {
l.SkuShortName == LicenseShortSkuEnterprise
}
func (l *License) HasSharedChannels() bool {
if l == nil {
return false
}
return (l.Features != nil && l.Features.SharedChannels != nil && *l.Features.SharedChannels) ||
l.SkuShortName == LicenseShortSkuProfessional ||
l.SkuShortName == LicenseShortSkuEnterprise
}
// NewTestLicense returns a license that expires in the future and has the given features.
func NewTestLicense(features ...string) *License {
ret := &License{

Просмотреть файл

@@ -343,3 +343,53 @@ func TestLicense_IsSanctionedTrial(t *testing.T) {
assert.True(t, license.IsSanctionedTrial())
})
}
func TestLicenseHasSharedChannels(t *testing.T) {
testCases := []struct {
description string
license License
expectedValue bool
}{
{
"licensed for shared channels",
License{
Features: &Features{
SharedChannels: NewBool(true),
},
SkuShortName: "other",
},
true,
},
{
"not licensed for shared channels",
License{
Features: &Features{},
SkuShortName: "other",
},
false,
},
{
"professional license for shared channels",
License{
Features: &Features{},
SkuShortName: LicenseShortSkuProfessional,
},
true,
},
{
"enterprise license for shared channels",
License{
Features: &Features{},
SkuShortName: LicenseShortSkuEnterprise,
},
true,
},
}
for _, testCase := range testCases {
t.Run(testCase.description, func(t *testing.T) {
assert.Equal(t, testCase.expectedValue, testCase.license.HasSharedChannels())
})
}
}

Просмотреть файл

@@ -256,11 +256,15 @@ func (er *AppError) Error() string {
// render the error information
sb.WriteString(er.Where)
sb.WriteString(": ")
sb.WriteString(er.Message)
if er.Message != NoTranslation {
sb.WriteString(er.Message)
}
// only render the detailed error when it's present
if er.DetailedError != "" {
sb.WriteString(", ")
if er.Message != NoTranslation {
sb.WriteString(", ")
}
sb.WriteString(er.DetailedError)
}

Просмотреть файл

@@ -81,6 +81,11 @@ func TestAppError(t *testing.T) {
t.Log(appErr.Error())
}
func TestAppErrorNoTranslation(t *testing.T) {
appErr := NewAppError("TestAppError", NoTranslation, nil, "test error", http.StatusBadRequest)
require.Equal(t, "TestAppError: test error", appErr.Error())
}
func TestAppErrorJunk(t *testing.T) {
rerr := AppErrorFromJSON(strings.NewReader("<html><body>This is a broken test</body></html>"))
require.Equal(t, "body: <html><body>This is a broken test</body></html>", rerr.DetailedError)

Просмотреть файл

@@ -330,6 +330,8 @@ func (env *Environment) Activate(id string) (manifest *model.Manifest, activated
return nil, false, fmt.Errorf("unable to start plugin: must at least have a web app or server component")
}
mlog.Debug("Plugin activated", mlog.String("plugin_id", pluginInfo.Manifest.Id), mlog.String("version", pluginInfo.Manifest.Version))
return pluginInfo.Manifest, true, nil
}

Просмотреть файл

@@ -333,7 +333,7 @@ func extractBinary(executablePath string, filename string) error {
if err != nil {
err2 := os.Rename(tmpFileName, executablePath)
if err2 != nil {
mlog.Critical("Unable to restore the backup of the executable file. Restore the executable file manually.")
mlog.Fatal("Unable to restore the backup of the executable file. Restore the executable file manually.")
return errors.Wrap(err2, "critical error: unable to upgrade the binary or restore the old binary version. Please restore it manually")
}
return err
@@ -342,13 +342,13 @@ func extractBinary(executablePath string, filename string) error {
if _, err = io.Copy(outFile, tarReader); err != nil {
err2 := os.Remove(executablePath)
if err2 != nil {
mlog.Critical("Unable to restore the backup of the executable file. Restore the executable file manually.")
mlog.Fatal("Unable to restore the backup of the executable file. Restore the executable file manually.")
return errors.Wrap(err2, "critical error: unable to upgrade the binary or restore the old binary version. Please restore it manually")
}
err2 = os.Rename(tmpFileName, executablePath)
if err2 != nil {
mlog.Critical("Unable to restore the backup of the executable file. Restore the executable file manually.")
mlog.Fatal("Unable to restore the backup of the executable file. Restore the executable file manually.")
return errors.Wrap(err2, "critical error: unable to upgrade the binary or restore the old binary version. Please restore it manually")
}
return err

Просмотреть файл

@@ -113,13 +113,10 @@ func Error(msg string, fields ...Field) {
// Convenience method equivalent to calling `Log` with the `Critical` level.
// DEPRECATED: Either use Error or Fatal.
// Critical level isn't added in mlog/levels.go:StdAll so calling this doesn't
// really work. For now we just call Fatal to atleast print something.
func Critical(msg string, fields ...Field) {
logger := getGlobalLogger()
if logger == nil {
defaultLog(LvlCritical, msg, fields...)
return
}
logger.Critical(msg, fields...)
Fatal(msg, fields...)
}
func Fatal(msg string, fields ...Field) {

Просмотреть файл

@@ -24,7 +24,6 @@ func TestLoggingBeforeInitialized(t *testing.T) {
mlog.Debug("debug log")
mlog.Warn("warning log")
mlog.Error("error log")
mlog.Critical("critical log")
})
}
@@ -40,14 +39,13 @@ func TestLoggingAfterInitialized(t *testing.T) {
Type: "file",
Format: "json",
FormatOptions: json.RawMessage(`{"enable_caller":true}`),
Levels: []mlog.Level{mlog.LvlCritical, mlog.LvlError, mlog.LvlWarn, mlog.LvlInfo, mlog.LvlDebug},
Levels: []mlog.Level{mlog.LvlError, mlog.LvlWarn, mlog.LvlInfo, mlog.LvlDebug},
},
[]string{
`{"timestamp":0,"level":"debug","msg":"real debug log","caller":"mlog/global_test.go:0"}`,
`{"timestamp":0,"level":"info","msg":"real info log","caller":"mlog/global_test.go:0"}`,
`{"timestamp":0,"level":"warn","msg":"real warning log","caller":"mlog/global_test.go:0"}`,
`{"timestamp":0,"level":"error","msg":"real error log","caller":"mlog/global_test.go:0"}`,
`{"timestamp":0,"level":"critical","msg":"real critical log","caller":"mlog/global_test.go:0"}`,
},
},
{
@@ -56,11 +54,10 @@ func TestLoggingAfterInitialized(t *testing.T) {
Type: "file",
Format: "json",
FormatOptions: json.RawMessage(`{"enable_caller":true}`),
Levels: []mlog.Level{mlog.LvlCritical, mlog.LvlError},
Levels: []mlog.Level{mlog.LvlError},
},
[]string{
`{"timestamp":0,"level":"error","msg":"real error log","caller":"mlog/global_test.go:0"}`,
`{"timestamp":0,"level":"critical","msg":"real critical log","caller":"mlog/global_test.go:0"}`,
},
},
{
@@ -69,14 +66,13 @@ func TestLoggingAfterInitialized(t *testing.T) {
Type: "file",
Format: "plain",
FormatOptions: json.RawMessage(`{"delim":" | ", "enable_caller":true}`),
Levels: []mlog.Level{mlog.LvlCritical, mlog.LvlError, mlog.LvlWarn, mlog.LvlInfo, mlog.LvlDebug},
Levels: []mlog.Level{mlog.LvlError, mlog.LvlWarn, mlog.LvlInfo, mlog.LvlDebug},
},
[]string{
`debug | TIME | real debug log | caller="mlog/global_test.go:0"`,
`info | TIME | real info log | caller="mlog/global_test.go:0"`,
`warn | TIME | real warning log | caller="mlog/global_test.go:0"`,
`error | TIME | real error log | caller="mlog/global_test.go:0"`,
`critical | TIME | real critical log | caller="mlog/global_test.go:0"`,
},
},
{
@@ -85,11 +81,10 @@ func TestLoggingAfterInitialized(t *testing.T) {
Type: "file",
Format: "plain",
FormatOptions: json.RawMessage(`{"delim":" | ", "enable_caller":true}`),
Levels: []mlog.Level{mlog.LvlCritical, mlog.LvlError},
Levels: []mlog.Level{mlog.LvlError},
},
[]string{
`error | TIME | real error log | caller="mlog/global_test.go:0"`,
`critical | TIME | real critical log | caller="mlog/global_test.go:0"`,
},
},
}
@@ -116,7 +111,6 @@ func TestLoggingAfterInitialized(t *testing.T) {
mlog.Info("real info log")
mlog.Warn("real warning log")
mlog.Error("real error log")
mlog.Critical("real critical log")
logger.Shutdown()