Skip to content

Commit

Permalink
is: Remove email preferences check for admins
Browse files Browse the repository at this point in the history
  • Loading branch information
ryaplots committed Oct 22, 2024
1 parent 7cca109 commit 13edb65
Show file tree
Hide file tree
Showing 12 changed files with 121 additions and 123 deletions.
1 change: 1 addition & 0 deletions api/buf.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ lint:
- ttn/lorawan/v3/messages.proto
- ttn/lorawan/v3/metadata.proto
- ttn/lorawan/v3/rights.proto
- ttn/lorawan/v3/notification_service.proto
ENUM_VALUE_UPPER_SNAKE_CASE:
- ttn/lorawan/v3/rights.proto
ENUM_ZERO_VALUE_SUFFIX:
Expand Down
24 changes: 3 additions & 21 deletions api/ttn/lorawan/v3/notification_service.proto
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,7 @@ message Notification {
repeated NotificationReceiver receivers = 8;

// Whether an email was sent for the notification.
bool email = 9 [
deprecated = true
];
bool email = 9 [deprecated = true];

// The status of the notification.
NotificationStatus status = 10;
Expand All @@ -69,33 +67,19 @@ message Notification {
}

enum NotificationType {
option (thethings.json.enum) = {
marshal_as_string: true,
prefix: "NOTIFICATION_TYPE"
};
option (thethings.json.enum) = {marshal_as_string: true};

UNKNOWN = 0;

API_KEY_CREATED = 1;

API_KEY_CHANGED = 2;

CLIENT_REQUESTED = 3;

COLLABORATOR_CHANGED = 4;

ENTITY_STATE_CHANGED = 5;

INVITATION = 6;

LOGIN_TOKEN = 7;

PASSWORD_CHANGED = 8;

TEMPORARY_PASSWORD = 9;

USER_REQUESTED = 10;

VALIDATE = 11;
}

Expand Down Expand Up @@ -154,9 +138,7 @@ message CreateNotificationRequest {
}];

// Whether an email should be sent for the notification.
bool email = 6 [
deprecated = true
];
bool email = 6 [deprecated = true];
}

message CreateNotificationResponse {
Expand Down
2 changes: 1 addition & 1 deletion api/ttn/lorawan/v3/user.proto
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ import "thethings/json/annotations.proto";
import "ttn/lorawan/v3/contact_info.proto";
import "ttn/lorawan/v3/enums.proto";
import "ttn/lorawan/v3/identifiers.proto";
import "ttn/lorawan/v3/notification_service.proto";
import "ttn/lorawan/v3/picture.proto";
import "ttn/lorawan/v3/rights.proto";
import "ttn/lorawan/v3/notification_service.proto";
import "validate/validate.proto";

option go_package = "go.thethings.network/lorawan-stack/v3/pkg/ttnpb";
Expand Down
1 change: 0 additions & 1 deletion pkg/identityserver/bunstore/user_store.go
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,6 @@ func (s *userStore) CreateUser(ctx context.Context, pb *ttnpb.User) (*ttnpb.User

return nil
})

if err != nil {
return nil, storeutil.WrapDriverError(err)
}
Expand Down
19 changes: 11 additions & 8 deletions pkg/identityserver/invitation_registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,14 +68,17 @@ func (is *IdentityServer) sendInvitation(ctx context.Context, in *ttnpb.SendInvi
return nil, err
}
events.Publish(evtCreateInvitation.NewWithIdentifiersAndData(ctx, nil, invitation))
go is.SendTemplateEmailToUsers(is.FromRequestContext(ctx), ttnpb.NotificationType_INVITATION, func(ctx context.Context, data email.TemplateData) (email.TemplateData, error) {
return &templates.InvitationData{
TemplateData: data,
SenderIds: authInfo.GetEntityIdentifiers().GetUserIds(),
InvitationToken: invitation.Token,
TTL: ttl,
}, nil
}, &ttnpb.User{PrimaryEmailAddress: in.Email})
go is.SendTemplateEmailToUsers( // nolint:errcheck
is.FromRequestContext(ctx),
ttnpb.NotificationType_INVITATION,
func(_ context.Context, data email.TemplateData) (email.TemplateData, error) {
return &templates.InvitationData{
TemplateData: data,
SenderIds: authInfo.GetEntityIdentifiers().GetUserIds(),
InvitationToken: invitation.Token,
TTL: ttl,
}, nil
}, &ttnpb.User{PrimaryEmailAddress: in.Email})
return invitation, nil
}

Expand Down
38 changes: 24 additions & 14 deletions pkg/identityserver/notification_registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,18 @@ func notificationTypeAllowed(notificationType ttnpb.NotificationType, allowedNot
return false
}

func filterAllowedEmailReveivers(emailReceiverUsers []*ttnpb.User, notificationType ttnpb.NotificationType) []*ttnpb.UserIdentifiers {
var emailReceiverIDs []*ttnpb.UserIdentifiers
// Collect IDs of users that have email notifications enabled for that notification type.
for _, user := range emailReceiverUsers {
userNotificationPreferences := user.GetEmailNotificationPreferences().GetTypes()
if notificationTypeAllowed(notificationType, userNotificationPreferences) {
emailReceiverIDs = append(emailReceiverIDs, user.GetIds())
}
}
return emailReceiverIDs
}

