Skip to content

Commit 7f0aa10

Browse files
committed
Update user authentication logic
1 parent 48b2f48 commit 7f0aa10

File tree

1 file changed

+123
-73
lines changed

1 file changed

+123
-73
lines changed

httpclient/httpclient_client_configuration.go

Lines changed: 123 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -24,63 +24,127 @@ const (
2424
DefaultTimeout = 10 * time.Second
2525
)
2626

27-
// SetClientConfiguration initializes and configures the HTTP client based on the provided configuration file path and logger.
28-
// It loads configuration values from environment variables and, if necessary, from the provided file path.
29-
// Default values are set for any missing configuration options, and a final check is performed to ensure completeness.
30-
// If any essential configuration values are still missing after setting defaults, it returns an error.
31-
func SetClientConfiguration(configFilePath string) (*ClientConfig, error) {
32-
config := &ClientConfig{}
33-
34-
// Load config values from environment variables
35-
loadConfigFromEnv(config)
36-
37-
// Load config values from file if necessary
38-
if validateConfigCompletion(config) && configFilePath != "" {
39-
log.Printf("Configuration values are incomplete from environment variables, attempting to load from config file: %s", configFilePath)
40-
if err := config.loadConfigFromFile(configFilePath); err != nil {
41-
log.Printf("Failed to load configuration from file: %s, error: %v", configFilePath, err)
42-
return nil, err
27+
// loadConfigFromFile loads configuration values from a JSON file into the ClientConfig struct.
28+
// It opens the specified configuration file, reads its content, and unmarshals the JSON data
29+
// into the ClientConfig struct. This function is crucial for initializing the client configuration
30+
// with values that may not be provided through environment variables or default values.
31+
// It uses Go's standard log package for logging, as the zap logger is not yet initialized when
32+
// this function is called.
33+
func (config *ClientConfig) LoadConfigFromFile(filePath string) error {
34+
// Open the configuration file
35+
file, err := os.Open(filePath)
36+
if err != nil {
37+
log.Printf("Failed to open the configuration file: %s, error: %v", filePath, err)
38+
return err
39+
}
40+
defer file.Close()
41+
42+
reader := bufio.NewReader(file)
43+
var builder strings.Builder
44+
45+
// Read the file content
46+
for {
47+
part, _, err := reader.ReadLine()
48+
if err == io.EOF {
49+
break
4350
}
51+
if err != nil {
52+
log.Printf("Failed to read the configuration file: %s, error: %v", filePath, err)
53+
return err
54+
}
55+
builder.Write(part)
4456
}
4557

58+
// Unmarshal JSON content into the ClientConfig struct
59+
err = json.Unmarshal([]byte(builder.String()), config)
60+
if err != nil {
61+
log.Printf("Failed to unmarshal the configuration file: %s, error: %v", filePath, err)
62+
return err
63+
}
64+
65+
log.Printf("Configuration successfully loaded from file: %s", filePath)
66+
4667
// Set default values if necessary
4768
setLoggerDefaultValues(config)
4869
setClientDefaultValues(config)
4970

50-
// Recheck if config values are still incomplete after setting defaults
51-
if validateConfigCompletion(config) {
52-
return nil, fmt.Errorf("incomplete configuration values even after setting defaults")
71+
// validate configuration
72+
if err := validateMandatoryConfiguration(config); err != nil {
73+
return fmt.Errorf("configuration validation failed: %w", err)
5374
}
5475

55-
return config, nil
76+
return nil
5677
}
5778

58-
// loadConfigFromEnv populates the ClientConfig structure with values from environment variables.
79+
// LoadConfigFromEnv populates the ClientConfig structure with values from environment variables.
5980
// It updates the configuration for authentication, environment specifics, and client options
6081
// based on the presence of environment variables. For each configuration option, if an environment
6182
// variable is set, its value is used; otherwise, the existing value in the ClientConfig structure
62-
// is retained.
63-
func loadConfigFromEnv(config *ClientConfig) {
83+
// is retained. It also sets default values if necessary and validates the final configuration,
84+
// returning an error if the configuration is incomplete.
85+
func LoadConfigFromEnv(config *ClientConfig) (*ClientConfig, error) {
86+
if config == nil {
87+
config = &ClientConfig{} // Initialize config if nil
88+
}
89+
6490
// AuthConfig
6591
config.Auth.ClientID = getEnvOrDefault("CLIENT_ID", config.Auth.ClientID)
92+
log.Printf("ClientID env value found and set to: %s", config.Auth.ClientID)
93+
6694
config.Auth.ClientSecret = getEnvOrDefault("CLIENT_SECRET", config.Auth.ClientSecret)
95+
log.Printf("ClientSecret env value found and set")
6796

6897
// EnvironmentConfig
6998
config.Environment.InstanceName = getEnvOrDefault("INSTANCE_NAME", config.Environment.InstanceName)
99+
log.Printf("InstanceName env value found and set to: %s", config.Environment.InstanceName)
100+
70101
config.Environment.OverrideBaseDomain = getEnvOrDefault("OVERRIDE_BASE_DOMAIN", config.Environment.OverrideBaseDomain)
102+
log.Printf("OverrideBaseDomain env value found and set to: %s", config.Environment.OverrideBaseDomain)
103+
71104
config.Environment.APIType = getEnvOrDefault("API_TYPE", config.Environment.APIType)
105+
log.Printf("APIType env value found and set to: %s", config.Environment.APIType)
72106

73107
// ClientOptions
74108
config.ClientOptions.LogLevel = getEnvOrDefault("LOG_LEVEL", config.ClientOptions.LogLevel)
109+
log.Printf("LogLevel env value found and set to: %s", config.ClientOptions.LogLevel)
110+
75111
config.ClientOptions.LogOutputFormat = getEnvOrDefault("LOG_OUTPUT_FORMAT", config.ClientOptions.LogOutputFormat)
112+
log.Printf("LogOutputFormat env value found and set to: %s", config.ClientOptions.LogOutputFormat)
113+
76114
config.ClientOptions.LogConsoleSeparator = getEnvOrDefault("LOG_CONSOLE_SEPARATOR", config.ClientOptions.LogConsoleSeparator)
115+
log.Printf("LogConsoleSeparator env value found and set to: %s", config.ClientOptions.LogConsoleSeparator)
116+
77117
config.ClientOptions.HideSensitiveData = parseBool(getEnvOrDefault("HIDE_SENSITIVE_DATA", strconv.FormatBool(config.ClientOptions.HideSensitiveData)))
118+
log.Printf("HideSensitiveData env value found and set to: %t", config.ClientOptions.HideSensitiveData)
119+
78120
config.ClientOptions.MaxRetryAttempts = parseInt(getEnvOrDefault("MAX_RETRY_ATTEMPTS", strconv.Itoa(config.ClientOptions.MaxRetryAttempts)), DefaultMaxRetryAttempts)
121+
log.Printf("MaxRetryAttempts env value found and set to: %d", config.ClientOptions.MaxRetryAttempts)
122+
79123
config.ClientOptions.EnableDynamicRateLimiting = parseBool(getEnvOrDefault("ENABLE_DYNAMIC_RATE_LIMITING", strconv.FormatBool(config.ClientOptions.EnableDynamicRateLimiting)))
124+
log.Printf("EnableDynamicRateLimiting env value found and set to: %t", config.ClientOptions.EnableDynamicRateLimiting)
125+
80126
config.ClientOptions.MaxConcurrentRequests = parseInt(getEnvOrDefault("MAX_CONCURRENT_REQUESTS", strconv.Itoa(config.ClientOptions.MaxConcurrentRequests)), DefaultMaxConcurrentRequests)
127+
log.Printf("MaxConcurrentRequests env value found and set to: %d", config.ClientOptions.MaxConcurrentRequests)
128+
81129
config.ClientOptions.TokenRefreshBufferPeriod = parseDuration(getEnvOrDefault("TOKEN_REFRESH_BUFFER_PERIOD", config.ClientOptions.TokenRefreshBufferPeriod.String()), DefaultTokenBufferPeriod)
130+
log.Printf("TokenRefreshBufferPeriod env value found and set to: %s", config.ClientOptions.TokenRefreshBufferPeriod)
131+
82132
config.ClientOptions.TotalRetryDuration = parseDuration(getEnvOrDefault("TOTAL_RETRY_DURATION", config.ClientOptions.TotalRetryDuration.String()), DefaultTotalRetryDuration)
133+
log.Printf("TotalRetryDuration env value found and set to: %s", config.ClientOptions.TotalRetryDuration)
134+
83135
config.ClientOptions.CustomTimeout = parseDuration(getEnvOrDefault("CUSTOM_TIMEOUT", config.ClientOptions.CustomTimeout.String()), DefaultTimeout)
136+
log.Printf("CustomTimeout env value found and set to: %s", config.ClientOptions.CustomTimeout)
137+
138+
// Set default values if necessary
139+
setLoggerDefaultValues(config)
140+
setClientDefaultValues(config)
141+
142+
// Validate final configuration
143+
if err := validateMandatoryConfiguration(config); err != nil {
144+
return nil, err // Return the error if the configuration is incomplete
145+
}
146+
147+
return config, nil
84148
}
85149

86150
// Helper function to get environment variable or default value
@@ -118,14 +182,42 @@ func parseDuration(value string, defaultVal time.Duration) time.Duration {
118182
return result
119183
}
120184

121-
// validateConfigCompletion checks if any essential configuration fields are missing,
122-
// indicating the configuration might be incomplete and may require loading from additional sources.
123-
func validateConfigCompletion(config *ClientConfig) bool {
124-
// Check if essential fields are missing; additional fields can be checked as needed
125-
return config.Auth.ClientID == "" || config.Auth.ClientSecret == "" ||
126-
config.Environment.InstanceName == "" || config.Environment.APIType == "" ||
127-
config.ClientOptions.LogLevel == "" || config.ClientOptions.LogOutputFormat == "" ||
128-
config.ClientOptions.LogConsoleSeparator == ""
185+
// validateMandatoryConfiguration checks if any essential configuration fields are missing,
186+
// and returns an error with details about the missing configurations.
187+
// This ensures the caller can understand what specific configurations need attention.
188+
func validateMandatoryConfiguration(config *ClientConfig) error {
189+
var missingFields []string
190+
191+
// Check for missing mandatory fields and add them to the missingFields slice if necessary.
192+
if config.Auth.ClientID == "" {
193+
missingFields = append(missingFields, "Auth.ClientID")
194+
}
195+
if config.Auth.ClientSecret == "" {
196+
missingFields = append(missingFields, "Auth.ClientSecret")
197+
}
198+
if config.Environment.InstanceName == "" {
199+
missingFields = append(missingFields, "Environment.InstanceName")
200+
}
201+
if config.Environment.APIType == "" {
202+
missingFields = append(missingFields, "Environment.APIType")
203+
}
204+
if config.ClientOptions.LogLevel == "" {
205+
missingFields = append(missingFields, "ClientOptions.LogLevel")
206+
}
207+
if config.ClientOptions.LogOutputFormat == "" {
208+
missingFields = append(missingFields, "ClientOptions.LogOutputFormat")
209+
}
210+
if config.ClientOptions.LogConsoleSeparator == "" {
211+
missingFields = append(missingFields, "ClientOptions.LogConsoleSeparator")
212+
}
213+
214+
// If there are missing fields, return an error detailing what is missing.
215+
if len(missingFields) > 0 {
216+
return fmt.Errorf("mandatory configuration missing: %s", strings.Join(missingFields, ", "))
217+
}
218+
219+
// If no fields are missing, return nil indicating the configuration is complete.
220+
return nil
129221
}
130222

131223
// setClientDefaultValues sets default values for the client configuration options if none are provided.
@@ -186,45 +278,3 @@ func setLoggerDefaultValues(config *ClientConfig) {
186278
// Log completion of setting default values
187279
log.Println("Default values set for logger configuration")
188280
}
189-
190-
// loadConfigFromFile loads configuration values from a JSON file into the ClientConfig struct.
191-
// It opens the specified configuration file, reads its content, and unmarshals the JSON data
192-
// into the ClientConfig struct. This function is crucial for initializing the client configuration
193-
// with values that may not be provided through environment variables or default values.
194-
// It uses Go's standard log package for logging, as the zap logger is not yet initialized when
195-
// this function is called.
196-
func (config *ClientConfig) loadConfigFromFile(filePath string) error {
197-
// Open the configuration file
198-
file, err := os.Open(filePath)
199-
if err != nil {
200-
log.Printf("Failed to open the configuration file: %s, error: %v", filePath, err)
201-
return err
202-
}
203-
defer file.Close()
204-
205-
reader := bufio.NewReader(file)
206-
var builder strings.Builder
207-
208-
// Read the file content
209-
for {
210-
part, _, err := reader.ReadLine()
211-
if err == io.EOF {
212-
break
213-
}
214-
if err != nil {
215-
log.Printf("Failed to read the configuration file: %s, error: %v", filePath, err)
216-
return err
217-
}
218-
builder.Write(part)
219-
}
220-
221-
// Unmarshal JSON content into the ClientConfig struct
222-
err = json.Unmarshal([]byte(builder.String()), config)
223-
if err != nil {
224-
log.Printf("Failed to unmarshal the configuration file: %s, error: %v", filePath, err)
225-
return err
226-
}
227-
228-
log.Printf("Configuration successfully loaded from file: %s", filePath)
229-
return nil
230-
}

0 commit comments

Comments
 (0)