@@ -26,6 +26,7 @@ func (d *Backend) User(ctx context.Context, username string) (proto.User, error)
2626 var m models.User
2727 var pks []ssh.PublicKey
2828 var hl models.Handle
29+ var ems []proto.UserEmail
2930 if err := d .db .TransactionContext (ctx , func (tx * db.Tx ) error {
3031 var err error
3132 m , err = d .store .FindUserByUsername (ctx , tx , username )
@@ -38,6 +39,15 @@ func (d *Backend) User(ctx context.Context, username string) (proto.User, error)
3839 return err
3940 }
4041
42+ emails , err := d .store .ListUserEmails (ctx , tx , m .ID )
43+ if err != nil {
44+ return err
45+ }
46+
47+ for _ , e := range emails {
48+ ems = append (ems , & userEmail {e })
49+ }
50+
4151 hl , err = d .store .GetHandleByUserID (ctx , tx , m .ID )
4252 return err
4353 }); err != nil {
@@ -53,6 +63,7 @@ func (d *Backend) User(ctx context.Context, username string) (proto.User, error)
5363 user : m ,
5464 publicKeys : pks ,
5565 handle : hl ,
66+ emails : ems ,
5667 }, nil
5768}
5869
@@ -61,6 +72,7 @@ func (d *Backend) UserByID(ctx context.Context, id int64) (proto.User, error) {
6172 var m models.User
6273 var pks []ssh.PublicKey
6374 var hl models.Handle
75+ var ems []proto.UserEmail
6476 if err := d .db .TransactionContext (ctx , func (tx * db.Tx ) error {
6577 var err error
6678 m , err = d .store .GetUserByID (ctx , tx , id )
@@ -73,6 +85,15 @@ func (d *Backend) UserByID(ctx context.Context, id int64) (proto.User, error) {
7385 return err
7486 }
7587
88+ emails , err := d .store .ListUserEmails (ctx , tx , m .ID )
89+ if err != nil {
90+ return err
91+ }
92+
93+ for _ , e := range emails {
94+ ems = append (ems , & userEmail {e })
95+ }
96+
7697 hl , err = d .store .GetHandleByUserID (ctx , tx , m .ID )
7798 return err
7899 }); err != nil {
@@ -88,6 +109,7 @@ func (d *Backend) UserByID(ctx context.Context, id int64) (proto.User, error) {
88109 user : m ,
89110 publicKeys : pks ,
90111 handle : hl ,
112+ emails : ems ,
91113 }, nil
92114}
93115
@@ -98,6 +120,7 @@ func (d *Backend) UserByPublicKey(ctx context.Context, pk ssh.PublicKey) (proto.
98120 var m models.User
99121 var pks []ssh.PublicKey
100122 var hl models.Handle
123+ var ems []proto.UserEmail
101124 if err := d .db .TransactionContext (ctx , func (tx * db.Tx ) error {
102125 var err error
103126 m , err = d .store .FindUserByPublicKey (ctx , tx , pk )
@@ -110,6 +133,15 @@ func (d *Backend) UserByPublicKey(ctx context.Context, pk ssh.PublicKey) (proto.
110133 return err
111134 }
112135
136+ emails , err := d .store .ListUserEmails (ctx , tx , m .ID )
137+ if err != nil {
138+ return err
139+ }
140+
141+ for _ , e := range emails {
142+ ems = append (ems , & userEmail {e })
143+ }
144+
113145 hl , err = d .store .GetHandleByUserID (ctx , tx , m .ID )
114146 return err
115147 }); err != nil {
@@ -125,6 +157,7 @@ func (d *Backend) UserByPublicKey(ctx context.Context, pk ssh.PublicKey) (proto.
125157 user : m ,
126158 publicKeys : pks ,
127159 handle : hl ,
160+ emails : ems ,
128161 }, nil
129162}
130163
@@ -134,6 +167,7 @@ func (d *Backend) UserByAccessToken(ctx context.Context, token string) (proto.Us
134167 var m models.User
135168 var pks []ssh.PublicKey
136169 var hl models.Handle
170+ var ems []proto.UserEmail
137171 token = HashToken (token )
138172
139173 if err := d .db .TransactionContext (ctx , func (tx * db.Tx ) error {
@@ -156,6 +190,15 @@ func (d *Backend) UserByAccessToken(ctx context.Context, token string) (proto.Us
156190 return err
157191 }
158192
193+ emails , err := d .store .ListUserEmails (ctx , tx , m .ID )
194+ if err != nil {
195+ return err
196+ }
197+
198+ for _ , e := range emails {
199+ ems = append (ems , & userEmail {e })
200+ }
201+
159202 hl , err = d .store .GetHandleByUserID (ctx , tx , m .ID )
160203 return err
161204 }); err != nil {
@@ -171,6 +214,7 @@ func (d *Backend) UserByAccessToken(ctx context.Context, token string) (proto.Us
171214 user : m ,
172215 publicKeys : pks ,
173216 handle : hl ,
217+ emails : ems ,
174218 }, nil
175219}
176220
@@ -228,7 +272,7 @@ func (d *Backend) AddPublicKey(ctx context.Context, username string, pk ssh.Publ
228272// It implements backend.Backend.
229273func (d * Backend ) CreateUser (ctx context.Context , username string , opts proto.UserOptions ) (proto.User , error ) {
230274 if err := d .db .TransactionContext (ctx , func (tx * db.Tx ) error {
231- return d .store .CreateUser (ctx , tx , username , opts .Admin , opts .PublicKeys )
275+ return d .store .CreateUser (ctx , tx , username , opts .Admin , opts .PublicKeys , opts . Emails )
232276 }); err != nil {
233277 return nil , db .WrapError (err )
234278 }
@@ -335,10 +379,60 @@ func (d *Backend) SetPassword(ctx context.Context, username string, rawPassword
335379 )
336380}
337381
382+ // AddUserEmail adds an email to a user.
383+ func (d * Backend ) AddUserEmail (ctx context.Context , user proto.User , email string ) error {
384+ return db .WrapError (
385+ d .db .TransactionContext (ctx , func (tx * db.Tx ) error {
386+ return d .store .AddUserEmail (ctx , tx , user .ID (), email , false )
387+ }),
388+ )
389+ }
390+
391+ // ListUserEmails lists the emails of a user.
392+ func (d * Backend ) ListUserEmails (ctx context.Context , user proto.User ) ([]proto.UserEmail , error ) {
393+ var ems []proto.UserEmail
394+ if err := d .db .TransactionContext (ctx , func (tx * db.Tx ) error {
395+ emails , err := d .store .ListUserEmails (ctx , tx , user .ID ())
396+ if err != nil {
397+ return err
398+ }
399+
400+ for _ , e := range emails {
401+ ems = append (ems , & userEmail {e })
402+ }
403+
404+ return nil
405+ }); err != nil {
406+ return nil , db .WrapError (err )
407+ }
408+
409+ return ems , nil
410+ }
411+
412+ // RemoveUserEmail deletes an email for a user.
413+ // The deleted email must not be the primary email.
414+ func (d * Backend ) RemoveUserEmail (ctx context.Context , user proto.User , email string ) error {
415+ return db .WrapError (
416+ d .db .TransactionContext (ctx , func (tx * db.Tx ) error {
417+ return d .store .RemoveUserEmail (ctx , tx , user .ID (), email )
418+ }),
419+ )
420+ }
421+
422+ // SetUserPrimaryEmail sets the primary email of a user.
423+ func (d * Backend ) SetUserPrimaryEmail (ctx context.Context , user proto.User , email string ) error {
424+ return db .WrapError (
425+ d .db .TransactionContext (ctx , func (tx * db.Tx ) error {
426+ return d .store .SetUserPrimaryEmail (ctx , tx , user .ID (), email )
427+ }),
428+ )
429+ }
430+
338431type user struct {
339432 user models.User
340433 publicKeys []ssh.PublicKey
341434 handle models.Handle
435+ emails []proto.UserEmail
342436}
343437
344438var _ proto.User = (* user )(nil )
@@ -371,3 +465,29 @@ func (u *user) Password() string {
371465
372466 return ""
373467}
468+
469+ // Emails implements proto.User.
470+ func (u * user ) Emails () []proto.UserEmail {
471+ return u .emails
472+ }
473+
474+ type userEmail struct {
475+ email models.UserEmail
476+ }
477+
478+ var _ proto.UserEmail = (* userEmail )(nil )
479+
480+ // Email implements proto.UserEmail.
481+ func (e * userEmail ) Email () string {
482+ return e .email .Email
483+ }
484+
485+ // ID implements proto.UserEmail.
486+ func (e * userEmail ) ID () int64 {
487+ return e .email .ID
488+ }
489+
490+ // IsPrimary implements proto.UserEmail.
491+ func (e * userEmail ) IsPrimary () bool {
492+ return e .email .IsPrimary
493+ }
0 commit comments