+2
models/models.go
+2
models/models.go
+29
-14
server/handle_server_create_session.go
+29
-14
server/handle_server_create_session.go
···
1
1
package server
2
2
3
3
import (
4
+
"context"
4
5
"errors"
5
6
"fmt"
6
7
"strings"
···
87
88
88
89
// if repo requires auth factor token and one hasn't been provided, return error prompting for one
89
90
if repo.EmailAuthFactor && (req.AuthFactorToken == nil || *req.AuthFactorToken == "") {
90
-
code := fmt.Sprintf("%s-%s", helpers.RandomVarchar(5), helpers.RandomVarchar(5))
91
-
eat := time.Now().Add(10 * time.Minute).UTC()
92
-
93
-
if err := s.db.Exec(ctx, "UPDATE repos SET email_update_code = ?, email_update_code_expires_at = ? WHERE did = ?", nil, code, eat, repo.Repo.Did).Error; err != nil {
94
-
s.logger.Error("error updating repo", "error", err)
95
-
return helpers.ServerError(e, nil)
96
-
}
97
-
98
-
if err := s.sendEmailUpdate(repo.Email, repo.Handle, code); err != nil {
99
-
s.logger.Error("error sending email", "error", err)
91
+
err = s.createAndSendAuthCode(ctx, repo)
92
+
if err != nil {
93
+
s.logger.Error("sending auth code", "error", err)
100
94
return helpers.ServerError(e, nil)
101
95
}
102
96
···
105
99
106
100
// if auth factor is required, now check that the one provided is valid
107
101
if repo.EmailAuthFactor {
108
-
if repo.EmailUpdateCode == nil || repo.EmailUpdateCodeExpiresAt == nil {
109
-
return helpers.InvalidTokenError(e)
102
+
if repo.AuthCode == nil || repo.AuthCodeExpiresAt == nil {
103
+
err = s.createAndSendAuthCode(ctx, repo)
104
+
if err != nil {
105
+
s.logger.Error("sending auth code", "error", err)
106
+
return helpers.ServerError(e, nil)
107
+
}
108
+
109
+
return helpers.InputError(e, to.StringPtr("AuthFactorTokenRequired"))
110
110
}
111
111
112
-
if *repo.EmailUpdateCode != *req.AuthFactorToken {
112
+
if *repo.AuthCode != *req.AuthFactorToken {
113
113
return helpers.InvalidTokenError(e)
114
114
}
115
115
116
-
if time.Now().UTC().After(*repo.EmailUpdateCodeExpiresAt) {
116
+
if time.Now().UTC().After(*repo.AuthCodeExpiresAt) {
117
117
return helpers.ExpiredTokenError(e)
118
118
}
119
119
}
···
143
143
Status: repo.Status(),
144
144
})
145
145
}
146
+
147
+
func (s *Server) createAndSendAuthCode(ctx context.Context, repo models.RepoActor) error {
148
+
code := fmt.Sprintf("%s-%s", helpers.RandomVarchar(5), helpers.RandomVarchar(5))
149
+
eat := time.Now().Add(10 * time.Minute).UTC()
150
+
151
+
if err := s.db.Exec(ctx, "UPDATE repos SET auth_code = ?, auth_code_expires_at = ? WHERE did = ?", nil, code, eat, repo.Repo.Did).Error; err != nil {
152
+
return fmt.Errorf("updating repo: %w", err)
153
+
}
154
+
155
+
if err := s.sendAuthCode(repo.Email, repo.Handle, code); err != nil {
156
+
return fmt.Errorf("sending email: %w", err)
157
+
}
158
+
159
+
return nil
160
+
}
+19
server/mail.go
+19
server/mail.go
···
96
96
97
97
return nil
98
98
}
99
+
100
+
func (s *Server) sendAuthCode(email, handle, code string) error {
101
+
if s.mail == nil {
102
+
return nil
103
+
}
104
+
105
+
s.mailLk.Lock()
106
+
defer s.mailLk.Unlock()
107
+
108
+
s.mail.To(email)
109
+
s.mail.Subject("2FA code for " + s.config.Hostname)
110
+
s.mail.Plain().Set(fmt.Sprintf("Hello %s. Your 2FA code is %s. This code will expire in ten minutes.", handle, code))
111
+
112
+
if err := s.mail.Send(); err != nil {
113
+
return err
114
+
}
115
+
116
+
return nil
117
+
}