github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/state/user_test.go (about)

     1  // Copyright 2013, 2014 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package state_test
     5  
     6  import (
     7  	"fmt"
     8  	"regexp"
     9  	"time"
    10  
    11  	"github.com/juju/errors"
    12  	jc "github.com/juju/testing/checkers"
    13  	"github.com/juju/utils"
    14  	gc "gopkg.in/check.v1"
    15  	"gopkg.in/juju/names.v2"
    16  
    17  	"github.com/juju/juju/permission"
    18  	"github.com/juju/juju/state"
    19  	"github.com/juju/juju/testing"
    20  	"github.com/juju/juju/testing/factory"
    21  )
    22  
    23  type UserSuite struct {
    24  	ConnSuite
    25  }
    26  
    27  var _ = gc.Suite(&UserSuite{})
    28  
    29  func (s *UserSuite) TestAddInvalidNames(c *gc.C) {
    30  	for _, name := range []string{
    31  		"",
    32  		"a",
    33  		"b^b",
    34  		"a.",
    35  		"a-",
    36  		"user@local",
    37  		"@ubuntuone",
    38  	} {
    39  		c.Logf("check invalid name %q", name)
    40  		user, err := s.State.AddUser(name, "ignored", "ignored", "ignored")
    41  		c.Check(err, gc.ErrorMatches, `invalid user name "`+regexp.QuoteMeta(name)+`"`)
    42  		c.Check(user, gc.IsNil)
    43  	}
    44  }
    45  
    46  func (s *UserSuite) TestAddUser(c *gc.C) {
    47  	name := "f00-Bar.ram77"
    48  	displayName := "Display"
    49  	password := "password"
    50  	creator := "admin"
    51  
    52  	now := testing.NonZeroTime().Round(time.Second).UTC()
    53  
    54  	user, err := s.State.AddUser(name, displayName, password, creator)
    55  	c.Assert(err, jc.ErrorIsNil)
    56  	c.Assert(user, gc.NotNil)
    57  	c.Assert(user.Name(), gc.Equals, name)
    58  	c.Assert(user.DisplayName(), gc.Equals, displayName)
    59  	c.Assert(user.PasswordValid(password), jc.IsTrue)
    60  	c.Assert(user.CreatedBy(), gc.Equals, creator)
    61  	c.Assert(user.DateCreated().After(now) ||
    62  		user.DateCreated().Equal(now), jc.IsTrue)
    63  	lastLogin, err := user.LastLogin()
    64  	c.Assert(err, jc.Satisfies, state.IsNeverLoggedInError)
    65  	c.Assert(lastLogin, gc.DeepEquals, time.Time{})
    66  
    67  	user, err = s.State.User(user.UserTag())
    68  	c.Assert(err, jc.ErrorIsNil)
    69  	c.Assert(user, gc.NotNil)
    70  	c.Assert(user.Name(), gc.Equals, name)
    71  	c.Assert(user.DisplayName(), gc.Equals, displayName)
    72  	c.Assert(user.PasswordValid(password), jc.IsTrue)
    73  	c.Assert(user.CreatedBy(), gc.Equals, creator)
    74  	c.Assert(user.DateCreated().After(now) ||
    75  		user.DateCreated().Equal(now), jc.IsTrue)
    76  	lastLogin, err = user.LastLogin()
    77  	c.Assert(err, jc.Satisfies, state.IsNeverLoggedInError)
    78  	c.Assert(lastLogin, gc.DeepEquals, time.Time{})
    79  }
    80  
    81  func (s *UserSuite) TestCheckUserExists(c *gc.C) {
    82  	user := s.Factory.MakeUser(c, nil)
    83  	exists, err := state.CheckUserExists(s.State, user.Name())
    84  	c.Assert(err, jc.ErrorIsNil)
    85  	c.Assert(exists, jc.IsTrue)
    86  	exists, err = state.CheckUserExists(s.State, "notAUser")
    87  	c.Assert(err, jc.ErrorIsNil)
    88  	c.Assert(exists, jc.IsFalse)
    89  }
    90  
    91  func (s *UserSuite) TestString(c *gc.C) {
    92  	user := s.Factory.MakeUser(c, &factory.UserParams{Name: "foo"})
    93  	c.Assert(user.String(), gc.Equals, "foo@local")
    94  }
    95  
    96  func (s *UserSuite) TestUpdateLastLogin(c *gc.C) {
    97  	now := testing.NonZeroTime().Round(time.Second).UTC()
    98  	user := s.Factory.MakeUser(c, nil)
    99  	err := user.UpdateLastLogin()
   100  	c.Assert(err, jc.ErrorIsNil)
   101  	lastLogin, err := user.LastLogin()
   102  	c.Assert(err, jc.ErrorIsNil)
   103  	c.Assert(lastLogin.After(now) ||
   104  		lastLogin.Equal(now), jc.IsTrue)
   105  }
   106  
   107  func (s *UserSuite) TestSetPassword(c *gc.C) {
   108  	user := s.Factory.MakeUser(c, nil)
   109  	testSetPassword(c, func() (state.Authenticator, error) {
   110  		return s.State.User(user.UserTag())
   111  	})
   112  }
   113  
   114  func (s *UserSuite) TestAddUserSetsSalt(c *gc.C) {
   115  	user := s.Factory.MakeUser(c, &factory.UserParams{Password: "a-password"})
   116  	salt, hash := state.GetUserPasswordSaltAndHash(user)
   117  	c.Assert(hash, gc.Not(gc.Equals), "")
   118  	c.Assert(salt, gc.Not(gc.Equals), "")
   119  	c.Assert(utils.UserPasswordHash("a-password", salt), gc.Equals, hash)
   120  	c.Assert(user.PasswordValid("a-password"), jc.IsTrue)
   121  }
   122  
   123  func (s *UserSuite) TestSetPasswordChangesSalt(c *gc.C) {
   124  	user := s.Factory.MakeUser(c, nil)
   125  	origSalt, origHash := state.GetUserPasswordSaltAndHash(user)
   126  	c.Assert(origSalt, gc.Not(gc.Equals), "")
   127  	user.SetPassword("a-password")
   128  	newSalt, newHash := state.GetUserPasswordSaltAndHash(user)
   129  	c.Assert(newSalt, gc.Not(gc.Equals), "")
   130  	c.Assert(newSalt, gc.Not(gc.Equals), origSalt)
   131  	c.Assert(newHash, gc.Not(gc.Equals), origHash)
   132  	c.Assert(user.PasswordValid("a-password"), jc.IsTrue)
   133  }
   134  
   135  func (s *UserSuite) TestRemoveUserNonExistent(c *gc.C) {
   136  	err := s.State.RemoveUser(names.NewUserTag("harvey"))
   137  	c.Assert(errors.IsNotFound(err), jc.IsTrue)
   138  }
   139  
   140  func isDeletedUserError(err error) bool {
   141  	_, ok := errors.Cause(err).(state.DeletedUserError)
   142  	return ok
   143  }
   144  
   145  func (s *UserSuite) TestAllUsersSkipsDeletedUsers(c *gc.C) {
   146  	user := s.Factory.MakeUser(c, &factory.UserParams{Name: "one"})
   147  	_ = s.Factory.MakeUser(c, &factory.UserParams{Name: "two"})
   148  	_ = s.Factory.MakeUser(c, &factory.UserParams{Name: "three"})
   149  
   150  	all, err := s.State.AllUsers(true)
   151  	c.Check(err, jc.ErrorIsNil)
   152  	c.Check(len(all), jc.DeepEquals, 4)
   153  
   154  	var got []string
   155  	for _, u := range all {
   156  		got = append(got, u.Name())
   157  	}
   158  	c.Check(got, jc.SameContents, []string{"test-admin", "one", "two", "three"})
   159  
   160  	s.State.RemoveUser(user.UserTag())
   161  
   162  	all, err = s.State.AllUsers(true)
   163  	got = nil
   164  	for _, u := range all {
   165  		got = append(got, u.Name())
   166  	}
   167  	c.Check(err, jc.ErrorIsNil)
   168  	c.Check(len(all), jc.DeepEquals, 3)
   169  	c.Check(got, jc.SameContents, []string{"test-admin", "two", "three"})
   170  
   171  }
   172  
   173  func (s *UserSuite) TestRemoveUser(c *gc.C) {
   174  	user := s.Factory.MakeUser(c, &factory.UserParams{Password: "so sekrit"})
   175  
   176  	// Assert user exists and can authenticate.
   177  	c.Assert(user.PasswordValid("so sekrit"), jc.IsTrue)
   178  
   179  	// Look for the user.
   180  	u, err := s.State.User(user.UserTag())
   181  	c.Check(err, jc.ErrorIsNil)
   182  	c.Assert(u, jc.DeepEquals, user)
   183  
   184  	// Remove the user.
   185  	err = s.State.RemoveUser(user.UserTag())
   186  	c.Check(err, jc.ErrorIsNil)
   187  
   188  	// Check that we cannot update last login.
   189  	err = u.UpdateLastLogin()
   190  	c.Check(err, gc.NotNil)
   191  	c.Check(isDeletedUserError(err), jc.IsTrue)
   192  	c.Assert(err.Error(), jc.DeepEquals,
   193  		fmt.Sprintf("cannot update last login: user %q deleted", user.Name()))
   194  
   195  	// Check that we cannot set a password.
   196  	err = u.SetPassword("should fail too")
   197  	c.Check(err, gc.NotNil)
   198  	c.Check(isDeletedUserError(err), jc.IsTrue)
   199  	c.Assert(err.Error(), jc.DeepEquals,
   200  		fmt.Sprintf("cannot set password: user %q deleted", user.Name()))
   201  
   202  	// Check that we cannot set the password hash.
   203  	err = u.SetPasswordHash("also", "fail")
   204  	c.Check(err, gc.NotNil)
   205  	c.Check(isDeletedUserError(err), jc.IsTrue)
   206  	c.Assert(err.Error(), jc.DeepEquals,
   207  		fmt.Sprintf("cannot set password hash: user %q deleted", user.Name()))
   208  
   209  	// Check that we cannot validate a password.
   210  	c.Assert(u.PasswordValid("should fail"), jc.IsFalse)
   211  
   212  	// Check that we cannot enable the user.
   213  	err = u.Enable()
   214  	c.Check(err, gc.NotNil)
   215  	c.Check(isDeletedUserError(err), jc.IsTrue)
   216  	c.Assert(err.Error(), jc.DeepEquals,
   217  		fmt.Sprintf("cannot enable: user %q deleted", user.Name()))
   218  
   219  	// Check that we cannot disable the user.
   220  	err = u.Disable()
   221  	c.Check(err, gc.NotNil)
   222  	c.Check(isDeletedUserError(err), jc.IsTrue)
   223  	c.Assert(err.Error(), jc.DeepEquals,
   224  		fmt.Sprintf("cannot disable: user %q deleted", user.Name()))
   225  
   226  	// Check again to verify the user cannot be retrieved.
   227  	u, err = s.State.User(user.UserTag())
   228  	c.Check(err, jc.Satisfies, errors.IsUserNotFound)
   229  }
   230  
   231  func (s *UserSuite) TestRemoveUserRemovesUserAccess(c *gc.C) {
   232  	user := s.Factory.MakeUser(c, &factory.UserParams{Password: "so sekrit"})
   233  
   234  	// Assert user exists and can authenticate.
   235  	c.Assert(user.PasswordValid("so sekrit"), jc.IsTrue)
   236  
   237  	s.State.SetUserAccess(user.UserTag(), s.State.ModelTag(), permission.AdminAccess)
   238  	s.State.SetUserAccess(user.UserTag(), s.State.ControllerTag(), permission.SuperuserAccess)
   239  
   240  	uam, err := s.State.UserAccess(user.UserTag(), s.State.ModelTag())
   241  	c.Assert(err, jc.ErrorIsNil)
   242  	c.Assert(uam.Access, gc.Equals, permission.AdminAccess)
   243  
   244  	uac, err := s.State.UserAccess(user.UserTag(), s.State.ControllerTag())
   245  	c.Assert(err, jc.ErrorIsNil)
   246  	c.Assert(uac.Access, gc.Equals, permission.SuperuserAccess)
   247  
   248  	// Look for the user.
   249  	u, err := s.State.User(user.UserTag())
   250  	c.Check(err, jc.ErrorIsNil)
   251  	c.Assert(u, jc.DeepEquals, user)
   252  
   253  	// Remove the user.
   254  	err = s.State.RemoveUser(user.UserTag())
   255  	c.Check(err, jc.ErrorIsNil)
   256  
   257  	uam, err = s.State.UserAccess(user.UserTag(), s.State.ModelTag())
   258  	c.Assert(err, gc.ErrorMatches, fmt.Sprintf("%q user not found", user.UserTag().Name()))
   259  
   260  	uac, err = s.State.UserAccess(user.UserTag(), s.State.ControllerTag())
   261  	c.Assert(err, gc.ErrorMatches, fmt.Sprintf("%q user not found", user.UserTag().Name()))
   262  }
   263  
   264  func (s *UserSuite) TestDisable(c *gc.C) {
   265  	user := s.Factory.MakeUser(c, &factory.UserParams{Password: "a-password"})
   266  	c.Assert(user.IsDisabled(), jc.IsFalse)
   267  	c.Assert(s.activeUsers(c), jc.DeepEquals, []string{"test-admin", user.Name()})
   268  
   269  	err := user.Disable()
   270  	c.Assert(err, jc.ErrorIsNil)
   271  	c.Assert(user.IsDisabled(), jc.IsTrue)
   272  	c.Assert(user.PasswordValid("a-password"), jc.IsFalse)
   273  	c.Assert(s.activeUsers(c), jc.DeepEquals, []string{"test-admin"})
   274  
   275  	err = user.Enable()
   276  	c.Assert(err, jc.ErrorIsNil)
   277  	c.Assert(user.IsDisabled(), jc.IsFalse)
   278  	c.Assert(user.PasswordValid("a-password"), jc.IsTrue)
   279  	c.Assert(s.activeUsers(c), jc.DeepEquals, []string{"test-admin", user.Name()})
   280  }
   281  
   282  func (s *UserSuite) activeUsers(c *gc.C) []string {
   283  	users, err := s.State.AllUsers(false)
   284  	c.Assert(err, jc.ErrorIsNil)
   285  	names := make([]string, len(users))
   286  	for i, u := range users {
   287  		names[i] = u.Name()
   288  	}
   289  	return names
   290  }
   291  
   292  func (s *UserSuite) TestSetPasswordHash(c *gc.C) {
   293  	user := s.Factory.MakeUser(c, nil)
   294  
   295  	salt, err := utils.RandomSalt()
   296  	c.Assert(err, jc.ErrorIsNil)
   297  	err = user.SetPasswordHash(utils.UserPasswordHash("foo", salt), salt)
   298  	c.Assert(err, jc.ErrorIsNil)
   299  
   300  	c.Assert(user.PasswordValid("foo"), jc.IsTrue)
   301  	c.Assert(user.PasswordValid("bar"), jc.IsFalse)
   302  
   303  	// User passwords should *not* use the fast PasswordHash function
   304  	hash := utils.AgentPasswordHash("foo-12345678901234567890")
   305  	c.Assert(err, jc.ErrorIsNil)
   306  	err = user.SetPasswordHash(hash, "")
   307  	c.Assert(err, jc.ErrorIsNil)
   308  
   309  	c.Assert(user.PasswordValid("foo-12345678901234567890"), jc.IsFalse)
   310  }
   311  
   312  func (s *UserSuite) TestSetPasswordHashWithSalt(c *gc.C) {
   313  	user := s.Factory.MakeUser(c, nil)
   314  
   315  	err := user.SetPasswordHash(utils.UserPasswordHash("foo", "salted"), "salted")
   316  	c.Assert(err, jc.ErrorIsNil)
   317  
   318  	c.Assert(user.PasswordValid("foo"), jc.IsTrue)
   319  	salt, _ := state.GetUserPasswordSaltAndHash(user)
   320  	c.Assert(salt, gc.Equals, "salted")
   321  }
   322  
   323  func (s *UserSuite) TestCantDisableAdmin(c *gc.C) {
   324  	user, err := s.State.User(s.Owner)
   325  	c.Assert(err, jc.ErrorIsNil)
   326  	err = user.Disable()
   327  	c.Assert(err, gc.ErrorMatches, "cannot disable controller model owner")
   328  }
   329  
   330  func (s *UserSuite) TestCaseSensitiveUsersErrors(c *gc.C) {
   331  	s.Factory.MakeUser(c, &factory.UserParams{Name: "Bob"})
   332  
   333  	_, err := s.State.AddUser(
   334  		"boB", "ignored", "ignored", "ignored")
   335  	c.Assert(errors.IsAlreadyExists(err), jc.IsTrue)
   336  	c.Assert(err, gc.ErrorMatches, "user already exists")
   337  }
   338  
   339  func (s *UserSuite) TestCaseInsensitiveLookup(c *gc.C) {
   340  	expectedUser := s.Factory.MakeUser(c, &factory.UserParams{Name: "Bob"})
   341  
   342  	assertCaseInsensitiveLookup := func(name string) {
   343  		userTag := names.NewUserTag(name)
   344  		obtainedUser, err := s.State.User(userTag)
   345  		c.Assert(err, jc.ErrorIsNil)
   346  		c.Assert(obtainedUser, gc.DeepEquals, expectedUser)
   347  	}
   348  
   349  	assertCaseInsensitiveLookup("bob")
   350  	assertCaseInsensitiveLookup("bOb")
   351  	assertCaseInsensitiveLookup("boB")
   352  	assertCaseInsensitiveLookup("BOB")
   353  }
   354  
   355  func (s *UserSuite) TestAllUsers(c *gc.C) {
   356  	// Create in non-alphabetical order.
   357  	s.Factory.MakeUser(c, &factory.UserParams{Name: "conrad"})
   358  	s.Factory.MakeUser(c, &factory.UserParams{Name: "adam"})
   359  	s.Factory.MakeUser(c, &factory.UserParams{Name: "debbie", Disabled: true})
   360  	s.Factory.MakeUser(c, &factory.UserParams{Name: "barbara"})
   361  	s.Factory.MakeUser(c, &factory.UserParams{Name: "fred", Disabled: true})
   362  	s.Factory.MakeUser(c, &factory.UserParams{Name: "erica"})
   363  	// There is the existing controller owner called "test-admin"
   364  
   365  	includeDeactivated := false
   366  	users, err := s.State.AllUsers(includeDeactivated)
   367  	c.Assert(err, jc.ErrorIsNil)
   368  	c.Assert(users, gc.HasLen, 5)
   369  	c.Check(users[0].Name(), gc.Equals, "adam")
   370  	c.Check(users[1].Name(), gc.Equals, "barbara")
   371  	c.Check(users[2].Name(), gc.Equals, "conrad")
   372  	c.Check(users[3].Name(), gc.Equals, "erica")
   373  	c.Check(users[4].Name(), gc.Equals, "test-admin")
   374  
   375  	includeDeactivated = true
   376  	users, err = s.State.AllUsers(includeDeactivated)
   377  	c.Assert(err, jc.ErrorIsNil)
   378  	c.Assert(users, gc.HasLen, 7)
   379  	c.Check(users[0].Name(), gc.Equals, "adam")
   380  	c.Check(users[1].Name(), gc.Equals, "barbara")
   381  	c.Check(users[2].Name(), gc.Equals, "conrad")
   382  	c.Check(users[3].Name(), gc.Equals, "debbie")
   383  	c.Check(users[4].Name(), gc.Equals, "erica")
   384  	c.Check(users[5].Name(), gc.Equals, "fred")
   385  	c.Check(users[6].Name(), gc.Equals, "test-admin")
   386  }
   387  
   388  func (s *UserSuite) TestAddUserNoSecretKey(c *gc.C) {
   389  	u, err := s.State.AddUser("bob", "display", "pass", "admin")
   390  	c.Assert(err, jc.ErrorIsNil)
   391  	c.Assert(u.SecretKey(), gc.IsNil)
   392  }
   393  
   394  func (s *UserSuite) TestAddUserSecretKey(c *gc.C) {
   395  	u, err := s.State.AddUserWithSecretKey("bob", "display", "admin")
   396  	c.Assert(err, jc.ErrorIsNil)
   397  	c.Assert(u.SecretKey(), gc.HasLen, 32)
   398  	c.Assert(u.PasswordValid(""), jc.IsFalse)
   399  }
   400  
   401  func (s *UserSuite) TestSetPasswordClearsSecretKey(c *gc.C) {
   402  	u, err := s.State.AddUserWithSecretKey("bob", "display", "admin")
   403  	c.Assert(err, jc.ErrorIsNil)
   404  	c.Assert(u.SecretKey(), gc.HasLen, 32)
   405  	err = u.SetPassword("anything")
   406  	c.Assert(err, jc.ErrorIsNil)
   407  	c.Assert(u.SecretKey(), gc.IsNil)
   408  	err = u.Refresh()
   409  	c.Assert(err, jc.ErrorIsNil)
   410  	c.Assert(u.SecretKey(), gc.IsNil)
   411  }