package revaconfig import ( "bufio" "fmt" "os" "path/filepath" "github.com/qsfera/server/pkg/config/defaults" "github.com/qsfera/server/pkg/generators" "github.com/qsfera/server/pkg/log" "github.com/qsfera/server/services/sharing/pkg/config" ) // SharingConfigFromStruct will adapt a КуСфера config struct into a reva mapstructure to start a reva service. func SharingConfigFromStruct(cfg *config.Config, logger log.Logger) (map[string]any, error) { passwordPolicyCfg, err := passwordPolicyConfig(cfg) if err != nil { logger.Err(err).Send() return nil, err } rcfg := map[string]any{ "shared": map[string]any{ "jwt_secret": cfg.TokenManager.JWTSecret, "gatewaysvc": cfg.Reva.Address, "skip_user_groups_in_token": cfg.SkipUserGroupsInToken, "grpc_client_options": cfg.Reva.GetGRPCClientConfig(), "multi_tenant_enabled": cfg.Commons.MultiTenantEnabled, }, "grpc": map[string]any{ "network": cfg.GRPC.Protocol, "address": cfg.GRPC.Addr, "tls_settings": map[string]any{ "enabled": cfg.GRPC.TLS.Enabled, "certificate": cfg.GRPC.TLS.Cert, "key": cfg.GRPC.TLS.Key, }, // TODO build services dynamically "services": map[string]any{ "usershareprovider": map[string]any{ "driver": cfg.UserSharingDriver, "drivers": map[string]any{ "json": map[string]any{ "file": cfg.UserSharingDrivers.JSON.File, "gateway_addr": cfg.Reva.Address, }, "sql": map[string]any{ // cernbox sql "db_username": cfg.UserSharingDrivers.SQL.DBUsername, "db_password": cfg.UserSharingDrivers.SQL.DBPassword, "db_host": cfg.UserSharingDrivers.SQL.DBHost, "db_port": cfg.UserSharingDrivers.SQL.DBPort, "db_name": cfg.UserSharingDrivers.SQL.DBName, "password_hash_cost": cfg.UserSharingDrivers.SQL.PasswordHashCost, "enable_expired_shares_cleanup": cfg.UserSharingDrivers.SQL.EnableExpiredSharesCleanup, "janitor_run_interval": cfg.UserSharingDrivers.SQL.JanitorRunInterval, }, "owncloudsql": map[string]any{ "gateway_addr": cfg.Reva.Address, "storage_mount_id": cfg.UserSharingDrivers.OwnCloudSQL.UserStorageMountID, "db_username": cfg.UserSharingDrivers.OwnCloudSQL.DBUsername, "db_password": cfg.UserSharingDrivers.OwnCloudSQL.DBPassword, "db_host": cfg.UserSharingDrivers.OwnCloudSQL.DBHost, "db_port": cfg.UserSharingDrivers.OwnCloudSQL.DBPort, "db_name": cfg.UserSharingDrivers.OwnCloudSQL.DBName, }, "cs3": map[string]any{ "gateway_addr": cfg.UserSharingDrivers.CS3.ProviderAddr, "provider_addr": cfg.UserSharingDrivers.CS3.ProviderAddr, "service_user_id": cfg.UserSharingDrivers.CS3.SystemUserID, "service_user_idp": cfg.UserSharingDrivers.CS3.SystemUserIDP, "machine_auth_apikey": cfg.UserSharingDrivers.CS3.SystemUserAPIKey, }, "jsoncs3": map[string]any{ "gateway_addr": cfg.Reva.Address, "provider_addr": cfg.UserSharingDrivers.JSONCS3.ProviderAddr, "system_user_id": cfg.UserSharingDrivers.JSONCS3.SystemUserID, "system_user_idp": cfg.UserSharingDrivers.JSONCS3.SystemUserIDP, "machine_auth_apikey": cfg.UserSharingDrivers.JSONCS3.SystemUserAPIKey, "ttl": cfg.UserSharingDrivers.JSONCS3.CacheTTL, "max_concurrency": cfg.UserSharingDrivers.JSONCS3.MaxConcurrency, "service_account_id": cfg.ServiceAccount.ServiceAccountID, "service_account_secret": cfg.ServiceAccount.ServiceAccountSecret, "events": map[string]any{ "natsaddress": cfg.Events.Addr, "natsclusterid": cfg.Events.ClusterID, "tlsinsecure": cfg.Events.TLSInsecure, "tlsrootcacertificate": cfg.Events.TLSRootCaCertPath, "authusername": cfg.Events.AuthUsername, "authpassword": cfg.Events.AuthPassword, }, }, }, }, "publicshareprovider": map[string]any{ "gateway_addr": cfg.Reva.Address, "writeable_share_must_have_password": cfg.WriteableShareMustHavePassword, "public_share_must_have_password": cfg.PublicShareMustHavePassword, "password_policy": passwordPolicyCfg, "driver": cfg.PublicSharingDriver, "drivers": map[string]any{ "json": map[string]any{ "file": cfg.PublicSharingDrivers.JSON.File, "gateway_addr": cfg.Reva.Address, }, "sql": map[string]any{ "db_username": cfg.PublicSharingDrivers.SQL.DBUsername, "db_password": cfg.PublicSharingDrivers.SQL.DBPassword, "db_host": cfg.PublicSharingDrivers.SQL.DBHost, "db_port": cfg.PublicSharingDrivers.SQL.DBPort, "db_name": cfg.PublicSharingDrivers.SQL.DBName, "password_hash_cost": cfg.PublicSharingDrivers.SQL.PasswordHashCost, "enable_expired_shares_cleanup": cfg.PublicSharingDrivers.SQL.EnableExpiredSharesCleanup, "janitor_run_interval": cfg.PublicSharingDrivers.SQL.JanitorRunInterval, }, "cs3": map[string]any{ "gateway_addr": cfg.PublicSharingDrivers.CS3.ProviderAddr, "provider_addr": cfg.PublicSharingDrivers.CS3.ProviderAddr, "service_user_id": cfg.PublicSharingDrivers.CS3.SystemUserID, "service_user_idp": cfg.PublicSharingDrivers.CS3.SystemUserIDP, "machine_auth_apikey": cfg.PublicSharingDrivers.CS3.SystemUserAPIKey, }, "jsoncs3": map[string]any{ "gateway_addr": cfg.Reva.Address, "provider_addr": cfg.PublicSharingDrivers.JSONCS3.ProviderAddr, "service_user_id": cfg.PublicSharingDrivers.JSONCS3.SystemUserID, "service_user_idp": cfg.PublicSharingDrivers.JSONCS3.SystemUserIDP, "machine_auth_apikey": cfg.PublicSharingDrivers.JSONCS3.SystemUserAPIKey, "enable_expired_shares_cleanup": cfg.EnableExpiredSharesCleanup, }, }, }, }, "interceptors": map[string]any{ "eventsmiddleware": map[string]any{ "group": "sharing", "type": "nats", "address": cfg.Events.Addr, "clusterID": cfg.Events.ClusterID, "tls-insecure": cfg.Events.TLSInsecure, "tls-root-ca-cert": cfg.Events.TLSRootCaCertPath, "enable-tls": cfg.Events.EnableTLS, "name": generators.GenerateConnectionName(cfg.Service.Name, generators.NTypeBus), "username": cfg.Events.AuthUsername, "password": cfg.Events.AuthPassword, }, "prometheus": map[string]any{ "namespace": "qsfera", "subsystem": "sharing", }, }, }, } return rcfg, nil } func readMultilineFile(path string) (map[string]struct{}, error) { if !fileExists(path) { path = filepath.Join(defaults.BaseConfigPath(), path) } file, err := os.Open(path) if err != nil { return nil, err } defer file.Close() scanner := bufio.NewScanner(file) data := make(map[string]struct{}) for scanner.Scan() { line := scanner.Text() if line != "" { data[line] = struct{}{} } } return data, err } func fileExists(path string) bool { info, err := os.Stat(path) if err != nil { return false } return !info.IsDir() } func passwordPolicyConfig(cfg *config.Config) (map[string]any, error) { _maxCharacters := 72 if cfg.PasswordPolicy.Disabled { return map[string]any{ "max_characters": _maxCharacters, "banned_passwords_list": nil, }, nil } var bannedPasswordsList map[string]struct{} var err error if cfg.PasswordPolicy.BannedPasswordsList != "" { bannedPasswordsList, err = readMultilineFile(cfg.PasswordPolicy.BannedPasswordsList) if err != nil { return nil, fmt.Errorf("failed to load the banned passwords from a file %s: %w", cfg.PasswordPolicy.BannedPasswordsList, err) } } return map[string]any{ "max_characters": _maxCharacters, "min_digits": cfg.PasswordPolicy.MinDigits, "min_characters": cfg.PasswordPolicy.MinCharacters, "min_lowercase_characters": cfg.PasswordPolicy.MinLowerCaseCharacters, "min_uppercase_characters": cfg.PasswordPolicy.MinUpperCaseCharacters, "min_special_characters": cfg.PasswordPolicy.MinSpecialCharacters, "banned_passwords_list": bannedPasswordsList, }, nil }