Skip to content

Commit ce2a7d2

Browse files
committed
feat: add changes from portal
1 parent 3b4d8d1 commit ce2a7d2

File tree

4 files changed

+117
-5
lines changed

4 files changed

+117
-5
lines changed

api/auth_verify.go

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"github.com/semaphoreui/semaphore/db"
1111
"github.com/semaphoreui/semaphore/util"
1212
"github.com/semaphoreui/semaphore/util/mailer"
13+
log "github.com/sirupsen/logrus"
1314
)
1415

1516
//go:embed templates/*.tmpl
@@ -80,6 +81,13 @@ func sendEmailVerificationCode(code string, email string) error {
8081
return err
8182
}
8283

84+
content := body.String()
85+
86+
log.WithFields(log.Fields{
87+
"email": email,
88+
"context": "send_email_verification_code",
89+
}).Info("send email otp code")
90+
8391
err = mailer.Send(
8492
util.Config.EmailSecure,
8593
util.Config.EmailTls,
@@ -89,10 +97,19 @@ func sendEmailVerificationCode(code string, email string) error {
8997
util.Config.EmailPassword,
9098
util.Config.EmailSender,
9199
email,
92-
"Email Verification Code",
93-
body.String(),
100+
"Email verification code",
101+
content,
94102
)
95103

104+
if err != nil {
105+
106+
log.WithError(err).WithFields(log.Fields{
107+
"email": email,
108+
"context": "send_email_verification_code",
109+
}).Error("failed to send email verification code")
110+
111+
}
112+
96113
return err
97114
}
98115

api/login.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -158,9 +158,11 @@ func createSession(w http.ResponseWriter, r *http.Request, user db.User, oidc bo
158158
switch {
159159
case user.Totp != nil && util.Config.Auth.Totp.Enabled:
160160
verificationMethod = db.SessionVerificationTotp
161+
161162
case util.Config.Auth.Email.Enabled && (!util.Config.Auth.Email.DisableForOidc || !oidc):
162-
code := random.Number(6)
163-
_, err = helpers.Store(r).AddEmailOtpVerification(user.ID, code)
163+
164+
err = newEmailOtp(user.ID, user.Email, helpers.Store(r))
165+
164166
if err != nil {
165167
log.WithError(err).WithFields(log.Fields{
166168
"user_id": user.ID,

api/login_email.go

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
package api
2+
3+
import (
4+
"errors"
5+
"github.com/semaphoreui/semaphore/api/helpers"
6+
"github.com/semaphoreui/semaphore/db"
7+
"github.com/semaphoreui/semaphore/pkg/random"
8+
log "github.com/sirupsen/logrus"
9+
"net/http"
10+
)
11+
12+
func newEmailOtp(userID int, userEmail string, store db.Store) error {
13+
code := random.Number(6)
14+
_, err := store.AddEmailOtpVerification(userID, code)
15+
16+
if err != nil {
17+
return err
18+
}
19+
err = sendEmailVerificationCode(code, userEmail)
20+
return err
21+
}
22+
23+
func resendEmailOtp(w http.ResponseWriter, r *http.Request) {
24+
25+
session, ok := getSession(r)
26+
27+
if !ok {
28+
w.WriteHeader(http.StatusUnauthorized)
29+
return
30+
}
31+
32+
user, err := helpers.Store(r).GetUser(session.UserID)
33+
34+
if err != nil {
35+
helpers.WriteErrorStatus(w, "User not found", http.StatusUnauthorized)
36+
return
37+
}
38+
39+
err = newEmailOtp(session.UserID, user.Email, helpers.Store(r))
40+
if err != nil {
41+
log.WithError(err).WithFields(log.Fields{
42+
"user_id": session.UserID,
43+
"context": "resend_email_otp",
44+
}).Error("Failed to add email otp verification")
45+
helpers.WriteErrorStatus(w, "Failed to create email OTP verification", http.StatusInternalServerError)
46+
return
47+
}
48+
}
49+
50+
func loginEmail(w http.ResponseWriter, r *http.Request) {
51+
52+
var email struct {
53+
Email string `json:"email" binding:"required"`
54+
}
55+
if !helpers.Bind(w, r, &email) {
56+
return
57+
}
58+
59+
store := helpers.Store(r)
60+
61+
user, err := store.GetUserByLoginOrEmail("", email.Email)
62+
63+
if err != nil {
64+
if errors.Is(err, db.ErrNotFound) {
65+
user, err = store.CreateUserWithoutPassword(db.User{
66+
Email: email.Email,
67+
External: true,
68+
Alert: true,
69+
Pro: true,
70+
Name: getRandomProfileName(),
71+
Username: getRandomUsername(),
72+
})
73+
} else {
74+
var validationError *db.ValidationError
75+
switch {
76+
case errors.As(err, &validationError):
77+
// TODO: Return more informative error code.
78+
}
79+
80+
log.WithError(err).WithFields(log.Fields{
81+
"email": email.Email,
82+
"context": "loginEmail",
83+
}).Error("Failed to get or create user by email")
84+
w.WriteHeader(http.StatusInternalServerError)
85+
return
86+
}
87+
}
88+
89+
createSession(w, r, user, false)
90+
91+
w.WriteHeader(http.StatusNoContent)
92+
}

api/router.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,8 @@ func Route(
143143
publicAPIRouter.Use(StoreMiddleware, JSONMiddleware)
144144

145145
publicAPIRouter.HandleFunc("/auth/login", login).Methods("GET", "POST")
146-
publicAPIRouter.HandleFunc("/auth/verify/email", startEmailVerification).Methods("POST")
146+
publicAPIRouter.HandleFunc("/auth/login/email", loginEmail).Methods("GET", "POST")
147+
publicAPIRouter.HandleFunc("/auth/login/email/resend", resendEmailOtp).Methods("GET", "POST")
147148
publicAPIRouter.HandleFunc("/auth/verify", verifySession).Methods("POST")
148149
publicAPIRouter.HandleFunc("/auth/recovery", recoverySession).Methods("POST")
149150

0 commit comments

Comments
 (0)