mattermost-community-enterp.../cmd/mmctl/commands/user_e2e_test.go
Claude ec1f89217a Merge: Complete Mattermost Server with Community Enterprise
Full Mattermost server source with integrated Community Enterprise features.
Includes vendor directory for offline/air-gapped builds.

Structure:
- enterprise-impl/: Enterprise feature implementations
- enterprise-community/: Init files that register implementations
- enterprise/: Bridge imports (community_imports.go)
- vendor/: All dependencies for offline builds

Build (online):
  go build ./cmd/mattermost

Build (offline/air-gapped):
  go build -mod=vendor ./cmd/mattermost

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-17 23:59:07 +09:00

1877 lines
67 KiB
Go

// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
package commands
import (
"context"
"fmt"
"net/http"
"github.com/hashicorp/go-multierror"
"github.com/mattermost/mattermost/server/public/model"
"github.com/spf13/cobra"
"github.com/mattermost/mattermost/server/v8/cmd/mmctl/client"
"github.com/mattermost/mattermost/server/v8/cmd/mmctl/printer"
)
func (s *MmctlE2ETestSuite) TestUserActivateCmd() {
s.SetupTestHelper().InitBasic()
user, appErr := s.th.App.CreateUser(s.th.Context, &model.User{Email: s.th.GenerateTestEmail(), Username: model.NewUsername(), Password: model.NewId()})
s.Require().Nil(appErr)
s.RunForSystemAdminAndLocal("Activate user", func(c client.Client) {
printer.Clean()
_, appErr := s.th.App.UpdateActive(s.th.Context, user, false)
s.Require().Nil(appErr)
err := userActivateCmdF(c, &cobra.Command{}, []string{user.Email})
s.Require().Nil(err)
s.Require().Len(printer.GetLines(), 0)
s.Require().Len(printer.GetErrorLines(), 0)
ruser, err := s.th.App.GetUser(user.Id)
s.Require().Nil(err)
s.Require().Zero(ruser.DeleteAt)
})
s.Run("Activate user without permissions", func() {
printer.Clean()
_, appErr := s.th.App.UpdateActive(s.th.Context, user, false)
s.Require().Nil(appErr)
err := userActivateCmdF(s.th.Client, &cobra.Command{}, []string{user.Email})
s.Require().Error(err)
s.Require().Len(printer.GetLines(), 0)
s.Require().Len(printer.GetErrorLines(), 1)
s.Require().Equal(printer.GetErrorLines()[0], "unable to change activation status of user "+user.Id+": You do not have the appropriate permissions.")
ruser, err := s.th.App.GetUser(user.Id)
s.Require().Nil(err)
s.Require().NotZero(ruser.DeleteAt)
})
s.RunForAllClients("Activate nonexistent user", func(c client.Client) {
printer.Clean()
err := userActivateCmdF(c, &cobra.Command{}, []string{"nonexistent@email"})
s.Require().Error(err)
s.Require().Len(printer.GetLines(), 0)
s.Require().Len(printer.GetErrorLines(), 1)
s.Require().Equal("1 error occurred:\n\t* user nonexistent@email not found\n\n", printer.GetErrorLines()[0])
})
}
func (s *MmctlE2ETestSuite) TestUserDeactivateCmd() {
s.SetupTestHelper().InitBasic()
user, appErr := s.th.App.CreateUser(s.th.Context, &model.User{Email: s.th.GenerateTestEmail(), Username: model.NewUsername(), Password: model.NewId()})
s.Require().Nil(appErr)
s.RunForSystemAdminAndLocal("Deactivate user", func(c client.Client) {
printer.Clean()
_, appErr := s.th.App.UpdateActive(s.th.Context, user, true)
s.Require().Nil(appErr)
err := userDeactivateCmdF(c, &cobra.Command{}, []string{user.Email})
s.Require().Nil(err)
s.Require().Len(printer.GetLines(), 0)
s.Require().Len(printer.GetErrorLines(), 0)
ruser, err := s.th.App.GetUser(user.Id)
s.Require().Nil(err)
s.Require().NotZero(ruser.DeleteAt)
})
s.Run("Deactivate user without permissions", func() {
printer.Clean()
_, appErr := s.th.App.UpdateActive(s.th.Context, user, true)
s.Require().Nil(appErr)
err := userDeactivateCmdF(s.th.Client, &cobra.Command{}, []string{user.Email})
s.Require().Error(err)
s.Require().Len(printer.GetLines(), 0)
s.Require().Len(printer.GetErrorLines(), 1)
s.Require().Equal(printer.GetErrorLines()[0], "unable to change activation status of user "+user.Id+": You do not have the appropriate permissions.")
ruser, err := s.th.App.GetUser(user.Id)
s.Require().Nil(err)
s.Require().Zero(ruser.DeleteAt)
})
s.RunForAllClients("Deactivate nonexistent user", func(c client.Client) {
printer.Clean()
err := userDeactivateCmdF(c, &cobra.Command{}, []string{"nonexistent@email"})
s.Require().Error(err)
s.Require().Len(printer.GetLines(), 0)
s.Require().Len(printer.GetErrorLines(), 1)
s.Require().Equal("1 error occurred:\n\t* user nonexistent@email not found\n\n", printer.GetErrorLines()[0])
})
}
func (s *MmctlE2ETestSuite) TestSearchUserCmd() {
s.SetupTestHelper().InitBasic()
s.RunForAllClients("Search for an existing user", func(c client.Client) {
printer.Clean()
err := searchUserCmdF(c, &cobra.Command{}, []string{s.th.BasicUser.Email})
s.Require().Nil(err)
s.Len(printer.GetLines(), 1)
user := printer.GetLines()[0].(userOut)
s.Equal(s.th.BasicUser.Username, user.Username)
s.False(user.Deactivated)
s.Empty(user.AuthData)
s.Empty(user.AuthService)
s.Len(printer.GetErrorLines(), 0)
})
s.RunForAllClients("Search for a disabled user", func(c client.Client) {
printer.Clean()
// Create a disabled user
disabledUser, appErr := s.th.App.CreateUser(s.th.Context, &model.User{
Email: s.th.GenerateTestEmail(),
Username: model.NewUsername(),
Password: model.NewId(),
DeleteAt: model.GetMillis(), // Set DeleteAt to disable the user
})
s.Require().Nil(appErr)
err := searchUserCmdF(c, &cobra.Command{}, []string{disabledUser.Email})
s.Require().Nil(err)
s.Len(printer.GetLines(), 1)
user := printer.GetLines()[0].(userOut)
s.Equal(disabledUser.Username, user.Username)
s.True(user.Deactivated) // Verify user shows as deactivated
s.Empty(user.AuthData)
s.Empty(user.AuthService)
s.Len(printer.GetErrorLines(), 0)
})
// Create a LDAP user
ldapUser, appErr := s.th.App.CreateUser(s.th.Context, &model.User{
Email: s.th.GenerateTestEmail(),
Username: model.NewUsername(),
AuthData: model.NewPointer("1234"),
AuthService: model.UserAuthServiceLdap,
})
s.Require().Nil(appErr)
s.RunForSystemAdminAndLocal("Search for a user with authData", func(c client.Client) {
printer.Clean()
err := searchUserCmdF(c, &cobra.Command{}, []string{ldapUser.Email})
s.Require().Nil(err)
s.Len(printer.GetLines(), 1)
user := printer.GetLines()[0].(userOut)
s.Equal(ldapUser.Username, user.Username)
s.False(user.Deactivated)
s.Equal(*ldapUser.AuthData, user.AuthData)
s.Equal(ldapUser.AuthService, user.AuthService)
s.Len(printer.GetErrorLines(), 0)
})
s.Run("Search for a user with authData/Client", func() {
printer.Clean()
// Non-admin should not be able to see AuthData or AuthService
err := searchUserCmdF(s.th.Client, &cobra.Command{}, []string{ldapUser.Email})
s.Require().Nil(err)
s.Len(printer.GetLines(), 1)
user := printer.GetLines()[0].(userOut)
s.Equal(ldapUser.Username, user.Username)
s.False(user.Deactivated)
s.Equal("", user.AuthData)
s.Equal("", user.AuthService)
s.Len(printer.GetErrorLines(), 0)
})
s.RunForAllClients("Search for a nonexistent user", func(c client.Client) {
printer.Clean()
emailArg := "nonexistentUser@example.com"
err := searchUserCmdF(c, &cobra.Command{}, []string{emailArg})
s.Require().Error(err)
s.Len(printer.GetLines(), 0)
s.Len(printer.GetErrorLines(), 1)
s.Equal(fmt.Sprintf("1 error occurred:\n\t* user %s not found\n\n", emailArg), printer.GetErrorLines()[0])
})
}
func (s *MmctlE2ETestSuite) TestListUserCmd() {
s.SetupTestHelper().InitBasic().DeleteBots()
// populate map for checking
userPool := []string{
s.th.BasicUser.Username,
s.th.BasicUser2.Username,
s.th.TeamAdminUser.Username,
s.th.SystemAdminUser.Username,
s.th.SystemManagerUser.Username,
}
for range 10 {
userData := model.User{
Username: "fakeuser" + model.NewRandomString(10),
Password: "Pa$$word11",
Email: s.th.GenerateTestEmail(),
}
usr, err := s.th.App.CreateUser(s.th.Context, &userData)
s.Require().Nil(err)
userPool = append(userPool, usr.Username)
}
inactivePool := []string{}
// create inactive users
for range 2 {
userData := model.User{
Username: "fakeuser" + model.NewRandomString(10),
Password: "Pa$$word11",
Email: s.th.GenerateTestEmail(),
DeleteAt: model.GetMillis(),
}
usr, err := s.th.App.CreateUser(s.th.Context, &userData)
s.Require().Nil(err)
userPool = append(userPool, usr.Username)
inactivePool = append(inactivePool, usr.Username)
}
s.RunForAllClients("Get some random user", func(c client.Client) {
printer.Clean()
cmd := ResetListUsersCmd(s.T())
s.Require().NoError(cmd.Flags().Set("per-page", "5"))
err := listUsersCmdF(c, cmd, []string{})
s.Require().Nil(err)
s.Require().GreaterOrEqual(len(printer.GetLines()), 5)
s.Len(printer.GetErrorLines(), 0)
for _, u := range printer.GetLines() {
user := u.(*model.User)
s.Require().Contains(userPool, user.Username)
}
})
s.RunForAllClients("Get list of all user", func(c client.Client) {
printer.Clean()
cmd := ResetListUsersCmd(s.T())
s.Require().NoError(cmd.Flags().Set("per-page", "12"))
s.Require().NoError(cmd.Flags().Set("all", "true"))
err := listUsersCmdF(c, cmd, []string{})
s.Require().Nil(err)
s.Require().GreaterOrEqual(len(printer.GetLines()), 16)
s.Len(printer.GetErrorLines(), 0)
for _, each := range printer.GetLines() {
user := each.(*model.User)
s.Require().Contains(userPool, user.Username)
}
})
s.RunForAllClients("Get list of inactive users", func(c client.Client) {
printer.Clean()
cmd := ResetListUsersCmd(s.T())
s.Require().NoError(cmd.Flags().Set("per-page", "12"))
s.Require().NoError(cmd.Flags().Set("all", "true"))
s.Require().NoError(cmd.Flags().Set("inactive", "true"))
err := listUsersCmdF(c, cmd, []string{})
s.Require().Nil(err)
s.Require().GreaterOrEqual(len(printer.GetLines()), 2)
s.Len(printer.GetErrorLines(), 0)
for _, each := range printer.GetLines() {
user := each.(*model.User)
s.Require().Contains(inactivePool, user.Username)
}
})
// create users with team
for range 10 {
userData := model.User{
Username: "teamuser" + model.NewRandomString(10),
Password: "Pa$$word11",
Email: s.th.GenerateTestEmail(),
}
usr, err := s.th.App.CreateUser(s.th.Context, &userData)
s.Require().Nil(err)
userPool = append(userPool, usr.Username)
s.th.LinkUserToTeam(usr, s.th.BasicTeam)
}
s.RunForAllClients("Get list users given team", func(c client.Client) {
printer.Clean()
cmd := ResetListUsersCmd(s.T())
s.Require().NoError(cmd.Flags().Set("per-page", "40"))
s.Require().NoError(cmd.Flags().Set("all", "true"))
s.Require().NoError(cmd.Flags().Set("team", s.th.BasicTeam.Name))
err := listUsersCmdF(c, cmd, []string{})
s.Require().Nil(err)
s.Require().GreaterOrEqual(len(printer.GetLines()), 10)
s.Len(printer.GetErrorLines(), 0)
for _, each := range printer.GetLines() {
user := each.(*model.User)
s.Require().Contains(userPool, user.Username)
}
})
// create inactive users with team
inactiveUserPool := []string{}
for range 10 {
userData := model.User{
Username: "inactiveteamuser" + model.NewRandomString(10),
Password: "Pa$$word11",
Email: s.th.GenerateTestEmail(),
DeleteAt: model.GetMillis(),
}
usr, err := s.th.App.CreateUser(s.th.Context, &userData)
s.Require().Nil(err)
inactiveUserPool = append(inactiveUserPool, usr.Username)
s.th.LinkUserToTeam(usr, s.th.BasicTeam)
}
s.RunForAllClients("Get list of inactive users given team", func(c client.Client) {
printer.Clean()
cmd := ResetListUsersCmd(s.T())
s.Require().NoError(cmd.Flags().Set("per-page", "40"))
s.Require().NoError(cmd.Flags().Set("all", "true"))
s.Require().NoError(cmd.Flags().Set("team", s.th.BasicTeam.Name))
s.Require().NoError(cmd.Flags().Set("inactive", "true"))
err := listUsersCmdF(c, cmd, []string{})
s.Require().Nil(err)
s.Require().GreaterOrEqual(len(printer.GetLines()), 10)
s.Len(printer.GetErrorLines(), 0)
for _, each := range printer.GetLines() {
user := each.(*model.User)
s.Require().Contains(inactiveUserPool, user.Username)
}
})
}
func (s *MmctlE2ETestSuite) TestUserInviteCmdf() {
s.SetupTestHelper().InitBasic()
s.RunForAllClients("Invite user", func(c client.Client) {
printer.Clean()
previousVal := s.th.App.Config().ServiceSettings.EnableEmailInvitations
s.th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableEmailInvitations = true })
defer s.th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableEmailInvitations = *previousVal })
err := userInviteCmdF(c, &cobra.Command{}, []string{s.th.BasicUser.Email, s.th.BasicTeam.Id})
s.Require().Nil(err)
s.Require().Len(printer.GetLines(), 1)
s.Require().Equal(printer.GetLines()[0], "Invites may or may not have been sent.")
s.Require().Len(printer.GetErrorLines(), 0)
})
s.RunForAllClients("Inviting when email invitation disabled", func(c client.Client) {
printer.Clean()
previousVal := s.th.App.Config().ServiceSettings.EnableEmailInvitations
s.th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableEmailInvitations = false })
defer func() {
s.th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableEmailInvitations = *previousVal })
}()
err := userInviteCmdF(c, &cobra.Command{}, []string{s.th.BasicUser.Email, s.th.BasicTeam.Id})
s.Require().Error(err)
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.",
s.th.BasicUser.Email,
s.th.BasicTeam.Name,
),
printer.GetErrorLines()[0],
)
})
s.RunForAllClients("Invite user outside of accepted domain", func(c client.Client) {
printer.Clean()
previousVal := s.th.App.Config().ServiceSettings.EnableEmailInvitations
s.th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableEmailInvitations = true })
defer func() {
s.th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableEmailInvitations = *previousVal })
}()
team := s.th.CreateTeam()
team.AllowedDomains = "@example.com"
team, appErr := s.th.App.UpdateTeam(team)
s.Require().Nil(appErr)
user := s.th.CreateUser()
err := userInviteCmdF(c, &cobra.Command{}, []string{user.Email, team.Id})
s.Require().Error(err)
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.`,
user.Email,
team.Name,
user.Email,
),
printer.GetErrorLines()[0],
)
})
}
func (s *MmctlE2ETestSuite) TestResetUserMfaCmd() {
s.SetupTestHelper().InitBasic()
user, appErr := s.th.App.CreateUser(s.th.Context, &model.User{Email: s.th.GenerateTestEmail(), Username: model.NewUsername(), Password: model.NewId(), MfaActive: true, MfaSecret: "secret"})
s.Require().Nil(appErr)
s.RunForSystemAdminAndLocal("Reset user mfa", func(c client.Client) {
printer.Clean()
previousVal := s.th.App.Config().ServiceSettings.EnableMultifactorAuthentication
s.th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableMultifactorAuthentication = true })
defer s.th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableMultifactorAuthentication = *previousVal })
err := resetUserMfaCmdF(c, &cobra.Command{}, []string{user.Email})
s.Require().Nil(err)
s.Require().Len(printer.GetLines(), 0)
s.Require().Len(printer.GetErrorLines(), 0)
// make sure user is updated after reset mfa
ruser, err := s.th.App.GetUser(user.Id)
s.Require().Nil(err)
s.Require().NotEqual(ruser.UpdateAt, user.UpdateAt)
})
s.RunForSystemAdminAndLocal("Reset mfa disabled config", func(c client.Client) {
printer.Clean()
previousVal := s.th.App.Config().ServiceSettings.EnableMultifactorAuthentication
s.th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableMultifactorAuthentication = false })
defer func() {
s.th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableMultifactorAuthentication = *previousVal })
}()
userMfaInactive, appErr := s.th.App.CreateUser(s.th.Context, &model.User{Email: s.th.GenerateTestEmail(), Username: model.NewUsername(), Password: model.NewId(), MfaActive: false})
s.Require().Nil(appErr)
err := resetUserMfaCmdF(c, &cobra.Command{}, []string{userMfaInactive.Email})
s.Require().Nil(err)
s.Require().Len(printer.GetLines(), 0)
s.Require().Len(printer.GetErrorLines(), 0)
})
s.Run("Reset user mfa without permission", func() {
printer.Clean()
previousVal := s.th.App.Config().ServiceSettings.EnableMultifactorAuthentication
s.th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableMultifactorAuthentication = true })
defer func() {
s.th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableMultifactorAuthentication = *previousVal })
}()
err := resetUserMfaCmdF(s.th.Client, &cobra.Command{}, []string{user.Email})
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
)
s.Require().EqualError(err, expected.Error())
s.Require().Len(printer.GetLines(), 0)
})
}
func (s *MmctlE2ETestSuite) TestVerifyUserEmailWithoutTokenCmd() {
s.SetupTestHelper().InitBasic()
user, appErr := s.th.App.CreateUser(s.th.Context, &model.User{Email: s.th.GenerateTestEmail(), Username: model.NewUsername(), Password: model.NewId()})
s.Require().Nil(appErr)
s.RunForSystemAdminAndLocal("Verify user email without token", func(c client.Client) {
printer.Clean()
err := verifyUserEmailWithoutTokenCmdF(c, &cobra.Command{}, []string{user.Email})
s.Require().Nil(err)
s.Require().Len(printer.GetLines(), 1)
s.Require().Len(printer.GetErrorLines(), 0)
})
s.Run("Verify user email without token (without permission)", func() {
printer.Clean()
err := verifyUserEmailWithoutTokenCmdF(s.th.Client, &cobra.Command{}, []string{user.Email})
var expected error
expected = multierror.Append(
expected, fmt.Errorf("unable to verify user %s email: You do not have the appropriate permissions.", user.Id),
)
s.Require().EqualError(err, expected.Error())
s.Require().Len(printer.GetLines(), 0)
})
s.RunForAllClients("Verify user email without token for nonexistent user", func(c client.Client) {
printer.Clean()
err := verifyUserEmailWithoutTokenCmdF(c, &cobra.Command{}, []string{"nonexistent@email"})
var expected error
expected = multierror.Append(
expected, ExtractErrorFromResponse(
&model.Response{StatusCode: http.StatusNotFound},
ErrEntityNotFound{Type: "user", ID: "nonexistent@email"},
),
)
s.Require().EqualError(err, expected.Error())
s.Require().Len(printer.GetLines(), 0)
})
}
func (s *MmctlE2ETestSuite) TestCreateUserCmd() {
s.SetupTestHelper().InitBasic()
s.RunForAllClients("Should not create a user w/o username", func(c client.Client) {
printer.Clean()
email := s.th.GenerateTestEmail()
cmd := &cobra.Command{}
cmd.Flags().String("password", "somepass", "")
cmd.Flags().String("email", email, "")
err := userCreateCmdF(c, cmd, []string{})
s.EqualError(err, "Username is required: flag accessed but not defined: username")
s.Require().Empty(printer.GetLines())
_, err = s.th.App.GetUserByEmail(email)
s.Require().NotNil(err)
s.Require().ErrorContains(err, "GetUserByEmail: Unable to find the user., failed to find User: resource \"User\" not found, id: email="+email)
})
s.RunForAllClients("Should not create a user w/o email", func(c client.Client) {
printer.Clean()
username := model.NewUsername()
cmd := &cobra.Command{}
cmd.Flags().String("username", username, "")
cmd.Flags().String("password", "somepass", "")
err := userCreateCmdF(c, cmd, []string{})
s.EqualError(err, "Email is required: flag accessed but not defined: email")
s.Require().Empty(printer.GetLines())
_, err = s.th.App.GetUserByUsername(username)
s.Require().NotNil(err)
s.Require().ErrorContains(err, "GetUserByUsername: Unable to find an existing account matching your username for this team. This team may require an invite from the team owner to join., failed to find User: resource \"User\" not found, id: username="+username)
})
s.RunForAllClients("Should not create a user w/o password", func(c client.Client) {
printer.Clean()
email := s.th.GenerateTestEmail()
cmd := &cobra.Command{}
cmd.Flags().String("username", model.NewId(), "")
cmd.Flags().String("email", email, "")
err := userCreateCmdF(c, cmd, []string{})
s.EqualError(err, "Password is required: flag accessed but not defined: password")
s.Require().Empty(printer.GetLines())
_, err = s.th.App.GetUserByEmail(email)
s.Require().NotNil(err)
s.Require().ErrorContains(err, "GetUserByEmail: Unable to find the user., failed to find User: resource \"User\" not found, id: email="+email)
})
s.Run("Should create a user but w/o system-admin privileges", func() {
printer.Clean()
email := s.th.GenerateTestEmail()
username := model.NewUsername()
cmd := &cobra.Command{}
cmd.Flags().String("username", username, "")
cmd.Flags().String("email", email, "")
cmd.Flags().String("password", "password", "")
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.Require().Empty(printer.GetLines())
user, err := s.th.App.GetUserByEmail(email)
s.Require().Nil(err)
s.Equal(username, user.Username)
s.Equal(false, user.IsSystemAdmin())
})
s.RunForSystemAdminAndLocal("Should create new system-admin user given required params", func(c client.Client) {
printer.Clean()
email := s.th.GenerateTestEmail()
username := model.NewUsername()
cmd := &cobra.Command{}
cmd.Flags().String("username", username, "")
cmd.Flags().String("email", email, "")
cmd.Flags().String("password", "somepass", "")
cmd.Flags().Bool("system-admin", true, "")
err := userCreateCmdF(s.th.SystemAdminClient, cmd, []string{})
s.Require().Nil(err)
s.Len(printer.GetLines(), 1)
user, err := s.th.App.GetUserByEmail(email)
s.Require().Nil(err)
s.Equal(username, user.Username)
s.Equal(true, user.IsSystemAdmin())
})
s.RunForAllClients("Should create new user given required params", func(c client.Client) {
printer.Clean()
email := s.th.GenerateTestEmail()
username := model.NewUsername()
cmd := &cobra.Command{}
cmd.Flags().String("username", username, "")
cmd.Flags().String("email", email, "")
cmd.Flags().String("password", "somepass", "")
err := userCreateCmdF(c, cmd, []string{})
s.Require().Nil(err)
s.Len(printer.GetLines(), 1)
user, err := s.th.App.GetUserByEmail(email)
s.Require().Nil(err)
s.Equal(username, user.Username)
s.Equal(false, user.IsSystemAdmin())
})
s.RunForSystemAdminAndLocal("Should create new user with the email already verified only for admin or local mode", func(c client.Client) {
printer.Clean()
email := s.th.GenerateTestEmail()
username := model.NewUsername()
cmd := &cobra.Command{}
cmd.Flags().String("username", username, "")
cmd.Flags().String("email", email, "")
cmd.Flags().String("password", "somepass", "")
cmd.Flags().Bool("email-verified", true, "")
err := userCreateCmdF(c, cmd, []string{})
s.Require().Nil(err)
s.Len(printer.GetLines(), 1)
user, err := s.th.App.GetUserByEmail(email)
s.Require().Nil(err)
s.Equal(username, user.Username)
s.Equal(false, user.IsSystemAdmin())
s.Equal(true, user.EmailVerified)
})
}
func (s *MmctlE2ETestSuite) TestDeleteUsersCmd() {
s.SetupTestHelper().InitBasic()
s.RunForSystemAdminAndLocal("Delete user", func(c client.Client) {
printer.Clean()
previousVal := s.th.App.Config().ServiceSettings.EnableAPIUserDeletion
s.th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableAPIUserDeletion = true })
defer s.th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableAPIUserDeletion = *previousVal })
cmd := &cobra.Command{}
confirm := true
cmd.Flags().BoolVar(&confirm, "confirm", confirm, "confirm")
newUser := s.th.CreateUser()
err := deleteUsersCmdF(c, cmd, []string{newUser.Email})
s.Require().Nil(err)
s.Len(printer.GetLines(), 1)
s.Len(printer.GetErrorLines(), 0)
deletedUser := printer.GetLines()[0].(*model.User)
s.Require().Equal(newUser.Username, deletedUser.Username)
// expect user deleted
_, err = s.th.App.GetUser(newUser.Id)
s.Require().NotNil(err)
s.Require().Equal("GetUser: Unable to find the user., resource \"User\" not found, id: "+newUser.Id, err.Error())
})
s.RunForSystemAdminAndLocal("Delete nonexistent user", func(c client.Client) {
printer.Clean()
emailArg := "nonexistentUser@example.com"
var expectedErr *multierror.Error
expectedErr = multierror.Append(expectedErr, fmt.Errorf("user %s not found", emailArg))
previousVal := s.th.App.Config().ServiceSettings.EnableAPIUserDeletion
s.th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableAPIUserDeletion = true })
defer func() {
s.th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableAPIUserDeletion = *previousVal })
}()
cmd := &cobra.Command{}
confirm := true
cmd.Flags().BoolVar(&confirm, "confirm", confirm, "confirm")
err := deleteUsersCmdF(c, cmd, []string{emailArg})
s.Require().NotNil(err)
s.Require().EqualError(err, expectedErr.Error())
})
s.Run("Delete user without permission", func() {
printer.Clean()
previousVal := s.th.App.Config().ServiceSettings.EnableAPIUserDeletion
s.th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableAPIUserDeletion = true })
defer func() {
s.th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableAPIUserDeletion = *previousVal })
}()
cmd := &cobra.Command{}
confirm := true
cmd.Flags().BoolVar(&confirm, "confirm", confirm, "confirm")
newUser := s.th.CreateUser()
var expectedErr *multierror.Error
expectedErr = multierror.Append(expectedErr, fmt.Errorf("unable to delete user %s error: %w", newUser.Username,
fmt.Errorf("You do not have the appropriate permissions.")))
err := deleteUsersCmdF(s.th.Client, cmd, []string{newUser.Email})
s.Require().NotNil(err)
s.Require().EqualError(err, expectedErr.Error())
// expect user not deleted
user, err := s.th.App.GetUser(newUser.Id)
s.Require().Nil(err)
s.Require().Equal(newUser.Username, user.Username)
})
s.Run("Delete user with disabled config as system admin", func() {
printer.Clean()
previousVal := s.th.App.Config().ServiceSettings.EnableAPIUserDeletion
s.th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableAPIUserDeletion = false })
defer func() {
s.th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableAPIUserDeletion = *previousVal })
}()
cmd := &cobra.Command{}
confirm := true
cmd.Flags().BoolVar(&confirm, "confirm", confirm, "confirm")
newUser := s.th.CreateUser()
var expectedErr *multierror.Error
expectedErr = multierror.Append(expectedErr, fmt.Errorf("unable to delete user %s error: %w", newUser.Username,
fmt.Errorf("Permanent user deletion feature is not enabled. ServiceSettings.EnableAPIUserDeletion must be set to true to use this command. See https://mattermost.com/pl/environment-configuration-settings for more information.")))
err := deleteUsersCmdF(s.th.SystemAdminClient, cmd, []string{newUser.Email})
s.Require().NotNil(err)
s.Require().EqualError(err, expectedErr.Error())
// expect user not deleted
user, err := s.th.App.GetUser(newUser.Id)
s.Require().Nil(err)
s.Require().Equal(newUser.Username, user.Username)
})
s.Run("Delete user with disabled config as local client", func() {
printer.Clean()
previousVal := s.th.App.Config().ServiceSettings.EnableAPIUserDeletion
s.th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableAPIUserDeletion = false })
defer func() {
s.th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableAPIUserDeletion = *previousVal })
}()
cmd := &cobra.Command{}
confirm := true
cmd.Flags().BoolVar(&confirm, "confirm", confirm, "confirm")
newUser := s.th.CreateUser()
err := deleteUsersCmdF(s.th.LocalClient, cmd, []string{newUser.Email})
s.Require().Nil(err)
s.Len(printer.GetLines(), 1)
s.Len(printer.GetErrorLines(), 0)
deletedUser := printer.GetLines()[0].(*model.User)
s.Require().Equal(newUser.Username, deletedUser.Username)
// expect user deleted
_, err = s.th.App.GetUser(newUser.Id)
s.Require().NotNil(err)
s.Require().EqualError(err, "GetUser: Unable to find the user., resource \"User\" not found, id: "+newUser.Id)
})
}
func (s *MmctlE2ETestSuite) TestUserConvertCmdF() {
s.SetupTestHelper().InitBasic()
s.RunForAllClients("Error when no flag provided", func(c client.Client) {
printer.Clean()
emailArg := "example@example.com"
cmd := &cobra.Command{}
err := userConvertCmdF(c, cmd, []string{emailArg})
s.Require().Error(err)
s.Require().Len(printer.GetLines(), 0)
s.Equal("either \"user\" flag or \"bot\" flag should be provided", err.Error())
})
s.RunForAllClients("Error for invalid user", func(c client.Client) {
printer.Clean()
emailArg := "something@something.com"
cmd := &cobra.Command{}
cmd.Flags().Bool("bot", true, "")
err := userConvertCmdF(c, cmd, []string{emailArg})
s.Require().Len(printer.GetLines(), 0)
s.Require().Len(printer.GetErrorLines(), 0)
s.ErrorContains(err, "user something@something.com not found")
})
s.RunForSystemAdminAndLocal("Valid user to bot convert", func(c client.Client) {
printer.Clean()
user, _ := s.th.App.CreateUser(s.th.Context, &model.User{Email: s.th.GenerateTestEmail(), Username: model.NewUsername(), Password: model.NewId()})
email := user.Email
cmd := &cobra.Command{}
cmd.Flags().Bool("bot", true, "")
err := userConvertCmdF(c, cmd, []string{email})
s.Require().NoError(err)
s.Require().Len(printer.GetLines(), 1)
bot := printer.GetLines()[0].(*model.Bot)
s.Equal(user.Username, bot.Username)
s.Equal(user.Id, bot.UserId)
s.Equal(user.Id, bot.OwnerId)
s.Require().Len(printer.GetErrorLines(), 0)
})
s.Run("Permission error for valid user to bot convert", func() {
printer.Clean()
email := s.th.BasicUser2.Email
cmd := &cobra.Command{}
cmd.Flags().Bool("bot", true, "")
err := userConvertCmdF(s.th.Client, cmd, []string{email})
s.Require().Len(printer.GetLines(), 0)
s.Require().Len(printer.GetErrorLines(), 0)
s.ErrorContains(err, "You do not have the appropriate permissions")
})
s.RunForSystemAdminAndLocal("Valid bot to user convert", func(c client.Client) {
printer.Clean()
username := "fakeuser" + model.NewRandomString(10)
bot, _ := s.th.App.CreateBot(s.th.Context, &model.Bot{Username: username, DisplayName: username, OwnerId: username})
cmd := &cobra.Command{}
cmd.Flags().Bool("user", true, "")
cmd.Flags().String("password", "password", "")
err := userConvertCmdF(c, cmd, []string{bot.Username})
s.Require().NoError(err)
s.Require().Len(printer.GetLines(), 1)
user := printer.GetLines()[0].(*model.User)
s.Equal(user.Username, bot.Username)
s.Require().Len(printer.GetErrorLines(), 0)
})
s.Run("Permission error for valid bot to user convert", func() {
printer.Clean()
username := "fakeuser" + model.NewRandomString(10)
bot, _ := s.th.App.CreateBot(s.th.Context, &model.Bot{Username: username, DisplayName: username, OwnerId: username})
cmd := &cobra.Command{}
cmd.Flags().Bool("user", true, "")
cmd.Flags().String("password", "password", "")
err := userConvertCmdF(s.th.Client, cmd, []string{bot.Username})
s.Require().Error(err)
s.EqualError(err, "You do not have the appropriate permissions.")
s.Require().Len(printer.GetLines(), 0)
s.Require().Len(printer.GetErrorLines(), 0)
})
}
func (s *MmctlE2ETestSuite) TestDeleteAllUserCmd() {
s.SetupTestHelper().InitBasic()
s.Run("Delete all user as unpriviliged user should not work", func() {
printer.Clean()
cmd := &cobra.Command{}
confirm := true
cmd.Flags().BoolVar(&confirm, "confirm", confirm, "confirm")
err := deleteAllUsersCmdF(s.th.Client, cmd, []string{})
s.Require().NotNil(err)
s.Len(printer.GetLines(), 0)
s.Len(printer.GetErrorLines(), 0)
// expect users not deleted
users, err := s.th.App.GetUsersPage(&model.UserGetOptions{
Page: 0,
PerPage: 10,
}, true)
s.Require().Nil(err)
s.Require().NotZero(len(users))
})
s.Run("Delete all user as system admin through the port API should not work", func() {
printer.Clean()
cmd := &cobra.Command{}
confirm := true
cmd.Flags().BoolVar(&confirm, "confirm", confirm, "confirm")
err := deleteAllUsersCmdF(s.th.SystemAdminClient, cmd, []string{})
s.Require().NotNil(err)
s.Len(printer.GetLines(), 0)
s.Len(printer.GetErrorLines(), 0)
// expect users not deleted
users, err := s.th.App.GetUsersPage(&model.UserGetOptions{
Page: 0,
PerPage: 10,
}, true)
s.Require().Nil(err)
s.Require().NotZero(len(users))
})
s.Run("Delete all users through local mode should work correctly", func() {
printer.Clean()
// populate with some user
for range 10 {
userData := model.User{
Username: "fakeuser" + model.NewRandomString(10),
Password: "Pa$$word11",
Email: s.th.GenerateTestEmail(),
}
_, err := s.th.App.CreateUser(s.th.Context, &userData)
s.Require().Nil(err)
}
cmd := &cobra.Command{}
confirm := true
cmd.Flags().BoolVar(&confirm, "confirm", confirm, "confirm")
// delete all users only works on local mode
err := deleteAllUsersCmdF(s.th.LocalClient, cmd, []string{})
s.Require().Nil(err)
s.Len(printer.GetLines(), 1)
s.Len(printer.GetErrorLines(), 0)
s.Require().Equal(printer.GetLines()[0], "All users successfully deleted")
// expect users deleted
users, err := s.th.App.GetUsersPage(&model.UserGetOptions{
Page: 0,
PerPage: 10,
}, true)
s.Require().Nil(err)
s.Require().Zero(len(users))
})
}
func (s *MmctlE2ETestSuite) TestPromoteGuestToUserCmd() {
s.SetupEnterpriseTestHelper().InitBasic()
user, appErr := s.th.App.CreateUser(s.th.Context, &model.User{Email: s.th.GenerateTestEmail(), Username: model.NewUsername(), Password: model.NewId()})
s.Require().Nil(appErr)
s.th.App.UpdateConfig(func(c *model.Config) { *c.GuestAccountsSettings.Enable = true })
defer s.th.App.UpdateConfig(func(c *model.Config) { *c.GuestAccountsSettings.Enable = false })
s.Require().Nil(s.th.App.DemoteUserToGuest(s.th.Context, user))
s.RunForSystemAdminAndLocal("MM-T3936 Promote a guest to a user", func(c client.Client) {
printer.Clean()
err := promoteGuestToUserCmdF(c, nil, []string{user.Email})
s.Require().NoError(err)
defer s.Require().Nil(s.th.App.DemoteUserToGuest(s.th.Context, user))
s.Require().Len(printer.GetLines(), 1)
s.Require().Len(printer.GetErrorLines(), 0)
})
s.Run("MM-T3937 Promote a guest to a user with normal client", func() {
printer.Clean()
err := promoteGuestToUserCmdF(s.th.Client, nil, []string{user.Email})
s.Require().Error(err)
s.Require().Len(printer.GetLines(), 0)
s.Require().Len(printer.GetErrorLines(), 1)
s.Require().Equal(fmt.Sprintf("unable to promote guest %s: You do not have the appropriate permissions.", user.Email), printer.GetErrorLines()[0])
})
}
func (s *MmctlE2ETestSuite) TestDemoteUserToGuestCmd() {
s.SetupEnterpriseTestHelper().InitBasic()
user, appErr := s.th.App.CreateUser(s.th.Context, &model.User{Email: s.th.GenerateTestEmail(), Username: model.NewUsername(), Password: model.NewId()})
s.Require().Nil(appErr)
s.th.App.UpdateConfig(func(c *model.Config) { *c.GuestAccountsSettings.Enable = true })
defer s.th.App.UpdateConfig(func(c *model.Config) { *c.GuestAccountsSettings.Enable = false })
s.RunForSystemAdminAndLocal("MM-T3938 Demote a user to a guest", func(c client.Client) {
printer.Clean()
err := demoteUserToGuestCmdF(c, nil, []string{user.Email})
s.Require().Nil(err)
defer s.Require().Nil(s.th.App.PromoteGuestToUser(s.th.Context, user, ""))
s.Require().Len(printer.GetLines(), 1)
s.Require().Len(printer.GetErrorLines(), 0)
})
s.Run("MM-T3939 Demote a user to a guest with normal client", func() {
printer.Clean()
err := demoteUserToGuestCmdF(s.th.Client, nil, []string{user.Email})
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: You do not have the appropriate permissions.", user.Email), printer.GetErrorLines()[0])
})
}
func (s *MmctlE2ETestSuite) TestMigrateAuthCmd() {
s.SetupEnterpriseTestHelper().InitBasic()
configForLdap(s.th)
s.Require().NoError(s.th.App.Srv().Jobs.StartWorkers()) // we need to start workers do actual sync
ldapUser, appErr := s.th.App.CreateUser(s.th.Context, &model.User{
Email: s.th.GenerateTestEmail(),
Username: model.NewId(),
AuthData: model.NewPointer("test.user.1"),
AuthService: model.UserAuthServiceLdap,
})
s.Require().Nil(appErr)
samlUser, appErr := s.th.App.CreateUser(s.th.Context, &model.User{
Email: "success+devone@simulator.amazonses.com",
Username: "dev.one",
AuthData: model.NewPointer("dev.one"),
AuthService: model.UserAuthServiceSaml,
})
s.Require().Nil(appErr)
s.Run("Should fail when regular user tries to migrate auth", func() {
printer.Clean()
cmd := &cobra.Command{}
cmd.Flags().Bool("auto", true, "")
cmd.Flags().Bool("confirm", true, "")
err := migrateAuthCmdF(s.th.Client, cmd, []string{"ldap", "saml"})
s.Require().Error(err)
s.Require().Empty(printer.GetLines())
s.Require().Empty(printer.GetErrorLines())
})
s.RunForSystemAdminAndLocal("Migrate from ldap to saml", func(c client.Client) {
printer.Clean()
cmd := &cobra.Command{}
cmd.Flags().Bool("auto", true, "")
cmd.Flags().Bool("confirm", true, "")
err := migrateAuthCmdF(c, cmd, []string{"ldap", "saml"})
s.Require().NoError(err)
defer func() {
_, appErr := s.th.App.UpdateUserAuth(s.th.Context, ldapUser.Id, &model.UserAuth{
AuthData: model.NewPointer("test.user.1"),
AuthService: model.UserAuthServiceLdap,
})
s.Require().Nil(appErr)
newUser, appErr := s.th.App.UpdateUser(s.th.Context, ldapUser, false)
s.Require().Nil(appErr)
s.Require().Equal(model.UserAuthServiceLdap, newUser.AuthService)
}()
s.Require().Len(printer.GetLines(), 1)
s.Require().Equal("Successfully migrated accounts.", printer.GetLines()[0])
s.Require().Empty(printer.GetErrorLines())
updatedUser, appErr := s.th.App.GetUser(ldapUser.Id)
s.Require().Nil(appErr)
s.Require().Equal(model.UserAuthServiceSaml, updatedUser.AuthService)
})
s.RunForSystemAdminAndLocal("Migrate from saml to ldap", func(c client.Client) {
printer.Clean()
cmd := &cobra.Command{}
cmd.Flags().Bool("confirm", true, "")
cmd.Flags().Bool("force", true, "")
err := migrateAuthCmdF(c, cmd, []string{"saml", "ldap", "email"})
s.Require().NoError(err)
defer func() {
_, appErr := s.th.App.UpdateUserAuth(s.th.Context, samlUser.Id, &model.UserAuth{
AuthData: model.NewPointer("dev.one"),
AuthService: model.UserAuthServiceSaml,
})
s.Require().Nil(appErr)
newUser, appErr := s.th.App.UpdateUser(s.th.Context, samlUser, false)
s.Require().Nil(appErr)
s.Require().Equal(model.UserAuthServiceSaml, newUser.AuthService)
}()
s.Require().Len(printer.GetLines(), 1)
s.Require().Equal("Successfully migrated accounts.", printer.GetLines()[0])
s.Require().Empty(printer.GetErrorLines())
updatedUser, appErr := s.th.App.GetUser(samlUser.Id)
s.Require().Nil(appErr)
s.Require().Equal(model.UserAuthServiceLdap, updatedUser.AuthService)
})
}
func (s *MmctlE2ETestSuite) cleanUpPreferences(userID string) {
s.T().Helper()
// Delete any existing preferences
preferences, _, err := s.th.SystemAdminClient.GetPreferences(context.TODO(), userID)
s.NoError(err)
if len(preferences) == 0 {
return
}
_, err = s.th.SystemAdminClient.DeletePreferences(context.TODO(), userID, preferences)
s.NoError(err)
}
func (s *MmctlE2ETestSuite) TestPreferenceListCmd() {
s.SetupTestHelper().InitBasic()
s.cleanUpPreferences(s.th.BasicUser.Id)
s.cleanUpPreferences(s.th.BasicUser2.Id)
preference1 := model.Preference{UserId: s.th.BasicUser.Id, Category: "display_settings", Name: "collapsed_reply_threads", Value: "threads_view"}
_, err := s.th.SystemAdminClient.UpdatePreferences(context.TODO(), s.th.BasicUser.Id, model.Preferences{preference1})
s.NoError(err)
preference2 := model.Preference{UserId: s.th.BasicUser.Id, Category: "display_settings", Name: "colorize_usernames", Value: "threads_view"}
_, err = s.th.SystemAdminClient.UpdatePreferences(context.TODO(), s.th.BasicUser.Id, model.Preferences{preference2})
s.NoError(err)
preference3 := model.Preference{UserId: s.th.BasicUser.Id, Category: "drafts", Name: "drafts_tour_tip_showed", Value: `{"drafts_tour_tip_showed":true}`}
_, err = s.th.SystemAdminClient.UpdatePreferences(context.TODO(), s.th.BasicUser.Id, model.Preferences{preference3})
s.NoError(err)
preference4 := model.Preference{UserId: s.th.BasicUser2.Id, Category: "display_settings", Name: "collapsed_reply_threads", Value: "threads_view"}
_, err = s.th.SystemAdminClient.UpdatePreferences(context.TODO(), s.th.BasicUser2.Id, model.Preferences{preference4})
s.NoError(err)
s.Run("list all preferences for single user", func() {
printer.Clean()
cmd := &cobra.Command{}
cmd.Flags().StringP("category", "c", "", "")
err = preferencesListCmdF(s.th.Client, cmd, []string{s.th.BasicUser.Email})
s.Require().NoError(err)
s.Require().Len(printer.GetLines(), 3)
s.Require().Equal(preference1, printer.GetLines()[0])
s.Require().Equal(preference2, printer.GetLines()[1])
s.Require().Equal(preference3, printer.GetLines()[2])
s.Require().Len(printer.GetErrorLines(), 0)
})
s.Run("list filtered preferences for single user", func() {
printer.Clean()
cmd := &cobra.Command{}
cmd.Flags().StringP("category", "c", preference1.Category, "")
err = preferencesListCmdF(s.th.Client, cmd, []string{s.th.BasicUser.Email})
s.Require().NoError(err)
s.Require().Len(printer.GetLines(), 2)
s.Require().Equal(preference1, printer.GetLines()[0])
s.Require().Equal(preference2, printer.GetLines()[1])
s.Require().Len(printer.GetErrorLines(), 0)
})
s.Run("list all preferences for multiple users as admin", func() {
printer.Clean()
cmd := &cobra.Command{}
cmd.Flags().StringP("category", "c", "", "")
err = preferencesListCmdF(s.th.SystemAdminClient, cmd, []string{s.th.BasicUser.Email, s.th.BasicUser2.Email})
s.Require().NoError(err)
s.Require().Len(printer.GetLines(), 4)
s.Require().Equal(preference1, printer.GetLines()[0])
s.Require().Equal(preference2, printer.GetLines()[1])
s.Require().Equal(preference3, printer.GetLines()[2])
s.Require().Equal(preference4, printer.GetLines()[3])
s.Require().Len(printer.GetErrorLines(), 0)
})
s.Run("list filtered preferences for multiple users as admin", func() {
printer.Clean()
cmd := &cobra.Command{}
cmd.Flags().StringP("category", "c", preference1.Category, "")
err = preferencesListCmdF(s.th.SystemAdminClient, cmd, []string{s.th.BasicUser.Email, s.th.BasicUser2.Email})
s.Require().NoError(err)
s.Require().Len(printer.GetLines(), 3)
s.Require().Equal(preference1, printer.GetLines()[0])
s.Require().Equal(preference2, printer.GetLines()[1])
s.Require().Equal(preference4, printer.GetLines()[2])
s.Require().Len(printer.GetErrorLines(), 0)
})
s.Run("list preferences for multiple users as non-admin", func() {
printer.Clean()
cmd := &cobra.Command{}
cmd.Flags().StringP("category", "c", preference1.Category, "")
err = preferencesListCmdF(s.th.Client, cmd, []string{s.th.BasicUser.Email, s.th.BasicUser2.Email})
s.Require().Error(err)
})
}
func (s *MmctlE2ETestSuite) TestPreferenceGetCmd() {
s.SetupTestHelper().InitBasic()
s.cleanUpPreferences(s.th.BasicUser.Id)
s.cleanUpPreferences(s.th.BasicUser2.Id)
preference1 := model.Preference{UserId: s.th.BasicUser.Id, Category: "display_settings", Name: "collapsed_reply_threads", Value: "threads_view"}
_, err := s.th.SystemAdminClient.UpdatePreferences(context.TODO(), s.th.BasicUser.Id, model.Preferences{preference1})
s.NoError(err)
preference2 := model.Preference{UserId: s.th.BasicUser.Id, Category: "display_settings", Name: "colorize_usernames", Value: "threads_view"}
_, err = s.th.SystemAdminClient.UpdatePreferences(context.TODO(), s.th.BasicUser.Id, model.Preferences{preference2})
s.NoError(err)
preference3 := model.Preference{UserId: s.th.BasicUser.Id, Category: "drafts", Name: "drafts_tour_tip_showed", Value: `{"drafts_tour_tip_showed":true}`}
_, err = s.th.SystemAdminClient.UpdatePreferences(context.TODO(), s.th.BasicUser.Id, model.Preferences{preference3})
s.NoError(err)
preference4 := model.Preference{UserId: s.th.BasicUser2.Id, Category: "display_settings", Name: "collapsed_reply_threads", Value: "threads_view"}
_, err = s.th.SystemAdminClient.UpdatePreferences(context.TODO(), s.th.BasicUser2.Id, model.Preferences{preference4})
s.NoError(err)
s.Run("get preference for single user", func() {
printer.Clean()
cmd := &cobra.Command{}
cmd.Flags().StringP("category", "c", preference1.Category, "")
cmd.Flags().StringP("name", "n", preference1.Name, "")
err = preferencesGetCmdF(s.th.Client, cmd, []string{s.th.BasicUser.Email})
s.Require().NoError(err)
s.Require().Len(printer.GetLines(), 1)
s.Require().Equal(&preference1, printer.GetLines()[0])
s.Require().Len(printer.GetErrorLines(), 0)
})
s.Run("get preferences for multiple users as admin", func() {
printer.Clean()
cmd := &cobra.Command{}
cmd.Flags().StringP("category", "c", preference1.Category, "")
cmd.Flags().StringP("name", "n", preference1.Name, "")
err = preferencesGetCmdF(s.th.SystemAdminClient, cmd, []string{s.th.BasicUser.Email, s.th.BasicUser2.Email})
s.Require().NoError(err)
s.Require().Len(printer.GetLines(), 2)
s.Require().Equal(&preference1, printer.GetLines()[0])
s.Require().Equal(&preference4, printer.GetLines()[1])
s.Require().Len(printer.GetErrorLines(), 0)
})
s.Run("get preferences for multiple users as non-admin", func() {
printer.Clean()
cmd := &cobra.Command{}
cmd.Flags().StringP("category", "c", preference1.Category, "")
cmd.Flags().StringP("name", "n", preference1.Name, "")
err = preferencesGetCmdF(s.th.Client, cmd, []string{s.th.BasicUser.Email, s.th.BasicUser2.Email})
s.Require().Error(err)
})
}
func (s *MmctlE2ETestSuite) TestPreferenceUpdateCmd() {
s.SetupTestHelper().InitBasic()
preference1 := model.Preference{UserId: s.th.BasicUser.Id, Category: "display_settings", Name: "collapsed_reply_threads", Value: "threads_view"}
preference2 := model.Preference{UserId: s.th.BasicUser.Id, Category: "display_settings", Name: "colorize_usernames", Value: "threads_view"}
preference3 := model.Preference{UserId: s.th.BasicUser.Id, Category: "drafts", Name: "drafts_tour_tip_showed", Value: `{"drafts_tour_tip_showed":true}`}
preference4 := model.Preference{UserId: s.th.BasicUser2.Id, Category: "display_settings", Name: "collapsed_reply_threads", Value: "threads_view"}
setup := func() {
s.T().Helper()
s.cleanUpPreferences(s.th.BasicUser.Id)
s.cleanUpPreferences(s.th.BasicUser2.Id)
_, err := s.th.SystemAdminClient.UpdatePreferences(context.TODO(), s.th.BasicUser.Id, model.Preferences{preference1})
s.NoError(err)
_, err = s.th.SystemAdminClient.UpdatePreferences(context.TODO(), s.th.BasicUser.Id, model.Preferences{preference2})
s.NoError(err)
_, err = s.th.SystemAdminClient.UpdatePreferences(context.TODO(), s.th.BasicUser.Id, model.Preferences{preference3})
s.NoError(err)
_, err = s.th.SystemAdminClient.UpdatePreferences(context.TODO(), s.th.BasicUser2.Id, model.Preferences{preference4})
s.NoError(err)
}
s.Run("add new preference for single user", func() {
setup()
printer.Clean()
preferenceNew := model.Preference{UserId: s.th.BasicUser.Id, Category: "zzz_custom", Name: "new", Value: "value"}
cmd := &cobra.Command{}
cmd.Flags().StringP("category", "c", preferenceNew.Category, "")
cmd.Flags().StringP("name", "n", preferenceNew.Name, "")
cmd.Flags().StringP("value", "v", preferenceNew.Value, "")
err := preferencesUpdateCmdF(s.th.Client, cmd, []string{s.th.BasicUser.Email})
s.Require().NoError(err)
s.Require().Len(printer.GetErrorLines(), 0)
actualPreferencesUser1, _, err := s.th.SystemAdminClient.GetPreferences(context.TODO(), s.th.BasicUser.Id)
s.NoError(err)
s.Require().Len(actualPreferencesUser1, 4)
s.Require().Equal(preference1, actualPreferencesUser1[0])
s.Require().Equal(preference2, actualPreferencesUser1[1])
s.Require().Equal(preference3, actualPreferencesUser1[2])
s.Require().Equal(preferenceNew, actualPreferencesUser1[3])
// Second user unaffected
actualPreferencesUser2, _, err := s.th.SystemAdminClient.GetPreferences(context.TODO(), s.th.BasicUser2.Id)
s.NoError(err)
s.Require().Len(actualPreferencesUser2, 1)
s.Require().Equal(preference4, actualPreferencesUser2[0])
})
s.Run("add new preference for multiple users as admin", func() {
setup()
printer.Clean()
preferenceNew := model.Preference{UserId: s.th.BasicUser.Id, Category: "zzz_custom", Name: "new", Value: "value"}
preferenceNew2 := model.Preference{UserId: s.th.BasicUser2.Id, Category: "zzz_custom", Name: "new", Value: "value"}
cmd := &cobra.Command{}
cmd.Flags().StringP("category", "c", preferenceNew.Category, "")
cmd.Flags().StringP("name", "n", preferenceNew.Name, "")
cmd.Flags().StringP("value", "v", preferenceNew.Value, "")
err := preferencesUpdateCmdF(s.th.SystemAdminClient, cmd, []string{s.th.BasicUser.Email, s.th.BasicUser2.Email})
s.Require().NoError(err)
s.Require().Len(printer.GetErrorLines(), 0)
actualPreferencesUser1, _, err := s.th.SystemAdminClient.GetPreferences(context.TODO(), s.th.BasicUser.Id)
s.NoError(err)
s.Require().Len(actualPreferencesUser1, 4)
s.Require().Equal(preference1, actualPreferencesUser1[0])
s.Require().Equal(preference2, actualPreferencesUser1[1])
s.Require().Equal(preference3, actualPreferencesUser1[2])
s.Require().Equal(preferenceNew, actualPreferencesUser1[3])
// Second user unaffected
actualPreferencesUser2, _, err := s.th.SystemAdminClient.GetPreferences(context.TODO(), s.th.BasicUser2.Id)
s.NoError(err)
s.Require().Len(actualPreferencesUser2, 2)
s.Require().Equal(preference4, actualPreferencesUser2[0])
s.Require().Equal(preferenceNew2, actualPreferencesUser2[1])
})
s.Run("add new preference for multiple users as non-admin", func() {
setup()
printer.Clean()
preference := model.Preference{Category: "display_settings", Name: "collapsed_reply_threads", Value: "threads_view"}
cmd := &cobra.Command{}
cmd.Flags().StringP("category", "c", preference.Category, "")
cmd.Flags().StringP("name", "n", preference.Name, "")
cmd.Flags().StringP("value", "v", preference.Value, "")
err := preferencesUpdateCmdF(s.th.Client, cmd, []string{s.th.BasicUser.Email, s.th.BasicUser2.Email})
s.Require().Error(err)
})
s.Run("update existing preference for single user", func() {
setup()
printer.Clean()
preferenceUpdated := model.Preference{UserId: s.th.BasicUser.Id, Category: preference1.Category, Name: preference1.Name, Value: "new_value"}
cmd := &cobra.Command{}
cmd.Flags().StringP("category", "c", preferenceUpdated.Category, "")
cmd.Flags().StringP("name", "n", preferenceUpdated.Name, "")
cmd.Flags().StringP("value", "v", preferenceUpdated.Value, "")
err := preferencesUpdateCmdF(s.th.Client, cmd, []string{s.th.BasicUser.Email})
s.Require().NoError(err)
s.Require().Len(printer.GetErrorLines(), 0)
actualPreferencesUser1, _, err := s.th.SystemAdminClient.GetPreferences(context.TODO(), s.th.BasicUser.Id)
s.NoError(err)
s.Require().Len(actualPreferencesUser1, 3)
// We can't guarantee the order of preferences returned by the database since they are not sorted at SQL query level.
s.Require().Contains(actualPreferencesUser1, preferenceUpdated)
s.Require().Contains(actualPreferencesUser1, preference2)
s.Require().Contains(actualPreferencesUser1, preference3)
// Second user unaffected
actualPreferencesUser2, _, err := s.th.SystemAdminClient.GetPreferences(context.TODO(), s.th.BasicUser2.Id)
s.NoError(err)
s.Require().Len(actualPreferencesUser2, 1)
s.Require().Equal(preference4, actualPreferencesUser2[0])
})
s.Run("update existing preference for multiple users as admin", func() {
setup()
printer.Clean()
preferenceUpdated := model.Preference{UserId: s.th.BasicUser.Id, Category: preference1.Category, Name: preference1.Name, Value: "new_value"}
preferenceUpdated2 := model.Preference{UserId: s.th.BasicUser2.Id, Category: preference1.Category, Name: preference1.Name, Value: "new_value"}
cmd := &cobra.Command{}
cmd.Flags().StringP("category", "c", preferenceUpdated.Category, "")
cmd.Flags().StringP("name", "n", preferenceUpdated.Name, "")
cmd.Flags().StringP("value", "v", preferenceUpdated.Value, "")
err := preferencesUpdateCmdF(s.th.SystemAdminClient, cmd, []string{s.th.BasicUser.Email, s.th.BasicUser2.Email})
s.Require().NoError(err)
s.Require().Len(printer.GetErrorLines(), 0)
actualPreferencesUser1, _, err := s.th.SystemAdminClient.GetPreferences(context.TODO(), s.th.BasicUser.Id)
s.NoError(err)
s.Require().Len(actualPreferencesUser1, 3)
// We can't guarantee the order of preferences returned by the database since they are not sorted at SQL query level.
s.Require().Contains(actualPreferencesUser1, preferenceUpdated)
s.Require().Contains(actualPreferencesUser1, preference2)
s.Require().Contains(actualPreferencesUser1, preference3)
actualPreferencesUser2, _, err := s.th.SystemAdminClient.GetPreferences(context.TODO(), s.th.BasicUser2.Id)
s.NoError(err)
s.Require().Len(actualPreferencesUser2, 1)
s.Require().Equal(preferenceUpdated2, actualPreferencesUser2[0])
})
s.Run("update existing preference for multiple users as non-admin", func() {
setup()
printer.Clean()
preferenceUpdated := model.Preference{Category: preference1.Category, Name: preference1.Name, Value: "new_value"}
cmd := &cobra.Command{}
cmd.Flags().StringP("category", "c", preferenceUpdated.Category, "")
cmd.Flags().StringP("name", "n", preferenceUpdated.Name, "")
cmd.Flags().StringP("value", "v", preferenceUpdated.Value, "")
err := preferencesUpdateCmdF(s.th.Client, cmd, []string{s.th.BasicUser.Email, s.th.BasicUser2.Email})
s.Require().Error(err)
})
}
func (s *MmctlE2ETestSuite) TestPreferenceDeleteCmd() {
s.SetupTestHelper().InitBasic()
s.cleanUpPreferences(s.th.BasicUser.Id)
s.cleanUpPreferences(s.th.BasicUser2.Id)
preference1 := model.Preference{UserId: s.th.BasicUser.Id, Category: "display_settings", Name: "collapsed_reply_threads", Value: "threads_view"}
_, err := s.th.SystemAdminClient.UpdatePreferences(context.TODO(), s.th.BasicUser.Id, model.Preferences{preference1})
s.NoError(err)
preference2 := model.Preference{UserId: s.th.BasicUser.Id, Category: "display_settings", Name: "colorize_usernames", Value: "threads_view"}
_, err = s.th.SystemAdminClient.UpdatePreferences(context.TODO(), s.th.BasicUser.Id, model.Preferences{preference2})
s.NoError(err)
preference3 := model.Preference{UserId: s.th.BasicUser.Id, Category: "drafts", Name: "drafts_tour_tip_showed", Value: `{"drafts_tour_tip_showed":true}`}
_, err = s.th.SystemAdminClient.UpdatePreferences(context.TODO(), s.th.BasicUser.Id, model.Preferences{preference3})
s.NoError(err)
preference4 := model.Preference{UserId: s.th.BasicUser2.Id, Category: "display_settings", Name: "collapsed_reply_threads", Value: "threads_view"}
_, err = s.th.SystemAdminClient.UpdatePreferences(context.TODO(), s.th.BasicUser2.Id, model.Preferences{preference4})
s.NoError(err)
s.Run("delete non-existing preference for single user", func() {
printer.Clean()
preference := model.Preference{Category: "does", Name: "not"}
cmd := &cobra.Command{}
cmd.Flags().StringP("category", "c", preference.Category, "")
cmd.Flags().StringP("name", "n", preference.Name, "")
err := preferencesDeleteCmdF(s.th.Client, cmd, []string{s.th.BasicUser.Email})
s.Require().NoError(err)
s.Require().Len(printer.GetErrorLines(), 0)
actualPreferencesUser1, _, err := s.th.SystemAdminClient.GetPreferences(context.TODO(), s.th.BasicUser.Id)
s.NoError(err)
s.Require().Len(actualPreferencesUser1, 3)
s.Require().Equal(preference1, actualPreferencesUser1[0])
s.Require().Equal(preference2, actualPreferencesUser1[1])
s.Require().Equal(preference3, actualPreferencesUser1[2])
// Second user unaffected
actualPreferencesUser2, _, err := s.th.SystemAdminClient.GetPreferences(context.TODO(), s.th.BasicUser2.Id)
s.NoError(err)
s.Require().Len(actualPreferencesUser2, 1)
s.Require().Equal(preference4, actualPreferencesUser2[0])
})
s.Run("delete existing preference for single user", func() {
printer.Clean()
cmd := &cobra.Command{}
cmd.Flags().StringP("category", "c", preference1.Category, "")
cmd.Flags().StringP("name", "n", preference1.Name, "")
err := preferencesDeleteCmdF(s.th.Client, cmd, []string{s.th.BasicUser.Email})
s.Require().NoError(err)
s.Require().Len(printer.GetErrorLines(), 0)
actualPreferencesUser1, _, err := s.th.SystemAdminClient.GetPreferences(context.TODO(), s.th.BasicUser.Id)
s.NoError(err)
s.Require().Len(actualPreferencesUser1, 2)
s.Require().Equal(preference2, actualPreferencesUser1[0])
s.Require().Equal(preference3, actualPreferencesUser1[1])
// Second user unaffected
actualPreferencesUser2, _, err := s.th.SystemAdminClient.GetPreferences(context.TODO(), s.th.BasicUser2.Id)
s.NoError(err)
s.Require().Len(actualPreferencesUser2, 1)
s.Require().Equal(preference4, actualPreferencesUser2[0])
})
s.Run("delete existing preferences for multiple users as admin", func() {
printer.Clean()
cmd := &cobra.Command{}
cmd.Flags().StringP("category", "c", preference1.Category, "")
cmd.Flags().StringP("name", "n", preference1.Name, "")
err := preferencesDeleteCmdF(s.th.SystemAdminClient, cmd, []string{s.th.BasicUser.Email, s.th.BasicUser2.Email})
s.Require().NoError(err)
s.Require().Len(printer.GetErrorLines(), 0)
actualPreferencesUser1, _, err := s.th.SystemAdminClient.GetPreferences(context.TODO(), s.th.BasicUser.Id)
s.NoError(err)
s.Require().Len(actualPreferencesUser1, 2)
s.Require().Equal(preference2, actualPreferencesUser1[0])
s.Require().Equal(preference3, actualPreferencesUser1[1])
// Second user unaffected
actualPreferencesUser2, _, err := s.th.SystemAdminClient.GetPreferences(context.TODO(), s.th.BasicUser2.Id)
s.NoError(err)
s.Require().Len(actualPreferencesUser2, 0)
})
s.Run("delete existing preferences for multiple users as non-admin", func() {
printer.Clean()
cmd := &cobra.Command{}
cmd.Flags().StringP("category", "c", preference1.Category, "")
cmd.Flags().StringP("name", "n", preference1.Name, "")
err := preferencesDeleteCmdF(s.th.Client, cmd, []string{s.th.BasicUser.Email, s.th.BasicUser2.Email})
s.Require().Error(err)
})
}
func (s *MmctlE2ETestSuite) TestSendPasswordResetEmailCmd() {
s.SetupTestHelper().InitBasic()
s.RunForAllClients("all users can send password reset email", func(c client.Client) {
printer.Clean()
emailArg1 := "demo1@example.com"
emailArg2 := "demo2@example.com"
err := sendPasswordResetEmailCmdF(c, &cobra.Command{}, []string{emailArg1, emailArg2})
s.Require().NoError(err)
s.Require().Len(printer.GetLines(), 0)
s.Require().Len(printer.GetErrorLines(), 0)
})
s.RunForAllClients("send valid and invalid email", func(c client.Client) {
printer.Clean()
emailArg1 := "demo@example.com"
emailArg2 := "invalid.Email@example.com"
var expected error
expected = multierror.Append(expected, fmt.Errorf("invalid email '%s'", emailArg2))
err := sendPasswordResetEmailCmdF(c, &cobra.Command{}, []string{emailArg1, emailArg2})
s.Require().EqualError(err, expected.Error())
s.Require().Len(printer.GetErrorLines(), 1)
})
s.RunForAllClients("no arguments passed", func(c client.Client) {
printer.Clean()
err := sendPasswordResetEmailCmdF(c, &cobra.Command{}, []string{})
s.Require().EqualError(err, "expected at least one argument. See help text for details")
})
}
func (s *MmctlE2ETestSuite) TestUserEditUsernameCmd() {
s.SetupTestHelper().InitBasic()
user, appErr := s.th.App.CreateUser(s.th.Context, &model.User{
Email: s.th.GenerateTestEmail(),
Username: model.NewUsername(),
Password: model.NewId(),
})
s.Require().Nil(appErr)
s.RunForSystemAdminAndLocal("Edit username successfully", func(c client.Client) {
printer.Clean()
oldUsername := user.Username
newUsername := "editedusername" + model.NewRandomString(5)
err := userEditUsernameCmdF(c, &cobra.Command{}, []string{user.Username, newUsername})
s.Require().Nil(err)
s.Require().Len(printer.GetLines(), 1)
s.Require().Len(printer.GetErrorLines(), 0)
// Verify username was updated
updatedUser, appErr := s.th.App.GetUser(user.Id)
s.Require().Nil(appErr)
s.Require().Equal(newUsername, updatedUser.Username)
// Restore original username for next test
user.Username = oldUsername
_, appErr = s.th.App.UpdateUser(s.th.Context, user, false)
s.Require().Nil(appErr)
})
s.Run("Edit username without permission", func() {
printer.Clean()
newUsername := "unauthorizedusername"
err := userEditUsernameCmdF(s.th.Client, &cobra.Command{}, []string{user.Username, newUsername})
s.Require().Error(err)
s.Require().Len(printer.GetLines(), 0)
s.Require().Len(printer.GetErrorLines(), 0)
// Verify username was not changed
unchangedUser, appErr := s.th.App.GetUser(user.Id)
s.Require().Nil(appErr)
s.Require().Equal(user.Username, unchangedUser.Username)
})
s.RunForAllClients("Edit username with invalid username", func(c client.Client) {
printer.Clean()
invalidUsername := "invalid username with spaces"
err := userEditUsernameCmdF(c, &cobra.Command{}, []string{user.Username, invalidUsername})
s.Require().Error(err)
s.Require().EqualError(err, "invalid username: '"+invalidUsername+"'")
s.Require().Len(printer.GetLines(), 0)
s.Require().Len(printer.GetErrorLines(), 0)
// Verify username was not changed
unchangedUser, appErr := s.th.App.GetUser(user.Id)
s.Require().Nil(appErr)
s.Require().Equal(user.Username, unchangedUser.Username)
})
s.RunForAllClients("Edit username for nonexistent user", func(c client.Client) {
printer.Clean()
nonexistentUser := "nonexistentuser"
newUsername := "newusername"
err := userEditUsernameCmdF(c, &cobra.Command{}, []string{nonexistentUser, newUsername})
s.Require().Error(err)
s.Require().EqualError(err, "user "+nonexistentUser+" not found")
s.Require().Len(printer.GetLines(), 0)
s.Require().Len(printer.GetErrorLines(), 0)
})
}
func (s *MmctlE2ETestSuite) TestUserEditEmailCmd() {
s.SetupTestHelper().InitBasic()
user, appErr := s.th.App.CreateUser(s.th.Context, &model.User{
Email: s.th.GenerateTestEmail(),
Username: model.NewUsername(),
Password: model.NewId(),
})
s.Require().Nil(appErr)
s.RunForSystemAdminAndLocal("Edit email successfully", func(c client.Client) {
printer.Clean()
oldEmail := user.Email
newEmail := "newemail" + model.NewRandomString(5) + "@example.com"
err := userEditEmailCmdF(c, &cobra.Command{}, []string{user.Username, newEmail})
s.Require().Nil(err)
s.Require().Len(printer.GetLines(), 1)
s.Require().Len(printer.GetErrorLines(), 0)
// Verify email was updated
updatedUser, appErr := s.th.App.GetUser(user.Id)
s.Require().Nil(appErr)
s.Require().Equal(newEmail, updatedUser.Email)
// Restore original email for next test
user.Email = oldEmail
_, appErr = s.th.App.UpdateUser(s.th.Context, user, false)
s.Require().Nil(appErr)
})
s.Run("Edit email without permission", func() {
printer.Clean()
newEmail := "unauthorized@example.com"
err := userEditEmailCmdF(s.th.Client, &cobra.Command{}, []string{user.Username, newEmail})
s.Require().Error(err)
s.Require().Len(printer.GetLines(), 0)
s.Require().Len(printer.GetErrorLines(), 0)
// Verify email was not changed
unchangedUser, appErr := s.th.App.GetUser(user.Id)
s.Require().Nil(appErr)
s.Require().Equal(user.Email, unchangedUser.Email)
})
s.RunForAllClients("Edit email with invalid email", func(c client.Client) {
printer.Clean()
invalidEmail := "invalidemail"
err := userEditEmailCmdF(c, &cobra.Command{}, []string{user.Username, invalidEmail})
s.Require().Error(err)
s.Require().EqualError(err, "invalid email: '"+invalidEmail+"'")
s.Require().Len(printer.GetLines(), 0)
s.Require().Len(printer.GetErrorLines(), 0)
// Verify email was not changed
unchangedUser, appErr := s.th.App.GetUser(user.Id)
s.Require().Nil(appErr)
s.Require().Equal(user.Email, unchangedUser.Email)
})
s.RunForAllClients("Edit email for nonexistent user", func(c client.Client) {
printer.Clean()
nonexistentUser := "nonexistentuser"
newEmail := "newemail@example.com"
err := userEditEmailCmdF(c, &cobra.Command{}, []string{nonexistentUser, newEmail})
s.Require().Error(err)
s.Require().EqualError(err, "user "+nonexistentUser+" not found")
s.Require().Len(printer.GetLines(), 0)
s.Require().Len(printer.GetErrorLines(), 0)
})
}
func (s *MmctlE2ETestSuite) TestUserEditAuthdataCmd() {
s.SetupTestHelper().InitBasic()
user, appErr := s.th.App.CreateUser(s.th.Context, &model.User{
Email: s.th.GenerateTestEmail(),
Username: model.NewUsername(),
AuthData: model.NewPointer("existingauthdata"),
AuthService: model.UserAuthServiceLdap,
})
s.Require().Nil(appErr)
newAuthdata := "newauthdata123"
s.Run("Edit authdata without permission", func() {
printer.Clean()
err := userEditAuthdataCmdF(s.th.Client, &cobra.Command{}, []string{user.Username, newAuthdata})
s.Require().Error(err)
s.Require().Len(printer.GetLines(), 0)
s.Require().Len(printer.GetErrorLines(), 0)
// Verify authdata was not changed
unchangedUser, appErr := s.th.App.GetUser(user.Id)
s.Require().Nil(appErr)
s.Require().NotNil(unchangedUser.AuthData)
s.Require().Equal("existingauthdata", *unchangedUser.AuthData)
})
s.RunForSystemAdminAndLocal("Clear authdata returns error", func(c client.Client) {
printer.Clean()
// Attempt to clear authdata with empty string should return error
err := userEditAuthdataCmdF(c, &cobra.Command{}, []string{user.Username, ""})
s.Require().Error(err)
s.Require().Len(printer.GetLines(), 0)
s.Require().Len(printer.GetErrorLines(), 0)
// Verify authdata was not changed
unchangedUser, appErr := s.th.App.GetUser(user.Id)
s.Require().Nil(appErr)
s.Require().NotNil(unchangedUser.AuthData)
s.Require().Equal("existingauthdata", *unchangedUser.AuthData)
})
s.RunForSystemAdminAndLocal("Edit authdata with too long value", func(c client.Client) {
printer.Clean()
// Create authdata longer than maximum allowed length
longAuthdata := make([]byte, model.UserAuthDataMaxLength+1)
for i := range longAuthdata {
longAuthdata[i] = 'a'
}
err := userEditAuthdataCmdF(c, &cobra.Command{}, []string{user.Username, string(longAuthdata)})
s.Require().Error(err)
s.Require().EqualError(err, fmt.Sprintf("authdata too long. Maximum length is %d characters", model.UserAuthDataMaxLength))
s.Require().Len(printer.GetLines(), 0)
s.Require().Len(printer.GetErrorLines(), 0)
// Verify authdata was not changed
unchangedUser, appErr := s.th.App.GetUser(user.Id)
s.Require().Nil(appErr)
s.Require().NotNil(unchangedUser.AuthData)
s.Require().Equal("existingauthdata", *unchangedUser.AuthData)
})
s.RunForSystemAdminAndLocal("Edit authdata for nonexistent user", func(c client.Client) {
printer.Clean()
nonexistentUser := "nonexistentuser"
err := userEditAuthdataCmdF(c, &cobra.Command{}, []string{nonexistentUser, newAuthdata})
s.Require().Error(err)
s.Require().EqualError(err, "user "+nonexistentUser+" not found")
s.Require().Len(printer.GetLines(), 0)
s.Require().Len(printer.GetErrorLines(), 0)
})
s.RunForSystemAdminAndLocal("Edit authdata successfully", func(c client.Client) {
printer.Clean()
err := userEditAuthdataCmdF(c, &cobra.Command{}, []string{user.Username, newAuthdata})
s.Require().Nil(err)
s.Require().Len(printer.GetLines(), 1)
s.Require().Len(printer.GetErrorLines(), 0)
// Verify authdata was updated
updatedUser, appErr := s.th.App.GetUser(user.Id)
s.Require().Nil(appErr)
s.Require().NotNil(updatedUser.AuthData)
s.Require().Equal(newAuthdata, *updatedUser.AuthData)
})
}