Skip to content

Commit

Permalink
Add new SetHmacKeys API method
Browse files Browse the repository at this point in the history
  • Loading branch information
neekolas committed Feb 29, 2024
1 parent 47481e5 commit 4ce9679
Show file tree
Hide file tree
Showing 12 changed files with 700 additions and 89 deletions.
33 changes: 25 additions & 8 deletions mocks/Installations.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

46 changes: 39 additions & 7 deletions mocks/Subscriptions.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

35 changes: 35 additions & 0 deletions pkg/api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,21 @@ func (s *ApiServer) Unsubscribe(
return connect.NewResponse(&emptypb.Empty{}), nil
}

func (s *ApiServer) SetHmacKeys(ctx context.Context, req *connect.Request[proto.SetHmacKeysRequest]) (*connect.Response[emptypb.Empty], error) {
s.logger.Info("SetHmacKeys", zap.Any("headers", req.Header()), zap.Any("req", req))
updates, err := convertHmacUpdates(req.Msg.Updates)
if err != nil {
return nil, connect.NewError(connect.CodeInvalidArgument, err)
}
err = s.subscriptions.SetHmacKeys(ctx, req.Msg.InstallationId, updates)
if err != nil {
s.logger.Error("error setting hmac keys", zap.Error(err))
return nil, connect.NewError(connect.CodeInternal, err)
}

return connect.NewResponse(&emptypb.Empty{}), nil
}

func convertDeliveryMechanism(mechanism *proto.DeliveryMechanism) *interfaces.DeliveryMechanism {
if mechanism == nil {
return nil
Expand All @@ -152,3 +167,23 @@ func convertDeliveryMechanism(mechanism *proto.DeliveryMechanism) *interfaces.De
return &interfaces.DeliveryMechanism{Kind: interfaces.FCM, Token: fcmToken}
}
}

func convertHmacUpdates(protoUpdates []*proto.SetHmacKeysRequest_KeyUpdates) (interfaces.HmacUpdates, error) {
out := make(interfaces.HmacUpdates)
for _, update := range protoUpdates {
if update == nil {
continue
}
if _, exists := out[update.Topic]; exists {
return nil, fmt.Errorf("duplicate topic: %s", update.Topic)
}
for _, key := range update.HmacKey {
out[update.Topic] = append(out[update.Topic], interfaces.HmacUpdate{
ThirtyDayPeriodsSinceEpoch: int(key.ThirtyDayPeriodsSinceEpoch),
Key: key.Key,
})
}
}

return out, nil
}
5 changes: 5 additions & 0 deletions pkg/db/migrations/20240229061721_add-hmac-keys.down.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
SET statement_timeout = 0;

--bun:split

DROP TABLE subscription_hmac_keys;
13 changes: 13 additions & 0 deletions pkg/db/migrations/20240229061721_add-hmac-keys.up.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
SET statement_timeout = 0;

--bun:split

CREATE TABLE subscription_hmac_keys (
subscription_id INTEGER NOT NULL,
thirty_day_periods_since_epoch INTEGER NOT NULL,
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW(),
key BYTEA NOT NULL,
PRIMARY KEY (subscription_id, thirty_day_periods_since_epoch),
FOREIGN KEY (subscription_id) REFERENCES subscriptions(id) ON DELETE CASCADE
);
9 changes: 9 additions & 0 deletions pkg/db/models.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,12 @@ type Subscription struct {
Topic string `bun:"topic,notnull"`
IsActive bool `bun:"is_active,notnull"`
}

type SubscriptionHmacKeys struct {
bun.BaseModel `bun:"table:subscription_hmac_keys"`
SubscriptionId int64 `bun:"subscription_id,notnull,pk"`
ThirtyDayPeriodsSinceEpoch int32 `bun:"thirty_day_periods_since_epoch,notnull,pk"`
Key []byte `bun:"key,notnull,type:bytea"`
CreatedAt time.Time `bun:"created_at,notnull,default:current_timestamp"`
UpdatedAt time.Time `bun:"updated_at,notnull,default:current_timestamp"`
}
12 changes: 12 additions & 0 deletions pkg/interfaces/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,18 +49,30 @@ type SendRequest struct {
Message *v1.Envelope
}

type HmacUpdate struct {
ThirtyDayPeriodsSinceEpoch int
Key []byte
}

type HmacUpdates map[string][]HmacUpdate

// Pluggable Installation Service interface
//
//go:generate mockery --dir ../interfaces --name Installations --output ../../mocks --outpkg mocks
type Installations interface {
Register(ctx context.Context, installation Installation) (*RegisterResponse, error)
Delete(ctx context.Context, installationId string) error
GetInstallations(ctx context.Context, installationIds []string) ([]Installation, error)
}

// This interface is not expected to be pluggable
//
//go:generate mockery --dir ../interfaces --name Subscriptions --output ../../mocks --outpkg mocks
type Subscriptions interface {
Subscribe(ctx context.Context, installationId string, topics []string) error
Unsubscribe(ctx context.Context, installationId string, topics []string) error
GetSubscriptions(ctx context.Context, topic string) ([]Subscription, error)
SetHmacKeys(ctx context.Context, installationId string, updates HmacUpdates) error
}

// Pluggable interface for sending push notifications
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 4ce9679

Please sign in to comment.