Send an email if you sign up with an existing email
This commit is contained in:
parent
7b2d016fe2
commit
368e657a79
|
@ -48,7 +48,47 @@ func SendRegistrationEmail(
|
||||||
perf.EndBlock()
|
perf.EndBlock()
|
||||||
|
|
||||||
perf.StartBlock("EMAIL", "Sending email")
|
perf.StartBlock("EMAIL", "Sending email")
|
||||||
err = sendMail(toAddress, toName, "[handmade.network] Registration confirmation", contents)
|
err = sendMail(toAddress, toName, "[Handmade Network] Registration confirmation", contents)
|
||||||
|
if err != nil {
|
||||||
|
return oops.New(err, "Failed to send email")
|
||||||
|
}
|
||||||
|
perf.EndBlock()
|
||||||
|
|
||||||
|
perf.EndBlock()
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type ExistingAccountEmailData struct {
|
||||||
|
Name string
|
||||||
|
Username string
|
||||||
|
HomepageUrl string
|
||||||
|
LoginUrl string
|
||||||
|
}
|
||||||
|
|
||||||
|
func SendExistingAccountEmail(
|
||||||
|
toAddress string,
|
||||||
|
toName string,
|
||||||
|
username string,
|
||||||
|
destination string,
|
||||||
|
perf *perf.RequestPerf,
|
||||||
|
) error {
|
||||||
|
perf.StartBlock("EMAIL", "Existing account email")
|
||||||
|
|
||||||
|
perf.StartBlock("EMAIL", "Rendering template")
|
||||||
|
contents, err := renderTemplate("email_account_existing.html", ExistingAccountEmailData{
|
||||||
|
Name: toName,
|
||||||
|
Username: username,
|
||||||
|
HomepageUrl: hmnurl.BuildHomepage(),
|
||||||
|
LoginUrl: hmnurl.BuildLoginPage(destination),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
perf.EndBlock()
|
||||||
|
|
||||||
|
perf.StartBlock("EMAIL", "Sending email")
|
||||||
|
err = sendMail(toAddress, toName, "[Handmade Network] You already have an account!", contents)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return oops.New(err, "Failed to send email")
|
return oops.New(err, "Failed to send email")
|
||||||
}
|
}
|
||||||
|
@ -80,7 +120,7 @@ func SendPasswordReset(toAddress string, toName string, username string, resetTo
|
||||||
perf.EndBlock()
|
perf.EndBlock()
|
||||||
|
|
||||||
perf.StartBlock("EMAIL", "Sending email")
|
perf.StartBlock("EMAIL", "Sending email")
|
||||||
err = sendMail(toAddress, toName, "[handmade.network] Your password reset request", contents)
|
err = sendMail(toAddress, toName, "[Handmade Network] Your password reset request", contents)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return oops.New(err, "Failed to send email")
|
return oops.New(err, "Failed to send email")
|
||||||
}
|
}
|
||||||
|
@ -118,7 +158,7 @@ func SendTimeMachineEmail(profileUrl, username, userEmail, discordUsername strin
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = sendMail("team@handmade.network", "HMN Team", "[time machine] New submission", contents)
|
err = sendMail("team@handmade.network", "HMN Team", "[Time Machine] New submission", contents)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return oops.New(err, "Failed to send email")
|
return oops.New(err, "Failed to send email")
|
||||||
}
|
}
|
||||||
|
|
|
@ -165,7 +165,11 @@ var RegexLoginPage = regexp.MustCompile("^/login$")
|
||||||
|
|
||||||
func BuildLoginPage(redirectTo string) string {
|
func BuildLoginPage(redirectTo string) string {
|
||||||
defer CatchPanic()
|
defer CatchPanic()
|
||||||
return Url("/login", []Q{{Name: "redirect", Value: redirectTo}})
|
var q []Q
|
||||||
|
if redirectTo != "" {
|
||||||
|
q = append(q, Q{Name: "redirect", Value: redirectTo})
|
||||||
|
}
|
||||||
|
return Url("/login", q)
|
||||||
}
|
}
|
||||||
|
|
||||||
var RegexLoginWithDiscord = regexp.MustCompile("^/login-with-discord$")
|
var RegexLoginWithDiscord = regexp.MustCompile("^/login-with-discord$")
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
<p>
|
||||||
|
Hello {{ .Name }} - you already have a <a href="{{ .HomepageUrl }}">Handmade Network</a> account. Welcome back!
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Your username is <b>{{ .Username }}</b>. To sign in, please visit the following link and try signing in with your existing username:
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<a href="{{ .LoginUrl }}">{{ .LoginUrl }}</a>
|
||||||
|
</p>
|
||||||
|
<p>Thanks,<br />
|
||||||
|
The Handmade Network staff.</p>
|
||||||
|
|
||||||
|
<hr />
|
||||||
|
<p style="font-size:small; -webkit-text-size-adjust:none; color: #666">
|
||||||
|
You are receiving this email because someone tried creating a new account with your email address at <a href="{{ .HomepageUrl }}">handmade.network</a>. If that wasn't you, kindly ignore this email.
|
||||||
|
</p>
|
|
@ -5,7 +5,7 @@
|
||||||
To complete the registration process, please use the following link:
|
To complete the registration process, please use the following link:
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<a href="{{ .CompleteRegistrationUrl }}">{{ .CompleteRegistrationUrl }}</a>.
|
<a href="{{ .CompleteRegistrationUrl }}">{{ .CompleteRegistrationUrl }}</a>
|
||||||
</p>
|
</p>
|
||||||
<p>Thanks,<br />
|
<p>Thanks,<br />
|
||||||
The Handmade Network staff.</p>
|
The Handmade Network staff.</p>
|
||||||
|
|
|
@ -232,26 +232,38 @@ func RegisterNewUserSubmit(c *RequestContext) ResponseData {
|
||||||
return c.RejectRequest(fmt.Sprintf("Username (%s) already exists.", username))
|
return c.RejectRequest(fmt.Sprintf("Username (%s) already exists.", username))
|
||||||
}
|
}
|
||||||
|
|
||||||
emailAlreadyExists := true
|
existingUser, err := db.QueryOne[models.User](c, c.Conn,
|
||||||
_, err = db.QueryOneScalar[int](c, c.Conn,
|
|
||||||
`
|
`
|
||||||
SELECT id
|
SELECT $columns
|
||||||
FROM hmn_user
|
FROM hmn_user
|
||||||
WHERE LOWER(email) = LOWER($1)
|
WHERE LOWER(email) = LOWER($1)
|
||||||
`,
|
`,
|
||||||
emailAddress,
|
emailAddress,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if errors.Is(err, db.NotFound) {
|
||||||
if errors.Is(err, db.NotFound) {
|
// this is fine
|
||||||
emailAlreadyExists = false
|
} else if err != nil {
|
||||||
} else {
|
return c.ErrorResponse(http.StatusInternalServerError, oops.New(err, "failed to fetch user"))
|
||||||
return c.ErrorResponse(http.StatusInternalServerError, oops.New(err, "failed to fetch user"))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
c.Perf.EndBlock()
|
c.Perf.EndBlock()
|
||||||
|
|
||||||
if emailAlreadyExists {
|
if existingUser != nil {
|
||||||
// NOTE(asaf): Silent rejection so we don't allow attackers to harvest emails.
|
// Render the page as if it was a successful new registration, but
|
||||||
|
// instead send an email to the duplicate email address containing
|
||||||
|
// their actual username. Spammers won't be able to harvest emails, but
|
||||||
|
// normal users will be able to find and access their old accounts.
|
||||||
|
|
||||||
|
err := email.SendExistingAccountEmail(
|
||||||
|
existingUser.Email,
|
||||||
|
existingUser.BestName(),
|
||||||
|
existingUser.Username,
|
||||||
|
destination,
|
||||||
|
c.Perf,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return c.ErrorResponse(http.StatusInternalServerError, oops.New(err, "failed to send existing account email"))
|
||||||
|
}
|
||||||
|
|
||||||
return c.Redirect(hmnurl.BuildRegistrationSuccess(), http.StatusSeeOther)
|
return c.Redirect(hmnurl.BuildRegistrationSuccess(), http.StatusSeeOther)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue