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