104 lines
3.5 KiB
Go
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{}
|
|
}
|