2020-05-20 11:13:14 +02:00
|
|
|
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
|
2020-05-26 11:11:53 +02:00
|
|
|
RememberMe bool
|
|
|
|
ClientName string
|
|
|
|
ClientURI string
|
2020-05-20 11:13:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
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,
|
2020-05-26 11:11:53 +02:00
|
|
|
req.RememberMe,
|
2020-05-20 11:13:14 +02:00
|
|
|
)
|
|
|
|
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{
|
2020-05-26 11:11:53 +02:00
|
|
|
"ClientName": req.ClientName,
|
|
|
|
"ClientURI": req.ClientURI,
|
2020-05-20 11:13:14 +02:00
|
|
|
"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),
|
2020-05-26 11:11:53 +02:00
|
|
|
mail.WithSubject(fmt.Sprintf("[%s] Connexion", req.ClientName)),
|
2020-05-20 11:13:14 +02:00
|
|
|
mail.WithBody(mail.ContentTypeHTML, html, nil),
|
|
|
|
mail.WithAlternativeBody(mail.ContentTypeText, "", nil),
|
|
|
|
)
|
|
|
|
if err != nil {
|
|
|
|
return errors.Wrap(err, "could not send email")
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|