all repos

onasty @ c9bc2f8

a one-time notes service

onasty/internal/events/mailermq/mailermq.go(view raw)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
package mailermq

import (
	"context"
	"encoding/json"

	"github.com/nats-io/nats.go"
	"github.com/olexsmir/onasty/internal/events"
	"github.com/olexsmir/onasty/internal/transport/http/reqid"
)

const sendTopic = "mailer.send"

type Mailer interface {
	// SendVerificationEmail sends an email with a verification token to the user.
	SendVerificationEmail(ctx context.Context, input SendVerificationEmailRequest) error

	// SendPasswordResetEmail sends an email with a password reset token to the user.
	SendPasswordResetEmail(ctx context.Context, input SendPasswordResetEmailRequest) error

	// SendChangeEmailVerification sends an email with a change email verification token to the user.
	SendChangeEmailConfirmation(ctx context.Context, inp SendChangeEmailConfirmationRequest) error
}

type MailerMQ struct {
	nc *nats.Conn
}

func New(nc *nats.Conn) *MailerMQ {
	return &MailerMQ{
		nc: nc,
	}
}

type sendRequest struct {
	RequestID    string            `json:"request_id"`
	Receiver     string            `json:"receiver"`
	TemplateName string            `json:"template_name"`
	Options      map[string]string `json:"options"`
}

type SendVerificationEmailRequest struct {
	Receiver string
	Token    string
}

func (m MailerMQ) SendVerificationEmail(
	ctx context.Context,
	inp SendVerificationEmailRequest,
) error {
	req, err := json.Marshal(sendRequest{
		RequestID:    reqid.GetContext(ctx),
		Receiver:     inp.Receiver,
		TemplateName: "email_verification",
		Options: map[string]string{
			"token": inp.Token,
		},
	})
	if err != nil {
		return err
	}

	resp, err := m.nc.RequestWithContext(ctx, sendTopic, req)
	if err != nil {
		return err
	}

	return events.CheckRespForError(resp)
}

type SendPasswordResetEmailRequest struct {
	Receiver string
	Token    string
}

func (m MailerMQ) SendPasswordResetEmail(
	ctx context.Context,
	inp SendPasswordResetEmailRequest,
) error {
	req, err := json.Marshal(sendRequest{
		RequestID:    reqid.GetContext(ctx),
		Receiver:     inp.Receiver,
		TemplateName: "reset_password",
		Options: map[string]string{
			"token": inp.Token,
		},
	})
	if err != nil {
		return err
	}

	resp, err := m.nc.RequestWithContext(ctx, sendTopic, req)
	if err != nil {
		return err
	}

	return events.CheckRespForError(resp)
}

type SendChangeEmailConfirmationRequest struct {
	Receiver string
	Token    string
	NewEmail string
}

func (m MailerMQ) SendChangeEmailConfirmation(
	ctx context.Context,
	inp SendChangeEmailConfirmationRequest,
) error {
	req, err := json.Marshal(sendRequest{
		RequestID:    reqid.GetContext(ctx),
		Receiver:     inp.Receiver,
		TemplateName: "confirm_email_change",
		Options: map[string]string{
			"token": inp.Token,
			"email": inp.NewEmail,
		},
	})
	if err != nil {
		return err
	}

	resp, err := m.nc.RequestWithContext(ctx, sendTopic, req)
	if err != nil {
		return err
	}

	return events.CheckRespForError(resp)
}