Files
go-sip/internal/store/mq_scope.go
T

41 lines
1.2 KiB
Go

package store
import (
"database/sql"
"errors"
"fmt"
)
// bindMQScope checks the configured database owner and the immutable tenant
// mapping inside the caller's transaction, before committing any input ACK.
func bindMQScope(tx *sql.Tx, dispatcherID, tenantID, tenantKey string) error {
var owner string
if err := tx.QueryRow(`SELECT dispatcher_id FROM dispatcher_identity WHERE singleton=1`).Scan(&owner); err != nil {
return fmt.Errorf("read MQ owner: %w", err)
}
if owner != dispatcherID {
return ErrMessageScope
}
var conflicting int
if err := tx.QueryRow(`SELECT EXISTS(SELECT 1 FROM inbox WHERE (tenant_id=? AND tenant_key<>?) OR (tenant_key=? AND tenant_id<>?))`, tenantID, tenantKey, tenantKey, tenantID).Scan(&conflicting); err != nil {
return err
}
if conflicting != 0 {
return ErrMessageScope
}
if _, err := tx.Exec(`INSERT INTO tenant_bindings(tenant_id,tenant_key) VALUES(?,?) ON CONFLICT DO NOTHING`, tenantID, tenantKey); err != nil {
return err
}
var key string
if err := tx.QueryRow(`SELECT tenant_key FROM tenant_bindings WHERE tenant_id=?`, tenantID).Scan(&key); err != nil {
if errors.Is(err, sql.ErrNoRows) {
return ErrMessageScope
}
return err
}
if key != tenantKey {
return ErrMessageScope
}
return nil
}