Files
sxchnge/backend/pkg/db/config.go
T

104 lines
3.5 KiB
Go

package db
import (
"strings"
mongoimpl "git.sendico.io/tech/sxchnge/bff/pkg/db/internal/mongo"
"git.sendico.io/tech/sxchnge/bff/pkg/merrors"
"git.sendico.io/tech/sxchnge/bff/pkg/model"
"github.com/go-viper/mapstructure/v2"
"go.uber.org/zap"
)
type DBDriver string
const (
Mongo DBDriver = "mongodb"
)
type Config = model.DriverConfig[DBDriver]
// PermissionsDatabaseConfig is the explicit public contract for services that
// read authorization metadata from the central permissions database.
type PermissionsDatabaseConfig Config
// AsDatabaseConfig converts the permissions DB contract to the existing DB
// config type without duplicating driver parsing or connection behavior.
func (c *PermissionsDatabaseConfig) AsDatabaseConfig() *Config {
if c == nil {
return nil
}
converted := Config(*c)
return &converted
}
// ResolvedDatabaseName identifies the database selected by a DB config.
type ResolvedDatabaseName struct {
Name string
Source string
}
// ResolveDatabaseName resolves only the database name portion of a DB config.
// It intentionally mirrors the existing env-over-literal behavior and leaves
// low-level connection validation to the normal DB connection path.
func ResolveDatabaseName(config *Config) ResolvedDatabaseName {
if config == nil {
return ResolvedDatabaseName{}
}
return resolveDatabaseName(config)
}
// ResolvePermissionsDatabaseName resolves only the database name portion of a
// permissions DB config.
func ResolvePermissionsDatabaseName(config *PermissionsDatabaseConfig) ResolvedDatabaseName {
return ResolveDatabaseName(config.AsDatabaseConfig())
}
// ValidateSplitDomainPermissionsDatabase verifies the generic split-domain
// invariant for services that must keep authorization metadata separate from
// domain storage.
func ValidateSplitDomainPermissionsDatabase(service string, domain *Config, permissions *PermissionsDatabaseConfig) (ResolvedDatabaseName, ResolvedDatabaseName, error) {
domainName := ResolveDatabaseName(domain)
permissionsName := ResolvePermissionsDatabaseName(permissions)
if permissions == nil {
return domainName, permissionsName, merrors.InvalidArgument(service+" permissions_database configuration is required", "permissions_database")
}
if strings.TrimSpace(domainName.Name) == "" {
return domainName, permissionsName, merrors.InvalidArgument(service+" domain database name is required for split-domain validation", "database")
}
if strings.TrimSpace(permissionsName.Name) == "" {
return domainName, permissionsName, merrors.InvalidArgument(service+" permissions database name is required for split-domain validation", "permissions_database")
}
if domainName.Name == permissionsName.Name {
return domainName, permissionsName, merrors.InvalidArgument(service+" permissions_database must resolve to a different database than the domain database", "permissions_database")
}
return domainName, permissionsName, nil
}
func resolveDatabaseName(config *Config) ResolvedDatabaseName {
if config == nil || config.Driver != Mongo {
return ResolvedDatabaseName{}
}
var mongoConfig mongoimpl.Config
if err := mapstructure.Decode(config.Settings, &mongoConfig); err != nil {
return ResolvedDatabaseName{}
}
dbSettings := mongoimpl.Config2DBSettings(zap.NewNop(), &mongoConfig)
source := ""
if mongoConfig.DatabaseEnv != nil {
source = "env:" + *mongoConfig.DatabaseEnv
} else if mongoConfig.Database != nil {
source = "settings.database"
}
if source != "" {
return ResolvedDatabaseName{
Name: dbSettings.Database,
Source: source,
}
}
return ResolvedDatabaseName{}
}