Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ go 1.25.8

require (
firebase.google.com/go/v4 v4.21.0
github.com/android-sms-gateway/client-go v1.14.5
github.com/android-sms-gateway/client-go v1.14.6-0.20260818010249-27de6c9d42cf
github.com/ansrivas/fiberprometheus/v2 v2.17.0
github.com/capcom6/go-helpers v0.4.0
github.com/capcom6/go-infra-fx v0.5.9
Expand Down
6 changes: 4 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,10 @@ github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc
github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE=
github.com/MicahParks/keyfunc v1.9.0 h1:lhKd5xrFHLNOWrDc4Tyb/Q1AJ4LCzQ48GVJyVIID3+o=
github.com/MicahParks/keyfunc v1.9.0/go.mod h1:IdnCilugA0O/99dW+/MkvlyrsX8+L8+x95xuVNtM5jw=
github.com/android-sms-gateway/client-go v1.14.5 h1:CtyXAHPdyDtCFTzeVPt5EUfnWhQ2RsIWbCUk52tbGjw=
github.com/android-sms-gateway/client-go v1.14.5/go.mod h1:DQsReciU1xcaVW3T5Z2bqslNdsAwCFCtghawmA6g6L4=
github.com/android-sms-gateway/client-go v1.14.5-0.20260812005854-c3143ac48b54 h1:i4pOpObty9ZHkQWE5JmJMrx4hAB6hmQ6elmgc/+3oKs=
github.com/android-sms-gateway/client-go v1.14.5-0.20260812005854-c3143ac48b54/go.mod h1:DQsReciU1xcaVW3T5Z2bqslNdsAwCFCtghawmA6g6L4=
github.com/android-sms-gateway/client-go v1.14.6-0.20260818010249-27de6c9d42cf h1:nNxdXmF6OL7H67X3XeY/kTa+ymJf8HtRFpo5qonR9Rk=
github.com/android-sms-gateway/client-go v1.14.6-0.20260818010249-27de6c9d42cf/go.mod h1:DQsReciU1xcaVW3T5Z2bqslNdsAwCFCtghawmA6g6L4=
github.com/andybalholm/brotli v1.2.2 h1:HzTuoo2ErYQqf5qvcJInB8uvqSVxRttzkFexPWtnceM=
github.com/andybalholm/brotli v1.2.2/go.mod h1:rzTDkvFWvIrjDXZHkuS16NPggd91W3kUSvPlQ1pLaKY=
github.com/ansrivas/fiberprometheus/v2 v2.17.0 h1:p0gqs5LsSCWGoSFF44fCJkyU+XcE6TLRqEMu80b2iCo=
Expand Down
4 changes: 4 additions & 0 deletions internal/sms-gateway/handlers/converters/devices.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ func DeviceToDTO(device devices.Device) smsgateway.Device {
DeletedAt: device.DeletedAt,
LastSeen: device.LastSeen,
SimCards: mapSimCards(device.SimCards),
VersionedPublicKey: smsgateway.VersionedPublicKey{
PublicKey: device.PublicKey,
KeyVersion: device.KeyVersion,
},
}
}

