mirror of
https://github.com/warmbly/warmbly.git
synced 2026-08-19 00:01:14 +00:00
c800081987
Mailboxes, integration tokens, and message content are organization assets. Keying their DEK by the connecting user meant offboarding that user made every ciphertext they created unreadable. Migration 000039 drops user_encrypted_keys and creates organization_encrypted_keys keyed by organization_id. The new table has no FK on purpose: platform secrets live under the zero UUID (no organizations row), and DEK rows must never cascade-delete because a lost DEK is unrecoverable. Pre-production, so there is no data migration; ciphertexts sealed under the old per-user DEKs are abandoned with the table.
64 lines
1.7 KiB
Go
64 lines
1.7 KiB
Go
package encryptedkeys
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
|
|
"github.com/google/uuid"
|
|
"github.com/jackc/pgx/v5"
|
|
"github.com/jackc/pgx/v5/pgconn"
|
|
"github.com/warmbly/warmbly/internal/infrastructure/db"
|
|
)
|
|
|
|
// PostgresStore stores encrypted DEKs in the organization_encrypted_keys
|
|
// table. Only the backend uses this impl directly; workers reach DEKs via the
|
|
// HTTP store (which proxies through the backend).
|
|
type PostgresStore struct {
|
|
db *db.DB
|
|
}
|
|
|
|
func NewPostgres(d *db.DB) *PostgresStore {
|
|
return &PostgresStore{db: d}
|
|
}
|
|
|
|
func (s *PostgresStore) Name() string { return "postgres" }
|
|
|
|
func (s *PostgresStore) Put(ctx context.Context, orgID uuid.UUID, encryptedDEKB64 string) error {
|
|
const q = `
|
|
INSERT INTO organization_encrypted_keys (organization_id, encrypted_data_key)
|
|
VALUES ($1, $2)
|
|
`
|
|
_, err := s.db.Exec(ctx, q, orgID, encryptedDEKB64)
|
|
if err != nil {
|
|
var pgErr *pgconn.PgError
|
|
if errors.As(err, &pgErr) && pgErr.Code == "23505" { // unique_violation
|
|
return ErrAlreadyExists
|
|
}
|
|
return fmt.Errorf("encryptedkeys.postgres: put: %w", err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (s *PostgresStore) Get(ctx context.Context, orgID uuid.UUID) (string, error) {
|
|
const q = `SELECT encrypted_data_key FROM organization_encrypted_keys WHERE organization_id = $1`
|
|
var out string
|
|
err := s.db.QueryRow(ctx, q, orgID).Scan(&out)
|
|
if err != nil {
|
|
if errors.Is(err, pgx.ErrNoRows) {
|
|
return "", nil
|
|
}
|
|
return "", fmt.Errorf("encryptedkeys.postgres: get: %w", err)
|
|
}
|
|
return out, nil
|
|
}
|
|
|
|
func (s *PostgresStore) Delete(ctx context.Context, orgID uuid.UUID) error {
|
|
const q = `DELETE FROM organization_encrypted_keys WHERE organization_id = $1`
|
|
_, err := s.db.Exec(ctx, q, orgID)
|
|
if err != nil {
|
|
return fmt.Errorf("encryptedkeys.postgres: delete: %w", err)
|
|
}
|
|
return nil
|
|
}
|