github.com/cloud-green/juju@v0.0.0-20151002100041-a00291338d3d/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  	"regexp"
     8  	"time"
     9  
    10  	"github.com/juju/errors"
    11  	"github.com/juju/names"
    12  	jc "github.com/juju/testing/checkers"
    13  	"github.com/juju/utils"
    14  	gc "gopkg.in/check.v1"
    15  
    16  	"github.com/juju/juju/state"
    17  	"github.com/juju/juju/testing/factory"
    18  )
    19  
    20  type UserSuite struct {
    21  	ConnSuite
    22  }
    23  
    24  var _ = gc.Suite(&UserSuite{})
    25  
    26  func (s *UserSuite) TestAddInvalidNames(c *gc.C) {
    27  	for _, name := range []string{
    28  		"",
    29  		"a",
    30  		"b^b",
    31  		"a.",
    32  		"a-",
    33  		"user@local",
    34  		"@ubuntuone",
    35  	} {
    36  		c.Logf("check invalid name %q", name)
    37  		user, err := s.State.AddUser(name, "ignored", "ignored", "ignored")
    38  		c.Check(err, gc.ErrorMatches, `invalid user name "`+regexp.QuoteMeta(name)+`"`)
    39  		c.Check(user, gc.IsNil)
    40  	}
    41  }
    42  
    43  func (s *UserSuite) TestAddUser(c *gc.C) {
    44  	name := "f00-Bar.ram77"
    45  	displayName := "Display"
    46  	password := "password"
    47  	creator := "admin"
    48  
    49  	now := time.Now().Round(time.Second).UTC()
    50  
    51  	user, err := s.State.AddUser(name, displayName, password, creator)
    52  	c.Assert(err, jc.ErrorIsNil)
    53  	c.Assert(user, gc.NotNil)
    54  	c.Assert(user.Name(), gc.Equals, name)
    55  	c.Assert(user.DisplayName(), gc.Equals, displayName)
    56  	c.Assert(user.PasswordValid(password), jc.IsTrue)
    57  	c.Assert(user.CreatedBy(), gc.Equals, creator)
    58  	c.Assert(user.DateCreated().After(now) ||
    59  		user.DateCreated().Equal(now), jc.IsTrue)
    60  	lastLogin, err := user.LastLogin()
    61  	c.Assert(err, jc.Satisfies, state.IsNeverLoggedInError)
    62  	c.Assert(lastLogin, gc.DeepEquals, time.Time{})
    63  
    64  	user, err = s.State.User(user.UserTag())
    65  	c.Assert(err, jc.ErrorIsNil)
    66  	c.Assert(user, gc.NotNil)
    67  	c.Assert(user.Name(), gc.Equals, name)
    68  	c.Assert(user.DisplayName(), gc.Equals, displayName)
    69  	c.Assert(user.PasswordValid(password), jc.IsTrue)
    70  	c.Assert(user.CreatedBy(), gc.Equals, creator)
    71  	c.Assert(user.DateCreated().After(now) ||
    72  		user.DateCreated().Equal(now), jc.IsTrue)
    73  	lastLogin, err = user.LastLogin()
    74  	c.Assert(err, jc.Satisfies, state.IsNeverLoggedInError)
    75  	c.Assert(lastLogin, gc.DeepEquals, time.Time{})
    76  }
    77  
    78  func (s *UserSuite) TestCheckUserExists(c *gc.C) {
    79  	user := s.Factory.MakeUser(c, nil)
    80  	exists, err := state.CheckUserExists(s.State, user.Name())
    81  	c.Assert(err, jc.ErrorIsNil)
    82  	c.Assert(exists, jc.IsTrue)
    83  	exists, err = state.CheckUserExists(s.State, "notAUser")
    84  	c.Assert(err, jc.ErrorIsNil)
    85  	c.Assert(exists, jc.IsFalse)
    86  }
    87  
    88  func (s *UserSuite) TestString(c *gc.C) {
    89  	user := s.Factory.MakeUser(c, &factory.UserParams{Name: "foo"})
    90  	c.Assert(user.String(), gc.Equals, "foo@local")
    91  }
    92  
    93  func (s *UserSuite) TestUpdateLastLogin(c *gc.C) {
    94  	now := time.Now().Round(time.Second).UTC()
    95  	user := s.Factory.MakeUser(c, nil)
    96  	err := user.UpdateLastLogin()
    97  	c.Assert(err, jc.ErrorIsNil)
    98  	lastLogin, err := user.LastLogin()
    99  	c.Assert(err, jc.ErrorIsNil)
   100  	c.Assert(lastLogin.After(now) ||
   101  		lastLogin.Equal(now), jc.IsTrue)
   102  }
   103  
   104  func (s *UserSuite) TestSetPassword(c *gc.C) {
   105  	user := s.Factory.MakeUser(c, nil)
   106  	testSetPassword(c, func() (state.Authenticator, error) {
   107  		return s.State.User(user.UserTag())
   108  	})
   109  }
   110  
   111  func (s *UserSuite) TestAddUserSetsSalt(c *gc.C) {
   112  	user := s.Factory.MakeUser(c, &factory.UserParams{Password: "a-password"})
   113  	salt, hash := state.GetUserPasswordSaltAndHash(user)
   114  	c.Assert(hash, gc.Not(gc.Equals), "")
   115  	c.Assert(salt, gc.Not(gc.Equals), "")
   116  	c.Assert(utils.UserPasswordHash("a-password", salt), gc.Equals, hash)
   117  	c.Assert(user.PasswordValid("a-password"), jc.IsTrue)
   118  }
   119  
   120  func (s *UserSuite) TestSetPasswordChangesSalt(c *gc.C) {
   121  	user := s.Factory.MakeUser(c, nil)
   122  	origSalt, origHash := state.GetUserPasswordSaltAndHash(user)
   123  	c.Assert(origSalt, gc.Not(gc.Equals), "")
   124  	user.SetPassword("a-password")
   125  	newSalt, newHash := state.GetUserPasswordSaltAndHash(user)
   126  	c.Assert(newSalt, gc.Not(gc.Equals), "")
   127  	c.Assert(newSalt, gc.Not(gc.Equals), origSalt)
   128  	c.Assert(newHash, gc.Not(gc.Equals), origHash)
   129  	c.Assert(user.PasswordValid("a-password"), jc.IsTrue)
   130  }
   131  
   132  func (s *UserSuite) TestDisable(c *gc.C) {
   133  	user := s.Factory.MakeUser(c, &factory.UserParams{Password: "a-password"})
   134  	c.Assert(user.IsDisabled(), jc.IsFalse)
   135  
   136  	err := user.Disable()
   137  	c.Assert(err, jc.ErrorIsNil)
   138  	c.Assert(user.IsDisabled(), jc.IsTrue)
   139  	c.Assert(user.PasswordValid("a-password"), jc.IsFalse)
   140  
   141  	err = user.Enable()
   142  	c.Assert(err, jc.ErrorIsNil)
   143  	c.Assert(user.IsDisabled(), jc.IsFalse)
   144  	c.Assert(user.PasswordValid("a-password"), jc.IsTrue)
   145  }
   146  
   147  func (s *UserSuite) TestSetPasswordHash(c *gc.C) {
   148  	user := s.Factory.MakeUser(c, nil)
   149  
   150  	err := user.SetPasswordHash(utils.UserPasswordHash("foo", utils.CompatSalt), utils.CompatSalt)
   151  	c.Assert(err, jc.ErrorIsNil)
   152  
   153  	c.Assert(user.PasswordValid("foo"), jc.IsTrue)
   154  	c.Assert(user.PasswordValid("bar"), jc.IsFalse)
   155  
   156  	// User passwords should *not* use the fast PasswordHash function
   157  	hash := utils.AgentPasswordHash("foo-12345678901234567890")
   158  	c.Assert(err, jc.ErrorIsNil)
   159  	err = user.SetPasswordHash(hash, "")
   160  	c.Assert(err, jc.ErrorIsNil)
   161  
   162  	c.Assert(user.PasswordValid("foo-12345678901234567890"), jc.IsFalse)
   163  }
   164  
   165  func (s *UserSuite) TestSetPasswordHashWithSalt(c *gc.C) {
   166  	user := s.Factory.MakeUser(c, nil)
   167  
   168  	err := user.SetPasswordHash(utils.UserPasswordHash("foo", "salted"), "salted")
   169  	c.Assert(err, jc.ErrorIsNil)
   170  
   171  	c.Assert(user.PasswordValid("foo"), jc.IsTrue)
   172  	salt, hash := state.GetUserPasswordSaltAndHash(user)
   173  	c.Assert(salt, gc.Equals, "salted")
   174  	c.Assert(hash, gc.Not(gc.Equals), utils.UserPasswordHash("foo", utils.CompatSalt))
   175  }
   176  
   177  func (s *UserSuite) TestPasswordValidUpdatesSalt(c *gc.C) {
   178  	user := s.Factory.MakeUser(c, nil)
   179  
   180  	compatHash := utils.UserPasswordHash("foo", utils.CompatSalt)
   181  	err := user.SetPasswordHash(compatHash, "")
   182  	c.Assert(err, jc.ErrorIsNil)
   183  	beforeSalt, beforeHash := state.GetUserPasswordSaltAndHash(user)
   184  	c.Assert(beforeSalt, gc.Equals, "")
   185  	c.Assert(beforeHash, gc.Equals, compatHash)
   186  	c.Assert(user.PasswordValid("bar"), jc.IsFalse)
   187  	// A bad password doesn't trigger a rewrite
   188  	afterBadSalt, afterBadHash := state.GetUserPasswordSaltAndHash(user)
   189  	c.Assert(afterBadSalt, gc.Equals, "")
   190  	c.Assert(afterBadHash, gc.Equals, compatHash)
   191  	// When we get a valid check, we then add a salt and rewrite the hash
   192  	c.Assert(user.PasswordValid("foo"), jc.IsTrue)
   193  	afterSalt, afterHash := state.GetUserPasswordSaltAndHash(user)
   194  	c.Assert(afterSalt, gc.Not(gc.Equals), "")
   195  	c.Assert(afterHash, gc.Not(gc.Equals), compatHash)
   196  	c.Assert(afterHash, gc.Equals, utils.UserPasswordHash("foo", afterSalt))
   197  	// running PasswordValid again doesn't trigger another rewrite
   198  	c.Assert(user.PasswordValid("foo"), jc.IsTrue)
   199  	lastSalt, lastHash := state.GetUserPasswordSaltAndHash(user)
   200  	c.Assert(lastSalt, gc.Equals, afterSalt)
   201  	c.Assert(lastHash, gc.Equals, afterHash)
   202  }
   203  
   204  func (s *UserSuite) TestCantDisableAdmin(c *gc.C) {
   205  	user, err := s.State.User(s.Owner)
   206  	c.Assert(err, jc.ErrorIsNil)
   207  	err = user.Disable()
   208  	c.Assert(err, gc.ErrorMatches, "cannot disable state server environment owner")
   209  }
   210  
   211  func (s *UserSuite) TestCaseSensitiveUsersErrors(c *gc.C) {
   212  	s.Factory.MakeUser(c, &factory.UserParams{Name: "Bob"})
   213  
   214  	_, err := s.State.AddUser(
   215  		"boB", "ignored", "ignored", "ignored")
   216  	c.Assert(errors.IsAlreadyExists(err), jc.IsTrue)
   217  	c.Assert(err, gc.ErrorMatches, "user already exists")
   218  }
   219  
   220  func (s *UserSuite) TestCaseInsensitiveLookup(c *gc.C) {
   221  	expectedUser := s.Factory.MakeUser(c, &factory.UserParams{Name: "Bob"})
   222  
   223  	assertCaseInsensitiveLookup := func(name string) {
   224  		userTag := names.NewUserTag(name)
   225  		obtainedUser, err := s.State.User(userTag)
   226  		c.Assert(err, jc.ErrorIsNil)
   227  		c.Assert(obtainedUser, gc.DeepEquals, expectedUser)
   228  	}
   229  
   230  	assertCaseInsensitiveLookup("bob")
   231  	assertCaseInsensitiveLookup("bOb")
   232  	assertCaseInsensitiveLookup("boB")
   233  	assertCaseInsensitiveLookup("BOB")
   234  }
   235  
   236  func (s *UserSuite) TestAllUsers(c *gc.C) {
   237  	// Create in non-alphabetical order.
   238  	s.Factory.MakeUser(c, &factory.UserParams{Name: "conrad"})
   239  	s.Factory.MakeUser(c, &factory.UserParams{Name: "adam"})
   240  	s.Factory.MakeUser(c, &factory.UserParams{Name: "debbie", Disabled: true})
   241  	s.Factory.MakeUser(c, &factory.UserParams{Name: "barbara"})
   242  	s.Factory.MakeUser(c, &factory.UserParams{Name: "fred", Disabled: true})
   243  	s.Factory.MakeUser(c, &factory.UserParams{Name: "erica"})
   244  	// There is the existing state server owner called "test-admin"
   245  
   246  	includeDeactivated := false
   247  	users, err := s.State.AllUsers(includeDeactivated)
   248  	c.Assert(err, jc.ErrorIsNil)
   249  	c.Assert(users, gc.HasLen, 5)
   250  	c.Check(users[0].Name(), gc.Equals, "adam")
   251  	c.Check(users[1].Name(), gc.Equals, "barbara")
   252  	c.Check(users[2].Name(), gc.Equals, "conrad")
   253  	c.Check(users[3].Name(), gc.Equals, "erica")
   254  	c.Check(users[4].Name(), gc.Equals, "test-admin")
   255  
   256  	includeDeactivated = true
   257  	users, err = s.State.AllUsers(includeDeactivated)
   258  	c.Assert(err, jc.ErrorIsNil)
   259  	c.Assert(users, gc.HasLen, 7)
   260  	c.Check(users[0].Name(), gc.Equals, "adam")
   261  	c.Check(users[1].Name(), gc.Equals, "barbara")
   262  	c.Check(users[2].Name(), gc.Equals, "conrad")
   263  	c.Check(users[3].Name(), gc.Equals, "debbie")
   264  	c.Check(users[4].Name(), gc.Equals, "erica")
   265  	c.Check(users[5].Name(), gc.Equals, "fred")
   266  	c.Check(users[6].Name(), gc.Equals, "test-admin")
   267  }