func uniqueOrganizationOrUserIdentifiers(ctx context.Context, ids []*ttnpb.OrganizationOrUserIdentifiers) []*ttnpb.OrganizationOrUserIdentifiers {
out := make([]*ttnpb.OrganizationOrUserIdentifiers, 0, len(ids))
seen := make(map[string]struct{}, len(ids))
Expand Down Expand Up @@ -133,7 +145,10 @@ func (is *IdentityServer) getContactReceivers(
return entityID, nil
}

func (is *IdentityServer) lookupNotificationReceivers(ctx context.Context, req *ttnpb.CreateNotificationRequest) ([]*ttnpb.UserIdentifiers, []*ttnpb.UserIdentifiers, error) {
func (is *IdentityServer) lookupNotificationReceivers( //nolint:gocyclo
ctx context.Context,
req *ttnpb.CreateNotificationRequest,
) ([]*ttnpb.UserIdentifiers, []*ttnpb.UserIdentifiers, error) {
var receiverIDs []*ttnpb.OrganizationOrUserIdentifiers
var receiverUserIDs []*ttnpb.UserIdentifiers
var emailReceiverIDs []*ttnpb.UserIdentifiers
Expand Down Expand Up @@ -230,13 +245,10 @@ func (is *IdentityServer) lookupNotificationReceivers(ctx context.Context, req *
// Filter only user identifiers and remove duplicates.
receiverUserIDs = filterUserIdentifiers(uniqueOrganizationOrUserIdentifiers(ctx, receiverIDs))

receiverUsers, _ := st.FindUsers(ctx, receiverUserIDs, []string{"email_notification_preferences"})
for _, user := range receiverUsers {
userNotificationPreferences := user.GetEmailNotificationPreferences().GetTypes()
if notificationTypeAllowed(req.NotificationType, userNotificationPreferences) {
emailReceiverIDs = append(emailReceiverIDs, user.Ids)
}
}
// Get the email notification preferences of the receiver users.
emailReceiverUsers, _ := st.FindUsers(ctx, receiverUserIDs, []string{"email_notification_preferences"})
// Filter only the users that have email notifications enabled for the notification type.
emailReceiverIDs = filterAllowedEmailReveivers(emailReceiverUsers, req.NotificationType)

return nil
})
Expand Down Expand Up @@ -318,8 +330,7 @@ func (is *IdentityServer) notifyAdminsInternal(ctx context.Context, req *ttnpb.C
}
}

isAdminActionNotificationType := req.NotificationType == ttnpb.NotificationType_CLIENT_REQUESTED || req.NotificationType == ttnpb.NotificationType_USER_REQUESTED
if isAdminActionNotificationType && email.GetNotification(ctx, req.GetNotificationType()) == nil {
if email.GetNotification(ctx, req.GetNotificationType()) == nil {
log.FromContext(ctx).WithField("notification_type", req.GetNotificationType()).Warn("email template for notification not registered")
}

Expand All @@ -342,10 +353,9 @@ func (is *IdentityServer) notifyAdminsInternal(ctx context.Context, req *ttnpb.C
return err
}

if isAdminActionNotificationType {
if err := is.SendNotificationEmailToUsers(ctx, notification, receivers...); err != nil {
return err
}
err = is.SendNotificationEmailToUsers(ctx, notification, receivers...)
if err != nil {
return err
}

return nil
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@ SELECT
FROM
accounts acc
JOIN users usr ON usr.id = acc.account_id
AND acc.account_type = 'user';
AND acc.account_type = 'user';
5 changes: 5 additions & 0 deletions pkg/identityserver/storetest/user_store.go
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,11 @@ func (st *StoreTest) TestUserStoreCRUD(t *T) {
ApiKey: ttnpb.DashboardLayout_DASHBOARD_LAYOUT_LIST,
},
},
EmailNotificationPreferences: &ttnpb.EmailNotificationPreferences{
Types: []ttnpb.NotificationType{
ttnpb.NotificationType_API_KEY_CREATED,
},
},
}, mask)
if a.So(err, should.BeNil) && a.So(updated, should.NotBeNil) {
a.So(updated.GetIds().GetUserId(), should.Equal, "foo")
Expand Down
16 changes: 9 additions & 7 deletions pkg/identityserver/user_registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -679,13 +679,15 @@ func (is *IdentityServer) createTemporaryPassword(ctx context.Context, req *ttnp
"temporary_password", temporaryPassword,
)).Info("Created temporary password")
events.Publish(evtUpdateUser.NewWithIdentifiersAndData(ctx, req.GetUserIds(), updateTemporaryPasswordFieldMask))
go is.SendTemplateEmailToUserIDs(is.FromRequestContext(ctx), ttnpb.NotificationType_TEMPORARY_PASSWORD, func(ctx context.Context, data email.TemplateData) (email.TemplateData, error) {
return &templates.TemporaryPasswordData{
TemplateData: data,
TemporaryPassword: temporaryPassword,
TTL: ttl,
}, nil
}, req.GetUserIds())
go is.SendTemplateEmailToUserIDs( // nolint:errcheck
is.FromRequestContext(ctx), ttnpb.NotificationType_TEMPORARY_PASSWORD,
func(_ context.Context, data email.TemplateData) (email.TemplateData, error) {
return &templates.TemporaryPasswordData{
TemplateData: data,
TemporaryPassword: temporaryPassword,
TTL: ttl,
}, nil
}, req.GetUserIds())

return ttnpb.Empty, nil
}
Expand Down
Loading

0 comments on commit 13edb65

Please sign in to comment.