auth

Paddy 2014-09-18 Parent:0b86c2d3ec75 Child:fb827644bfd8

41:113ccb15b919 Go to Latest

auth/profile.go

Added validation for clients, split endpoints out. Split endpoints out into their own type and added associated methods to the ClientStores, so now each client can have more than one redirect endpoint. Added unit testing for endpoint methods. Added validation code to validate client changes.

History
paddy@27 1 package auth
paddy@27 2
paddy@27 3 import (
paddy@38 4 "errors"
paddy@27 5 "time"
paddy@27 6
paddy@27 7 "secondbit.org/uuid"
paddy@27 8 )
paddy@27 9
paddy@38 10 var (
paddy@38 11 ErrProfileAlreadyExists = errors.New("profile already exists in ProfileStore")
paddy@38 12 ErrProfileNotFound = errors.New("profile not found in ProfileStore")
paddy@38 13 )
paddy@38 14
paddy@27 15 type Profile struct {
paddy@38 16 ID uuid.ID
paddy@38 17 Name string
paddy@38 18 Passphrase string
paddy@38 19 Iterations int64
paddy@38 20 Salt string
paddy@38 21 PassphraseScheme int
paddy@38 22 Compromised bool
paddy@38 23 LockedUntil time.Time
paddy@38 24 PassphraseReset string
paddy@38 25 PassphraseResetCreated time.Time
paddy@38 26 Created time.Time
paddy@38 27 LastSeen time.Time
paddy@38 28 }
paddy@38 29
paddy@38 30 func (p *Profile) ApplyChange(change ProfileChange) {
paddy@38 31 if change.Name != nil {
paddy@38 32 p.Name = *change.Name
paddy@38 33 }
paddy@38 34 if change.Passphrase != nil {
paddy@38 35 p.Passphrase = *change.Passphrase
paddy@38 36 }
paddy@38 37 if change.Iterations != nil {
paddy@38 38 p.Iterations = *change.Iterations
paddy@38 39 }
paddy@38 40 if change.Salt != nil {
paddy@38 41 p.Salt = *change.Salt
paddy@38 42 }
paddy@38 43 if change.PassphraseScheme != nil {
paddy@38 44 p.PassphraseScheme = *change.PassphraseScheme
paddy@38 45 }
paddy@38 46 if change.Compromised != nil {
paddy@38 47 p.Compromised = *change.Compromised
paddy@38 48 }
paddy@38 49 if change.LockedUntil != nil {
paddy@38 50 p.LockedUntil = *change.LockedUntil
paddy@38 51 }
paddy@38 52 if change.PassphraseReset != nil {
paddy@38 53 p.PassphraseReset = *change.PassphraseReset
paddy@38 54 }
paddy@38 55 if change.PassphraseResetCreated != nil {
paddy@38 56 p.PassphraseResetCreated = *change.PassphraseResetCreated
paddy@38 57 }
paddy@38 58 if change.LastSeen != nil {
paddy@38 59 p.LastSeen = *change.LastSeen
paddy@38 60 }
paddy@38 61 }
paddy@38 62
paddy@38 63 type ProfileChange struct {
paddy@38 64 Name *string
paddy@38 65 Passphrase *string
paddy@38 66 Iterations *int64
paddy@38 67 Salt *string
paddy@38 68 PassphraseScheme *int
paddy@38 69 Compromised *bool
paddy@38 70 LockedUntil *time.Time
paddy@38 71 PassphraseReset *string
paddy@38 72 PassphraseResetCreated *time.Time
paddy@38 73 LastSeen *time.Time
paddy@38 74 }
paddy@38 75
paddy@38 76 func (c ProfileChange) Validate() error {
paddy@40 77 // TODO: validate profile changes
paddy@38 78 return nil
paddy@27 79 }
paddy@27 80
paddy@27 81 type Login struct {
paddy@27 82 Type string
paddy@27 83 Value string
paddy@27 84 ProfileID uuid.ID
paddy@27 85 Created time.Time
paddy@27 86 LastUsed time.Time
paddy@27 87 }
paddy@27 88
paddy@27 89 type ProfileStore interface {
paddy@27 90 GetProfileByID(id uuid.ID) (Profile, error)
paddy@38 91 GetProfileByLogin(login Login) (Profile, error)
paddy@38 92 SaveProfile(profile Profile) error
paddy@38 93 UpdateProfile(id uuid.ID, change ProfileChange) error
paddy@27 94 DeleteProfile(id uuid.ID) error
paddy@38 95 }
paddy@27 96
paddy@38 97 func (m *Memstore) GetProfileByID(id uuid.ID) (Profile, error) {
paddy@38 98 m.profileLock.RLock()
paddy@38 99 defer m.profileLock.RUnlock()
paddy@38 100 p, ok := m.profiles[id.String()]
paddy@38 101 if !ok {
paddy@38 102 return Profile{}, ErrProfileNotFound
paddy@38 103 }
paddy@38 104 return p, nil
paddy@27 105 }
paddy@38 106
paddy@38 107 func (m *Memstore) GetProfileByLogin(login Login) (Profile, error) {
paddy@40 108 // TODO: get profile by login
paddy@38 109 return Profile{}, nil
paddy@38 110 }
paddy@38 111
paddy@38 112 func (m *Memstore) SaveProfile(profile Profile) error {
paddy@38 113 m.profileLock.Lock()
paddy@38 114 defer m.profileLock.Unlock()
paddy@38 115 _, ok := m.profiles[profile.ID.String()]
paddy@38 116 if ok {
paddy@38 117 return ErrProfileAlreadyExists
paddy@38 118 }
paddy@38 119 m.profiles[profile.ID.String()] = profile
paddy@38 120 return nil
paddy@38 121 }
paddy@38 122
paddy@38 123 func (m *Memstore) UpdateProfile(id uuid.ID, change ProfileChange) error {
paddy@38 124 m.profileLock.Lock()
paddy@38 125 defer m.profileLock.Unlock()
paddy@38 126 p, ok := m.profiles[id.String()]
paddy@38 127 if !ok {
paddy@38 128 return ErrProfileNotFound
paddy@38 129 }
paddy@38 130 p.ApplyChange(change)
paddy@38 131 m.profiles[id.String()] = p
paddy@38 132 return nil
paddy@38 133 }
paddy@38 134
paddy@38 135 func (m *Memstore) DeleteProfile(id uuid.ID) error {
paddy@38 136 m.profileLock.Lock()
paddy@38 137 defer m.profileLock.Unlock()
paddy@38 138 _, ok := m.profiles[id.String()]
paddy@38 139 if !ok {
paddy@38 140 return ErrProfileNotFound
paddy@38 141 }
paddy@38 142 delete(m.profiles, id.String())
paddy@38 143 return nil
paddy@38 144 }
paddy@40 145
paddy@40 146 // TODO: login store
paddy@40 147 // TODO: login delete
paddy@40 148 // TODO: login update