github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/cmd/juju/user/add_test.go (about)

     1  // Copyright 2014 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package user_test
     5  
     6  import (
     7  	"strings"
     8  
     9  	"github.com/juju/cmd"
    10  	"github.com/juju/cmd/cmdtesting"
    11  	"github.com/juju/errors"
    12  	jc "github.com/juju/testing/checkers"
    13  	gc "gopkg.in/check.v1"
    14  	"gopkg.in/juju/names.v2"
    15  
    16  	"github.com/juju/juju/api/base"
    17  	"github.com/juju/juju/apiserver/common"
    18  	"github.com/juju/juju/apiserver/params"
    19  	"github.com/juju/juju/cmd/juju/user"
    20  	"github.com/juju/juju/testing"
    21  )
    22  
    23  // All of the functionality of the AddUser api call is contained elsewhere.
    24  // This suite provides basic tests for the "add-user" command
    25  type UserAddCommandSuite struct {
    26  	BaseSuite
    27  	mockAPI *mockAddUserAPI
    28  }
    29  
    30  var _ = gc.Suite(&UserAddCommandSuite{})
    31  
    32  func (s *UserAddCommandSuite) SetUpTest(c *gc.C) {
    33  	s.BaseSuite.SetUpTest(c)
    34  	s.mockAPI = &mockAddUserAPI{}
    35  	s.mockAPI.secretKey = []byte(strings.Repeat("X", 32))
    36  }
    37  
    38  func (s *UserAddCommandSuite) run(c *gc.C, args ...string) (*cmd.Context, error) {
    39  	addCommand, _ := user.NewAddCommandForTest(s.mockAPI, s.store, &mockModelAPI{})
    40  	return cmdtesting.RunCommand(c, addCommand, args...)
    41  }
    42  
    43  func (s *UserAddCommandSuite) TestInit(c *gc.C) {
    44  	for i, test := range []struct {
    45  		args        []string
    46  		user        string
    47  		displayname string
    48  		models      string
    49  		acl         string
    50  		outPath     string
    51  		errorString string
    52  	}{{
    53  		errorString: "no username supplied",
    54  	}, {
    55  		args: []string{"foobar"},
    56  		user: "foobar",
    57  	}, {
    58  		args:        []string{"foobar", "Foo Bar"},
    59  		user:        "foobar",
    60  		displayname: "Foo Bar",
    61  	}, {
    62  		args:        []string{"foobar", "Foo Bar", "extra"},
    63  		errorString: `unrecognized args: \["extra"\]`,
    64  	}, {
    65  		args: []string{"foobar"},
    66  		user: "foobar",
    67  	}, {
    68  		args: []string{"foobar"},
    69  		user: "foobar",
    70  	}} {
    71  		c.Logf("test %d (%q)", i, test.args)
    72  		wrappedCommand, command := user.NewAddCommandForTest(s.mockAPI, s.store, &mockModelAPI{})
    73  		err := cmdtesting.InitCommand(wrappedCommand, test.args)
    74  		if test.errorString == "" {
    75  			c.Check(err, jc.ErrorIsNil)
    76  			c.Check(command.User, gc.Equals, test.user)
    77  			c.Check(command.DisplayName, gc.Equals, test.displayname)
    78  		} else {
    79  			c.Check(err, gc.ErrorMatches, test.errorString)
    80  		}
    81  	}
    82  }
    83  
    84  func (s *UserAddCommandSuite) TestAddUserWithUsername(c *gc.C) {
    85  	context, err := s.run(c, "foobar")
    86  	c.Assert(err, jc.ErrorIsNil)
    87  	c.Assert(s.mockAPI.username, gc.Equals, "foobar")
    88  	c.Assert(s.mockAPI.displayname, gc.Equals, "")
    89  	expected := `
    90  User "foobar" added
    91  Please send this command to foobar:
    92      juju register MEQTBmZvb2JhcjAPEw0wLjEuMi4zOjEyMzQ1BCBYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWBMHdGVzdGluZwAA
    93  
    94  "foobar" has not been granted access to any models. You can use "juju grant" to grant access.
    95  `[1:]
    96  	c.Assert(cmdtesting.Stdout(context), gc.Equals, expected)
    97  	c.Assert(cmdtesting.Stderr(context), gc.Equals, "")
    98  }
    99  
   100  func (s *UserAddCommandSuite) TestAddUserWithUsernameAndDisplayname(c *gc.C) {
   101  	context, err := s.run(c, "foobar", "Foo Bar")
   102  	c.Assert(err, jc.ErrorIsNil)
   103  	c.Assert(s.mockAPI.username, gc.Equals, "foobar")
   104  	c.Assert(s.mockAPI.displayname, gc.Equals, "Foo Bar")
   105  	expected := `
   106  User "Foo Bar (foobar)" added
   107  Please send this command to foobar:
   108      juju register MEQTBmZvb2JhcjAPEw0wLjEuMi4zOjEyMzQ1BCBYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWBMHdGVzdGluZwAA
   109  
   110  "Foo Bar (foobar)" has not been granted access to any models. You can use "juju grant" to grant access.
   111  `[1:]
   112  	c.Assert(cmdtesting.Stdout(context), gc.Equals, expected)
   113  	c.Assert(cmdtesting.Stderr(context), gc.Equals, "")
   114  }
   115  
   116  func (s *UserAddCommandSuite) TestUserRegistrationString(c *gc.C) {
   117  	// Ensure that the user registration string only contains alphanumerics.
   118  	for i := 0; i < 3; i++ {
   119  		s.mockAPI.secretKey = []byte(strings.Repeat("X", 32+i))
   120  		context, err := s.run(c, "foobar", "Foo Bar")
   121  		c.Assert(err, jc.ErrorIsNil)
   122  		lines := strings.Split(cmdtesting.Stdout(context), "\n")
   123  		c.Assert(lines, gc.HasLen, 6)
   124  		c.Assert(lines[2], gc.Matches, `^\s+juju register [A-Za-z0-9]+$`)
   125  	}
   126  }
   127  
   128  type mockModelAPI struct{}
   129  
   130  func (m *mockModelAPI) ListModels(user string) ([]base.UserModel, error) {
   131  	return []base.UserModel{{Name: "model", UUID: "modeluuid", Owner: "current-user"}}, nil
   132  }
   133  
   134  func (m *mockModelAPI) Close() error {
   135  	return nil
   136  }
   137  
   138  func (s *UserAddCommandSuite) TestBlockAddUser(c *gc.C) {
   139  	// Block operation
   140  	s.mockAPI.blocked = true
   141  	_, err := s.run(c, "foobar", "Foo Bar")
   142  	testing.AssertOperationWasBlocked(c, err, ".*To enable changes.*")
   143  }
   144  
   145  func (s *UserAddCommandSuite) TestAddUserErrorResponse(c *gc.C) {
   146  	s.mockAPI.failMessage = "failed to create user, chaos ensues"
   147  	_, err := s.run(c, "foobar")
   148  	c.Assert(err, gc.ErrorMatches, s.mockAPI.failMessage)
   149  }
   150  
   151  func (s *UserAddCommandSuite) TestAddUserUnauthorizedMentionsJujuGrant(c *gc.C) {
   152  	s.mockAPI.addError = &params.Error{
   153  		Message: "permission denied",
   154  		Code:    params.CodeUnauthorized,
   155  	}
   156  	ctx, _ := s.run(c, "foobar")
   157  	errString := strings.Replace(cmdtesting.Stderr(ctx), "\n", " ", -1)
   158  	c.Assert(errString, gc.Matches, `.*juju grant.*`)
   159  }
   160  
   161  type mockAddUserAPI struct {
   162  	addError    error
   163  	failMessage string
   164  	blocked     bool
   165  	secretKey   []byte
   166  
   167  	username    string
   168  	displayname string
   169  	password    string
   170  }
   171  
   172  func (m *mockAddUserAPI) AddUser(username, displayname, password string) (names.UserTag, []byte, error) {
   173  	if m.blocked {
   174  		return names.UserTag{}, nil, common.OperationBlockedError("the operation has been blocked")
   175  	}
   176  	if m.addError != nil {
   177  		return names.UserTag{}, nil, m.addError
   178  	}
   179  	m.username = username
   180  	m.displayname = displayname
   181  	m.password = password
   182  	if m.failMessage != "" {
   183  		return names.UserTag{}, nil, errors.New(m.failMessage)
   184  	}
   185  	return names.NewLocalUserTag(username), m.secretKey, nil
   186  }
   187  
   188  func (*mockAddUserAPI) Close() error {
   189  	return nil
   190  }