[feat](alarm): store device ids as sha256 digests
device_id is a stable pseudonymous idempotency key, not a credential; a database dump should not be a usable list of device identifiers. Hash every caller-supplied value before it reaches the table, keep raw values out of logs and subscription views, and migrate existing rows with the identical SQL encoding.
This commit is contained in:
+17
-2
@@ -59,16 +59,31 @@ func scanSubscription(row pgx.Row) (*Subscription, error) {
|
||||
// sequential re-scan path is handled by the caller's lookup and never reaches
|
||||
// this error.
|
||||
func CreateSubscription(ctx context.Context, s *Subscription) (*Subscription, error) {
|
||||
tx, err := Pool().Begin(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer func() { _ = tx.Rollback(ctx) }()
|
||||
|
||||
const q = `INSERT INTO alarm.subscriptions
|
||||
(alert_id, subscriber_user_id, device_id, device_label, platform)
|
||||
VALUES ($1, $2, $3, $4, $5)
|
||||
RETURNING ` + subscriptionColumns
|
||||
row, err := scanSubscription(Pool().QueryRow(ctx, q,
|
||||
row, err := scanSubscription(tx.QueryRow(ctx, q,
|
||||
s.AlertID, s.SubscriberUserID, s.DeviceID, s.DeviceLabel, s.Platform))
|
||||
if isUniqueViolation(err) {
|
||||
return nil, ErrConflict
|
||||
}
|
||||
return row, err
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := recordEvent(ctx, tx, s.AlertID, &s.SubscriberUserID, EventJoined, ""); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := tx.Commit(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return row, nil
|
||||
}
|
||||
|
||||
// GetSubscriptionByDevice is the idempotency lookup for joinAlert.
|
||||
|
||||
Reference in New Issue
Block a user