Expand Down
21 changes: 21 additions & 0 deletions internal/sms-gateway/handlers/converters/devices_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,27 @@ func TestDeviceToDTO(t *testing.T) {
Name: "",
},
},
{
name: "device with versioned public key",
device: devices.Device{
DeviceInput: devices.DeviceInput{
DeviceInfo: devices.DeviceInfo{
DeviceUpdate: devices.DeviceUpdate{
PublicKey: lo.ToPtr("test-public-key"),
KeyVersion: lo.ToPtr(1),
},
},
ID: "test-id",
},
},
expected: smsgateway.Device{
ID: "test-id",
VersionedPublicKey: smsgateway.VersionedPublicKey{
PublicKey: lo.ToPtr("test-public-key"),
KeyVersion: lo.ToPtr(1),
},
},
},
{
name: "device with sim cards",
device: devices.Device{
Expand Down
10 changes: 3 additions & 7 deletions internal/sms-gateway/handlers/messages/3rdparty.go
Original file line number Diff line number Diff line change
Expand Up @@ -327,13 +327,9 @@ func (h *ThirdPartyController) errorHandler(c *fiber.Ctx) error {
case errors.Is(err, messages.ErrMessageNotPending):
return fiber.NewError(fiber.StatusConflict, err.Error())

case errors.Is(err, devices.ErrNotFound):
fallthrough
case errors.Is(err, devices.ErrInvalidFilter):
fallthrough
case errors.Is(err, devices.ErrInvalidUser):
fallthrough
case errors.Is(err, devices.ErrMoreThanOne):
case errors.Is(err, devices.ErrNotFound),
errors.Is(err, devices.ErrInvalidFilter),
errors.Is(err, devices.ErrMoreThanOne):
return fiber.NewError(fiber.StatusBadRequest, err.Error())
}

Expand Down
12 changes: 8 additions & 4 deletions internal/sms-gateway/handlers/mobile.go
Original file line number Diff line number Diff line change
Expand Up @@ -195,8 +195,10 @@ func (h *mobileHandler) postDevice(c *fiber.Ctx) error {
userID,
devices.DeviceInfo{
DeviceUpdate: devices.DeviceUpdate{
PushToken: req.PushToken,
SimCards: h.simCardsToDomain(req.SimCards),
PushToken: req.PushToken,
SimCards: h.simCardsToDomain(req.SimCards),
PublicKey: req.PublicKey,
KeyVersion: req.KeyVersion,
},
Name: req.Name,
},
Expand Down Expand Up @@ -239,8 +241,10 @@ func (h *mobileHandler) patchDevice(device devices.Device, c *fiber.Ctx) error {
}

err := h.devicesSvc.Update(c.Context(), req.Id, devices.DeviceUpdate{
PushToken: lo.EmptyableToPtr(req.PushToken),
SimCards: h.simCardsToDomain(req.SimCards),
PushToken: req.PushToken,
SimCards: h.simCardsToDomain(req.SimCards),
PublicKey: req.PublicKey,
KeyVersion: req.KeyVersion,
})
if err != nil {
return fmt.Errorf("failed to update device: %w", err)
Comment thread
greptile-apps[bot] marked this conversation as resolved.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
-- +goose Up
-- +goose StatementBegin
ALTER TABLE `devices`
ADD `public_key` text NULL;
-- +goose StatementEnd
-- +goose StatementBegin
ALTER TABLE `devices`
ADD `key_version` int NULL DEFAULT NULL;
-- +goose StatementEnd
-- +goose StatementBegin
ALTER TABLE `message_recipients`
MODIFY COLUMN `phone_number` varchar(512) NOT NULL;
-- +goose StatementEnd
---
-- +goose Down
-- +goose StatementBegin
ALTER TABLE `message_recipients`
MODIFY COLUMN `phone_number` varchar(128) NOT NULL;
-- +goose StatementEnd
-- +goose StatementBegin
ALTER TABLE `devices` DROP `key_version`;
-- +goose StatementEnd
-- +goose StatementBegin
ALTER TABLE `devices` DROP `public_key`;
-- +goose StatementEnd
13 changes: 12 additions & 1 deletion internal/sms-gateway/modules/devices/domain.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package devices

import "time"
import (
"time"
)

type DeviceInput struct {
DeviceInfo
Expand All @@ -20,6 +22,15 @@ type DeviceInfo struct {
type DeviceUpdate struct {
PushToken *string
SimCards []SimCard
// PublicKey is a base64-encoded RSA public key (nil if no E2E).
// Setting a new key together with KeyVersion overwrites the previous key;
// clearing an existing key is intentionally unsupported. On insert, nil
// means the device is created without E2E; on update, a both-nil pair is
// a no-op that leaves the existing key unchanged.
PublicKey *string
// KeyVersion is the key version used for rotation tracking (nil if no
// E2E).
KeyVersion *int
Comment thread
capcom6 marked this conversation as resolved.
}

type Device struct {
Expand Down
4 changes: 3 additions & 1 deletion internal/sms-gateway/modules/devices/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,7 @@ package devices
import "errors"

var (
ErrInvalidUser = errors.New("invalid user")
ErrNotFound = errors.New("record not found")
ErrInvalidFilter = errors.New("invalid filter")
ErrMoreThanOne = errors.New("more than one record")
)
12 changes: 10 additions & 2 deletions internal/sms-gateway/modules/devices/models.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ type DeviceModel struct {
UserID string `gorm:"not null;type:varchar(32)"`

SimCards datatypes.JSONSlice[simCardModel] `gorm:"serializer:json;type:json"`

PublicKey *string `gorm:"type:text"`
KeyVersion *int `gorm:"default:null"`
}

func newDeviceModel(device DeviceInput) *DeviceModel {
Expand All @@ -46,6 +49,9 @@ func newDeviceModel(device DeviceInput) *DeviceModel {
device.SimCards,
func(simCard SimCard, _ int) simCardModel { return newSimCardModel(simCard) },
),

PublicKey: device.PublicKey,
KeyVersion: device.KeyVersion,
}
}

Expand All @@ -62,8 +68,10 @@ func (m *DeviceModel) toDomain() *Device {
DeviceInput: DeviceInput{
DeviceInfo: DeviceInfo{
DeviceUpdate: DeviceUpdate{
PushToken: m.PushToken,
SimCards: lo.Map(m.SimCards, func(m simCardModel, _ int) SimCard { return m.toDomain() }),
PushToken: m.PushToken,
SimCards: lo.Map(m.SimCards, func(m simCardModel, _ int) SimCard { return m.toDomain() }),
PublicKey: m.PublicKey,
KeyVersion: m.KeyVersion,
},

Name: m.Name,
Expand Down
16 changes: 9 additions & 7 deletions internal/sms-gateway/modules/devices/repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,6 @@ import (
"gorm.io/gorm"
)

var (
ErrNotFound = errors.New("record not found")
ErrInvalidFilter = errors.New("invalid filter")
ErrMoreThanOne = errors.New("more than one record")
)

type Repository struct {
db *gorm.DB
}
Expand Down Expand Up @@ -93,7 +87,7 @@ func (r *Repository) Update(ctx context.Context, id string, device DeviceUpdate)
updates := map[string]any{}

if device.PushToken != nil {
updates["push_token"] = device.PushToken
updates["push_token"] = lo.EmptyableToPtr(*device.PushToken)
}

if device.SimCards != nil {
Expand All @@ -103,6 +97,14 @@ func (r *Repository) Update(ctx context.Context, id string, device DeviceUpdate)
))
}

if device.PublicKey != nil {
updates["public_key"] = device.PublicKey
}

if device.KeyVersion != nil {
updates["key_version"] = *device.KeyVersion
}
Comment thread
capcom6 marked this conversation as resolved.
Comment thread
capcom6 marked this conversation as resolved.

if len(updates) == 0 {
return nil
}
Expand Down
2 changes: 1 addition & 1 deletion internal/sms-gateway/modules/push/fcm/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ func (c *Client) Send(ctx context.Context, messages []client.Message) ([]error,
Android: &messaging.AndroidConfig{
Priority: "high",
},
Token: message.Token,
Token: message.Token, //nolint:staticcheck //migration to Fid is planned
})
if err != nil {
errs[i] = fmt.Errorf("failed to send message: %w", err)
Expand Down
13 changes: 12 additions & 1 deletion internal/sms-gateway/openapi/docs.go
Original file line number Diff line number Diff line change
Expand Up @@ -1431,6 +1431,12 @@ const docTemplate = `{
"type": "string",
"example": "PyDmBQZZXYmyxMwED8Fzy"
},
"keyVersion": {
"description": "Key version for rotation tracking",
"type": "integer",
"minimum": 1,
"example": 1
},
"lastSeen": {
"description": "Time at which the device was last seen, read only.",
"type": "string",
Expand All @@ -1441,6 +1447,11 @@ const docTemplate = `{
"type": "string",
"example": "My Device"
},
"publicKey": {
"description": "Base64-encoded RSA public key for E2E encryption (nullable)",
"type": "string",
"example": "MIIBIjANBgkqh..."
},
"simCards": {
"description": "List of SIM cards in the device.",
"type": "array",
Expand Down Expand Up @@ -2210,7 +2221,7 @@ const docTemplate = `{
"phoneNumber": {
"description": "Phone number or first 16 symbols of SHA256 hash",
"type": "string",
"maxLength": 128,
"maxLength": 512,
"minLength": 1,
"example": "79990001234"
},
Expand Down
Loading