Stage 11: account linking & merge (email + Telegram Login Widget) (#12)
Tests · Go / test (push) Successful in 7s
Tests · Integration / integration (push) Successful in 11s
Tests · UI / test (push) Successful in 18s

This commit was merged in pull request #12.
This commit is contained in:
2026-06-04 09:18:17 +00:00
parent 3a640a17a4
commit 01485d8fc6
68 changed files with 3331 additions and 369 deletions
@@ -38,17 +38,6 @@ type statsDTO struct {
MaxWordPoints int `json:"max_word_points"`
}
// emailBindRequestBody starts binding an email to the caller's account.
type emailBindRequestBody struct {
Email string `json:"email"`
}
// emailBindConfirmBody completes binding an email with its confirm code.
type emailBindConfirmBody struct {
Email string `json:"email"`
Code string `json:"code"`
}
// parseAwayTime parses an "HH:MM" away-window bound.
func parseAwayTime(s string) (time.Time, bool) {
t, err := time.Parse(awayTimeLayout, strings.TrimSpace(s))
@@ -117,43 +106,3 @@ func (s *Server) handleStats(c *gin.Context) {
MaxWordPoints: st.MaxWordPoints,
})
}
// handleEmailBindRequest issues a confirm code to bind an email to the caller.
func (s *Server) handleEmailBindRequest(c *gin.Context) {
uid, ok := userID(c)
if !ok {
abortBadRequest(c, "missing identity")
return
}
var req emailBindRequestBody
if err := c.ShouldBindJSON(&req); err != nil {
abortBadRequest(c, "invalid request body")
return
}
if err := s.emails.RequestCode(c.Request.Context(), uid, req.Email); err != nil {
s.abortErr(c, err)
return
}
c.JSON(http.StatusOK, okResponse{OK: true})
}
// handleEmailBindConfirm verifies the code and binds the email, returning the
// updated profile.
func (s *Server) handleEmailBindConfirm(c *gin.Context) {
uid, ok := userID(c)
if !ok {
abortBadRequest(c, "missing identity")
return
}
var req emailBindConfirmBody
if err := c.ShouldBindJSON(&req); err != nil {
abortBadRequest(c, "invalid request body")
return
}
acc, err := s.emails.ConfirmCode(c.Request.Context(), uid, req.Email, req.Code)
if err != nil {
s.abortErr(c, err)
return
}
c.JSON(http.StatusOK, profileResponseFor(acc))
}