auth

Paddy 2014-10-26 Parent:73a9f7a6af54 Child:42bc3e44f4fe

57:e45bfa2abc00 Go to Latest

auth/profile.go

The great documentation and exported interface cleanup. Modify all our *Store interfaces to be unexported, as there's no real good reason they need to be exported, especially as they can be implemented without being exported. The interfaces shouldn't matter to 99% of users of the package, so let's not pollute our package API. Further, all methods of the interfaces are now unexported, for pretty much the same reasoning. Add a doc.go file with documentation explaining the choices the package is making and what it provides. Implement documentation on all our exported types and methods and functions, which makes golint happy. The only remaining golint warning is about NewMemstore, which will stay the way it is. The memstore type is useful outside tests for things like standing up a server quickly when we don't care about the storage, and because the type is unexported, we _need_ a New function to create an instance that can be passed to the Context.

History
     1.1 --- a/profile.go	Wed Oct 22 00:30:28 2014 -0400
     1.2 +++ b/profile.go	Sun Oct 26 00:53:36 2014 -0400
     1.3 @@ -8,24 +8,46 @@
     1.4  )
     1.5  
     1.6  const (
     1.7 +	// MinPassphraseLength is the minimum length, in bytes, of a passphrase, exclusive.
     1.8  	MinPassphraseLength = 6
     1.9 +	// MaxPassphraseLength is the maximum length, in bytes, of a passphrase, exclusive.
    1.10  	MaxPassphraseLength = 64
    1.11  )
    1.12  
    1.13  var (
    1.14 -	ErrNoProfileStore       = errors.New("no ProfileStore was specified for the Context")
    1.15 -	ErrProfileAlreadyExists = errors.New("profile already exists in ProfileStore")
    1.16 -	ErrProfileNotFound      = errors.New("profile not found in ProfileStore")
    1.17 -	ErrLoginAlreadyExists   = errors.New("login already exists in ProfileStore")
    1.18 -	ErrLoginNotFound        = errors.New("login not found in ProfileStore")
    1.19 +	// ErrNoProfileStore is returned when a Context tries to act on a profileStore without setting one first.
    1.20 +	ErrNoProfileStore = errors.New("no profileStore was specified for the Context")
    1.21 +	// ErrProfileAlreadyExists is returned when a Profile is added to a profileStore, but another Profile with
    1.22 +	// the same ID already exists in the profileStore.
    1.23 +	ErrProfileAlreadyExists = errors.New("profile already exists in profileStore")
    1.24 +	// ErrProfileNotFound is returned when a Profile is requested but not found in the profileStore.
    1.25 +	ErrProfileNotFound = errors.New("profile not found in profileStore")
    1.26 +	// ErrLoginAlreadyExists is returned when a Login is added to a profileStore, but another Login with the same
    1.27 +	// Type and Value already exists in the profileStore.
    1.28 +	ErrLoginAlreadyExists = errors.New("login already exists in profileStore")
    1.29 +	// ErrLoginNotFound is returned when a Login is requested but not found in the profileStore.
    1.30 +	ErrLoginNotFound = errors.New("login not found in profileStore")
    1.31  
    1.32 -	ErrMissingPassphrase             = errors.New("missing passphrase")
    1.33 -	ErrMissingPassphraseReset        = errors.New("missing passphrase reset")
    1.34 +	// ErrMissingPassphrase is returned when a ProfileChange is validated but does not contain a
    1.35 +	// Passphrase, and requires one.
    1.36 +	ErrMissingPassphrase = errors.New("missing passphrase")
    1.37 +	// ErrMissingPassphraseReset is returned when a ProfileChange is validated but does not contain
    1.38 +	// a PassphraseReset, and requires one.
    1.39 +	ErrMissingPassphraseReset = errors.New("missing passphrase reset")
    1.40 +	// ErrMissingPassphraseResetCreated is returned when a ProfileChange is validated but does not
    1.41 +	// contain a PassphraseResetCreated, and requires one.
    1.42  	ErrMissingPassphraseResetCreated = errors.New("missing passphrase reset created timestamp")
    1.43 -	ErrPassphraseTooShort            = errors.New("passphrase too short")
    1.44 -	ErrPassphraseTooLong             = errors.New("passphrase too long")
    1.45 +	// ErrPassphraseTooShort is returned when a ProfileChange is validated and contains a Passphrase,
    1.46 +	// but the Passphrase is shorter than MinPassphraseLength.
    1.47 +	ErrPassphraseTooShort = errors.New("passphrase too short")
    1.48 +	// ErrPassphraseTooLong is returned when a ProfileChange is validated and contains a Passphrase,
    1.49 +	// but the Passphrase is longer than MaxPassphraseLength.
    1.50 +	ErrPassphraseTooLong = errors.New("passphrase too long")
    1.51  )
    1.52  
    1.53 +// Profile represents a single user of the service,
    1.54 +// including their authentication information, but not
    1.55 +// including their username or email.
    1.56  type Profile struct {
    1.57  	ID                     uuid.ID
    1.58  	Name                   string
    1.59 @@ -41,6 +63,8 @@
    1.60  	LastSeen               time.Time
    1.61  }
    1.62  
    1.63 +// ApplyChange applies the properties of the passed ProfileChange
    1.64 +// to the Profile it is called on.
    1.65  func (p *Profile) ApplyChange(change ProfileChange) {
    1.66  	if change.Name != nil {
    1.67  		p.Name = *change.Name
    1.68 @@ -74,12 +98,15 @@
    1.69  	}
    1.70  }
    1.71  
    1.72 +// ApplyBulkChange applies the properties of the passed BulkProfileChange
    1.73 +// to the Profile it is called on.
    1.74  func (p *Profile) ApplyBulkChange(change BulkProfileChange) {
    1.75  	if change.Compromised != nil {
    1.76  		p.Compromised = *change.Compromised
    1.77  	}
    1.78  }
    1.79  
    1.80 +// ProfileChange represents a single atomic change to a Profile's mutable data.
    1.81  type ProfileChange struct {
    1.82  	Name                   *string
    1.83  	Passphrase             *string
    1.84 @@ -93,6 +120,10 @@
    1.85  	LastSeen               *time.Time
    1.86  }
    1.87  
    1.88 +// Validate checks the ProfileChange it is called on
    1.89 +// and asserts its internal validity, or lack thereof.
    1.90 +// A descriptive error will be returned in the case of
    1.91 +// an invalid change.
    1.92  func (c ProfileChange) Validate() error {
    1.93  	if c.Name == nil && c.Passphrase == nil && c.Iterations == nil && c.Salt == nil && c.PassphraseScheme == nil && c.Compromised == nil && c.LockedUntil == nil && c.PassphraseReset == nil && c.PassphraseResetCreated == nil && c.LastSeen == nil {
    1.94  		return ErrEmptyChange
    1.95 @@ -121,10 +152,17 @@
    1.96  	return nil
    1.97  }
    1.98  
    1.99 +// BulkProfileChange represents a single atomic change to many Profiles' mutable data.
   1.100 +// It is a subset of a ProfileChange, as it doesn't make sense to mutate some of the
   1.101 +// ProfileChange values across many Profiles all at once.
   1.102  type BulkProfileChange struct {
   1.103  	Compromised *bool
   1.104  }
   1.105  
   1.106 +// Validate checks the BulkProfileChange it is called on
   1.107 +// and asserts its internal validity, or lack thereof.
   1.108 +// A descriptive error will be returned in the case of an
   1.109 +// invalid change.
   1.110  func (b BulkProfileChange) Validate() error {
   1.111  	if b.Compromised == nil {
   1.112  		return ErrEmptyChange
   1.113 @@ -132,6 +170,9 @@
   1.114  	return nil
   1.115  }
   1.116  
   1.117 +// Login represents a single human-friendly identifier for
   1.118 +// a given Profile that can be used to log into that Profile.
   1.119 +// Each Profile may only have one Login for each Type.
   1.120  type Login struct {
   1.121  	Type      string
   1.122  	Value     string
   1.123 @@ -140,21 +181,21 @@
   1.124  	LastUsed  time.Time
   1.125  }
   1.126  
   1.127 -type ProfileStore interface {
   1.128 -	GetProfileByID(id uuid.ID) (Profile, error)
   1.129 -	GetProfileByLogin(loginType, value string) (Profile, error)
   1.130 -	SaveProfile(profile Profile) error
   1.131 -	UpdateProfile(id uuid.ID, change ProfileChange) error
   1.132 -	UpdateProfiles(ids []uuid.ID, change BulkProfileChange) error
   1.133 -	DeleteProfile(id uuid.ID) error
   1.134 +type profileStore interface {
   1.135 +	getProfileByID(id uuid.ID) (Profile, error)
   1.136 +	getProfileByLogin(loginType, value string) (Profile, error)
   1.137 +	saveProfile(profile Profile) error
   1.138 +	updateProfile(id uuid.ID, change ProfileChange) error
   1.139 +	updateProfiles(ids []uuid.ID, change BulkProfileChange) error
   1.140 +	deleteProfile(id uuid.ID) error
   1.141  
   1.142 -	AddLogin(login Login) error
   1.143 -	RemoveLogin(loginType, value string, profile uuid.ID) error
   1.144 -	RecordLoginUse(loginType, value string, when time.Time) error
   1.145 -	ListLogins(profile uuid.ID, num, offset int) ([]Login, error)
   1.146 +	addLogin(login Login) error
   1.147 +	removeLogin(loginType, value string, profile uuid.ID) error
   1.148 +	recordLoginUse(loginType, value string, when time.Time) error
   1.149 +	listLogins(profile uuid.ID, num, offset int) ([]Login, error)
   1.150  }
   1.151  
   1.152 -func (m *Memstore) GetProfileByID(id uuid.ID) (Profile, error) {
   1.153 +func (m *memstore) getProfileByID(id uuid.ID) (Profile, error) {
   1.154  	m.profileLock.RLock()
   1.155  	defer m.profileLock.RUnlock()
   1.156  	p, ok := m.profiles[id.String()]
   1.157 @@ -164,7 +205,7 @@
   1.158  	return p, nil
   1.159  }
   1.160  
   1.161 -func (m *Memstore) GetProfileByLogin(loginType, value string) (Profile, error) {
   1.162 +func (m *memstore) getProfileByLogin(loginType, value string) (Profile, error) {
   1.163  	m.loginLock.RLock()
   1.164  	defer m.loginLock.RUnlock()
   1.165  	login, ok := m.logins[loginType+":"+value]
   1.166 @@ -180,7 +221,7 @@
   1.167  	return profile, nil
   1.168  }
   1.169  
   1.170 -func (m *Memstore) SaveProfile(profile Profile) error {
   1.171 +func (m *memstore) saveProfile(profile Profile) error {
   1.172  	m.profileLock.Lock()
   1.173  	defer m.profileLock.Unlock()
   1.174  	_, ok := m.profiles[profile.ID.String()]
   1.175 @@ -191,7 +232,7 @@
   1.176  	return nil
   1.177  }
   1.178  
   1.179 -func (m *Memstore) UpdateProfile(id uuid.ID, change ProfileChange) error {
   1.180 +func (m *memstore) updateProfile(id uuid.ID, change ProfileChange) error {
   1.181  	m.profileLock.Lock()
   1.182  	defer m.profileLock.Unlock()
   1.183  	p, ok := m.profiles[id.String()]
   1.184 @@ -203,7 +244,7 @@
   1.185  	return nil
   1.186  }
   1.187  
   1.188 -func (m *Memstore) UpdateProfiles(ids []uuid.ID, change BulkProfileChange) error {
   1.189 +func (m *memstore) updateProfiles(ids []uuid.ID, change BulkProfileChange) error {
   1.190  	m.profileLock.Lock()
   1.191  	defer m.profileLock.Unlock()
   1.192  	for id, profile := range m.profiles {
   1.193 @@ -218,7 +259,7 @@
   1.194  	return nil
   1.195  }
   1.196  
   1.197 -func (m *Memstore) DeleteProfile(id uuid.ID) error {
   1.198 +func (m *memstore) deleteProfile(id uuid.ID) error {
   1.199  	m.profileLock.Lock()
   1.200  	defer m.profileLock.Unlock()
   1.201  	_, ok := m.profiles[id.String()]
   1.202 @@ -229,7 +270,7 @@
   1.203  	return nil
   1.204  }
   1.205  
   1.206 -func (m *Memstore) AddLogin(login Login) error {
   1.207 +func (m *memstore) addLogin(login Login) error {
   1.208  	m.loginLock.Lock()
   1.209  	defer m.loginLock.Unlock()
   1.210  	_, ok := m.logins[login.Type+":"+login.Value]
   1.211 @@ -241,7 +282,7 @@
   1.212  	return nil
   1.213  }
   1.214  
   1.215 -func (m *Memstore) RemoveLogin(loginType, value string, profile uuid.ID) error {
   1.216 +func (m *memstore) removeLogin(loginType, value string, profile uuid.ID) error {
   1.217  	m.loginLock.Lock()
   1.218  	defer m.loginLock.Unlock()
   1.219  	l, ok := m.logins[loginType+":"+value]
   1.220 @@ -265,7 +306,7 @@
   1.221  	return nil
   1.222  }
   1.223  
   1.224 -func (m *Memstore) RecordLoginUse(loginType, value string, when time.Time) error {
   1.225 +func (m *memstore) recordLoginUse(loginType, value string, when time.Time) error {
   1.226  	m.loginLock.Lock()
   1.227  	defer m.loginLock.Unlock()
   1.228  	l, ok := m.logins[loginType+":"+value]
   1.229 @@ -277,7 +318,7 @@
   1.230  	return nil
   1.231  }
   1.232  
   1.233 -func (m *Memstore) ListLogins(profile uuid.ID, num, offset int) ([]Login, error) {
   1.234 +func (m *memstore) listLogins(profile uuid.ID, num, offset int) ([]Login, error) {
   1.235  	m.loginLock.RLock()
   1.236  	defer m.loginLock.RUnlock()
   1.237  	ids, ok := m.profileLoginLookup[profile.String()]