hydra-passwordless/internal/command/send_confirmation_email.go

106 lines
2.6 KiB
Go

package command
import (
"bytes"
"context"
"fmt"
"forge.cadoles.com/wpetit/hydra-passwordless/internal/config"
"forge.cadoles.com/wpetit/hydra-passwordless/internal/hydra"
"forge.cadoles.com/wpetit/hydra-passwordless/internal/mail"
"forge.cadoles.com/wpetit/hydra-passwordless/internal/token"
"github.com/aymerick/douceur/inliner"
"github.com/pkg/errors"
"gitlab.com/wpetit/goweb/cqrs"
"gitlab.com/wpetit/goweb/middleware/container"
"gitlab.com/wpetit/goweb/service/build"
"gitlab.com/wpetit/goweb/service/template"
)
type SendConfirmationEmailRequest struct {
Email string
Challenge string
DefaultScheme string
DefaultAddress string
RememberMe bool
ClientName string
ClientURI string
}
func HandleSendConfirmationEmailRequest(ctx context.Context, cmd cqrs.Command) error {
req, ok := cmd.Request().(*SendConfirmationEmailRequest)
if !ok {
return cqrs.ErrUnexpectedRequest
}
ctn := container.Must(ctx)
tmpl := template.Must(ctn)
hydr := hydra.Must(ctn)
info := build.Must(ctn)
ml := mail.Must(ctn)
conf := config.Must(ctn)
_, err := hydr.LoginRequest(req.Challenge)
if err != nil {
return errors.Wrap(err, "could not retrieve hydra login response")
}
token, err := token.Generate(
conf.HTTP.TokenSigningKey,
conf.HTTP.TokenEncryptionKey,
req.Email,
req.Challenge,
req.RememberMe,
)
if err != nil {
return errors.Wrap(err, "could not generate jwt")
}
address := req.DefaultAddress
if conf.HTTP.PublicAddress != "" {
address = conf.HTTP.PublicAddress
}
scheme := req.DefaultScheme
if scheme == "" {
scheme = "http:"
}
if conf.HTTP.PublicScheme != "" {
scheme = conf.HTTP.PublicScheme
}
verificationLink := fmt.Sprintf("%s//%s/verify?token=%s", scheme, address, token)
data := template.Data{
"ClientName": req.ClientName,
"ClientURI": req.ClientURI,
"BuildInfo": info,
"VerificationLink": verificationLink,
}
var buf bytes.Buffer
if err := tmpl.Render(&buf, "verification_email.html.tmpl", data); err != nil {
return errors.Wrap(err, "could not render email template")
}
// Inline CSS for mail clients
html, err := inliner.Inline(buf.String())
if err != nil {
return errors.Wrap(err, "could not inline css")
}
err = ml.Send(
mail.WithSender(conf.SMTP.SenderAddress, conf.SMTP.SenderName),
mail.WithRecipients(req.Email),
mail.WithSubject(fmt.Sprintf("[%s] Connexion", req.ClientName)),
mail.WithBody(mail.ContentTypeHTML, html, nil),
mail.WithAlternativeBody(mail.ContentTypeText, "", nil),
)
if err != nil {
return errors.Wrap(err, "could not send email")
}
return nil
}