package auth import ( "net/http" "strings" "codeberg.org/pronounscc/pronouns.cc/backend/common" "codeberg.org/pronounscc/pronouns.cc/backend/server" "emperror.dev/errors" "github.com/go-chi/render" "github.com/mediocregopher/radix/v4" ) type postEmailSignupRequest struct { Email string `json:"email"` } func (s *Server) postEmailSignup(w http.ResponseWriter, r *http.Request) (err error) { ctx := r.Context() var req postEmailSignupRequest err = render.Decode(r, &req) if err != nil { return server.APIError{Code: server.ErrBadRequest} } if !strings.Contains(req.Email, "@") { return server.APIError{Code: server.ErrBadRequest, Details: "Email seems to be invalid"} } ticket := common.RandBase64(48) err = s.DB.Redis.Do(ctx, radix.Cmd(nil, "SET", emailSignupTicketKey(ticket), req.Email, "EX", "3600")) if err != nil { return errors.Wrap(err, "setting email signup key") } // if the email address already exists, pretend we sent an email and return // to prevent people from discovering valid email addresses exists, err := s.DB.EmailExists(ctx, req.Email) if err != nil { return errors.Wrap(err, "checking if email exists") } if exists { render.NoContent(w, r) return nil } go s.SendEmail(req.Email, "Confirm your email address", "signup", map[string]any{ "ticket": ticket, }) return nil } func emailSignupTicketKey(ticket string) string { return "email-signup:" + ticket }