account state changes #463
@@ -1,8 +1,60 @@
|
||||
package telegram
|
||||
|
||||
import "github.com/tech/sendico/pkg/model"
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/tech/sendico/pkg/model"
|
||||
)
|
||||
|
||||
const legacyContactRequestTopicSignup = "signup_request"
|
||||
|
||||
func newContactRequestTemplate(request *model.ContactRequest) messageTemplate {
|
||||
if request == nil {
|
||||
request = &model.ContactRequest{}
|
||||
}
|
||||
|
||||
switch normalizeContactRequestTopic(request.Topic) {
|
||||
case model.ContactRequestTopicAccountVerificationCompleted:
|
||||
return newAccountVerificationCompletedTemplate(request)
|
||||
case model.ContactRequestTopicSignupCompleted:
|
||||
return newSignupCompletedTemplate(request)
|
||||
default:
|
||||
return newSiteContactTemplate(request)
|
||||
}
|
||||
}
|
||||
|
||||
func normalizeContactRequestTopic(topic string) string {
|
||||
normalized := strings.ToLower(strings.TrimSpace(topic))
|
||||
if normalized == legacyContactRequestTopicSignup {
|
||||
return model.ContactRequestTopicSignupCompleted
|
||||
}
|
||||
return normalized
|
||||
}
|
||||
|
||||
func newAccountVerificationCompletedTemplate(request *model.ContactRequest) messageTemplate {
|
||||
return messageTemplate{
|
||||
title: "Account verification completed",
|
||||
emphasize: []string{"verification completed"},
|
||||
fields: []messageField{
|
||||
{label: "Name", value: request.Name},
|
||||
{label: "Email", value: request.Email},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func newSignupCompletedTemplate(request *model.ContactRequest) messageTemplate {
|
||||
return messageTemplate{
|
||||
title: "New signup completed",
|
||||
emphasize: []string{"signup completed"},
|
||||
fields: []messageField{
|
||||
{label: "Organization", value: request.Company},
|
||||
{label: "Name", value: request.Name},
|
||||
{label: "Email", value: request.Email},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func newSiteContactTemplate(request *model.ContactRequest) messageTemplate {
|
||||
return messageTemplate{
|
||||
title: "New site request received",
|
||||
emphasize: []string{"site request"},
|
||||
|
||||
@@ -0,0 +1,118 @@
|
||||
package telegram
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/tech/sendico/pkg/model"
|
||||
)
|
||||
|
||||
func TestNewContactRequestTemplate_SignupTopic(t *testing.T) {
|
||||
template := newContactRequestTemplate(&model.ContactRequest{
|
||||
Name: "Alice Example",
|
||||
Email: "alice@example.com",
|
||||
Company: "Acme Inc",
|
||||
Topic: model.ContactRequestTopicSignupCompleted,
|
||||
})
|
||||
|
||||
if template.title != "New signup completed" {
|
||||
t.Fatalf("unexpected title: %s", template.title)
|
||||
}
|
||||
if !reflect.DeepEqual(template.emphasize, []string{"signup completed"}) {
|
||||
t.Fatalf("unexpected emphasize words: %#v", template.emphasize)
|
||||
}
|
||||
|
||||
expectedFields := []messageField{
|
||||
{label: "Organization", value: "Acme Inc"},
|
||||
{label: "Name", value: "Alice Example"},
|
||||
{label: "Email", value: "alice@example.com"},
|
||||
}
|
||||
if !reflect.DeepEqual(template.fields, expectedFields) {
|
||||
t.Fatalf("unexpected fields: %#v", template.fields)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewContactRequestTemplate_LegacySignupTopic(t *testing.T) {
|
||||
template := newContactRequestTemplate(&model.ContactRequest{
|
||||
Name: "Alice Example",
|
||||
Email: "alice@example.com",
|
||||
Company: "Acme Inc",
|
||||
Topic: "signup_request",
|
||||
})
|
||||
|
||||
if template.title != "New signup completed" {
|
||||
t.Fatalf("unexpected title: %s", template.title)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewContactRequestTemplate_DefaultTopic(t *testing.T) {
|
||||
template := newContactRequestTemplate(&model.ContactRequest{
|
||||
Name: "Alice Example",
|
||||
Email: "alice@example.com",
|
||||
Phone: "+123456",
|
||||
Company: "Acme Inc",
|
||||
Topic: "partnership",
|
||||
Message: "Hi there",
|
||||
})
|
||||
|
||||
if template.title != "New site request received" {
|
||||
t.Fatalf("unexpected title: %s", template.title)
|
||||
}
|
||||
if !reflect.DeepEqual(template.emphasize, []string{"site request"}) {
|
||||
t.Fatalf("unexpected emphasize words: %#v", template.emphasize)
|
||||
}
|
||||
|
||||
expectedFields := []messageField{
|
||||
{label: "Name", value: "Alice Example"},
|
||||
{label: "Email", value: "alice@example.com"},
|
||||
{label: "Phone", value: "+123456"},
|
||||
{label: "Company", value: "Acme Inc"},
|
||||
{label: "Topic", value: "partnership"},
|
||||
{label: "Message", value: "Hi there"},
|
||||
}
|
||||
if !reflect.DeepEqual(template.fields, expectedFields) {
|
||||
t.Fatalf("unexpected fields: %#v", template.fields)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewContactRequestTemplate_AccountVerificationCompletedTopic(t *testing.T) {
|
||||
template := newContactRequestTemplate(&model.ContactRequest{
|
||||
Name: "Alice Example",
|
||||
Email: "alice@example.com",
|
||||
Topic: model.ContactRequestTopicAccountVerificationCompleted,
|
||||
})
|
||||
|
||||
if template.title != "Account verification completed" {
|
||||
t.Fatalf("unexpected title: %s", template.title)
|
||||
}
|
||||
if !reflect.DeepEqual(template.emphasize, []string{"verification completed"}) {
|
||||
t.Fatalf("unexpected emphasize words: %#v", template.emphasize)
|
||||
}
|
||||
|
||||
expectedFields := []messageField{
|
||||
{label: "Name", value: "Alice Example"},
|
||||
{label: "Email", value: "alice@example.com"},
|
||||
}
|
||||
if !reflect.DeepEqual(template.fields, expectedFields) {
|
||||
t.Fatalf("unexpected fields: %#v", template.fields)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewContactRequestTemplate_NilRequest(t *testing.T) {
|
||||
template := newContactRequestTemplate(nil)
|
||||
if template.title != "New site request received" {
|
||||
t.Fatalf("unexpected title: %s", template.title)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewContactRequestTemplate_LegacySignupTopicCaseInsensitive(t *testing.T) {
|
||||
template := newContactRequestTemplate(&model.ContactRequest{
|
||||
Name: "Alice Example",
|
||||
Email: "alice@example.com",
|
||||
Company: "Acme Inc",
|
||||
Topic: " SIGNUP_REQUEST ",
|
||||
})
|
||||
if template.title != "New signup completed" {
|
||||
t.Fatalf("unexpected title: %s", template.title)
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,12 @@ type ContactRequest struct {
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
const (
|
||||
ContactRequestTopicSiteContact = "site_contact_request"
|
||||
ContactRequestTopicSignupCompleted = "signup_completed"
|
||||
ContactRequestTopicAccountVerificationCompleted = "account_verification_completed"
|
||||
)
|
||||
|
||||
// Normalize trims whitespace from all string fields.
|
||||
func (cr *ContactRequest) Normalize() {
|
||||
if cr == nil {
|
||||
|
||||
@@ -44,6 +44,9 @@ func (a *AccountAPI) verify(r *http.Request) http.HandlerFunc {
|
||||
a.logger.Warn("Failed to save account while verifying account", zap.Error(err))
|
||||
return response.Internal(a.logger, a.Name(), err)
|
||||
}
|
||||
if err := a.sendAccountVerificationCompletedNotification(&user); err != nil {
|
||||
a.logger.Warn("Failed to enqueue account verification notification", zap.Error(err), zap.String("email", user.Login))
|
||||
}
|
||||
|
||||
// TODO: Send verification confirmation email
|
||||
return response.Success(a.logger)
|
||||
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
"github.com/tech/sendico/pkg/api/http/response"
|
||||
"github.com/tech/sendico/pkg/db/storable"
|
||||
"github.com/tech/sendico/pkg/merrors"
|
||||
snotifications "github.com/tech/sendico/pkg/messaging/notifications/site"
|
||||
"github.com/tech/sendico/pkg/model"
|
||||
"github.com/tech/sendico/pkg/mservice"
|
||||
"github.com/tech/sendico/pkg/mutil/mzap"
|
||||
@@ -104,10 +105,52 @@ func (a *AccountAPI) signup(r *http.Request) http.HandlerFunc {
|
||||
if err := a.sendWelcomeEmail(newAccount, verificationToken); err != nil {
|
||||
a.logger.Warn("Failed to send welcome email", zap.Error(err), mzap.StorableRef(newAccount))
|
||||
}
|
||||
if err := a.sendSignupNotification(newAccount, &sr); err != nil {
|
||||
a.logger.Warn("Failed to enqueue signup notification", zap.Error(err), zap.String("login", newAccount.Login))
|
||||
}
|
||||
|
||||
return sresponse.SignUp(a.logger, newAccount)
|
||||
}
|
||||
|
||||
func (a *AccountAPI) sendSignupNotification(account *model.Account, request *srequest.Signup) error {
|
||||
if account == nil || request == nil {
|
||||
return merrors.InvalidArgument("signup notification payload is empty")
|
||||
}
|
||||
|
||||
signupNotification := &model.ContactRequest{
|
||||
Name: accountNotificationName(account),
|
||||
Email: strings.TrimSpace(account.Login),
|
||||
Company: strings.TrimSpace(request.Organization.Name),
|
||||
Topic: model.ContactRequestTopicSignupCompleted,
|
||||
}
|
||||
|
||||
return a.producer.SendMessage(snotifications.ContactRequest(a.Name(), signupNotification))
|
||||
}
|
||||
|
||||
func (a *AccountAPI) sendAccountVerificationCompletedNotification(account *model.Account) error {
|
||||
if account == nil {
|
||||
return merrors.InvalidArgument("account verification notification payload is empty", "account")
|
||||
}
|
||||
|
||||
notification := &model.ContactRequest{
|
||||
Name: accountNotificationName(account),
|
||||
Email: strings.TrimSpace(account.Login),
|
||||
Topic: model.ContactRequestTopicAccountVerificationCompleted,
|
||||
}
|
||||
|
||||
return a.producer.SendMessage(snotifications.ContactRequest(a.Name(), notification))
|
||||
}
|
||||
|
||||
func accountNotificationName(account *model.Account) string {
|
||||
if account == nil {
|
||||
return ""
|
||||
}
|
||||
return strings.TrimSpace(strings.Join([]string{
|
||||
strings.TrimSpace(account.Name),
|
||||
strings.TrimSpace(account.LastName),
|
||||
}, " "))
|
||||
}
|
||||
|
||||
func (a *AccountAPI) signupAvailability(r *http.Request) http.HandlerFunc {
|
||||
login := strings.ToLower(strings.TrimSpace(r.URL.Query().Get("login")))
|
||||
if login == "" {
|
||||
|
||||
@@ -17,6 +17,9 @@ func (a *SiteAPI) contactRequest(r *http.Request) http.HandlerFunc {
|
||||
return response.BadRequest(a.logger, a.Name(), "invalid_payload", "Failed to decode contact request payload")
|
||||
}
|
||||
request.Normalize()
|
||||
if request.Topic == "" {
|
||||
request.Topic = model.ContactRequestTopicSiteContact
|
||||
}
|
||||
if err := request.Validate(); err != nil {
|
||||
a.logger.Warn("Contact request validation failed", zap.Error(err))
|
||||
return response.BadPayload(a.logger, a.Name(), err)
|
||||
|
||||
Reference in New Issue
Block a user