@@ -312,15 +312,19 @@ func readAuthConfig(ctx context.Context, state *SettingsResourceModel, client *a
312312 msg := fmt .Sprintf ("Unable to read auth settings, got status %d: %s" , httpResp .StatusCode (), httpResp .Body )
313313 return diag.Diagnostics {diag .NewErrorDiagnostic ("Client Error" , msg )}
314314 }
315- // API treats sensitive fields as write-only
316- var body LocalAuthConfig
315+ // API treats sensitive fields as write-only, preserve them from state
316+ var stateBody LocalAuthConfig
317317 if ! state .Auth .IsNull () {
318- if diags := state .Auth .Unmarshal (& body ); diags .HasError () {
318+ if diags := state .Auth .Unmarshal (& stateBody ); diags .HasError () {
319319 return diags
320320 }
321321 }
322- body .overrideSensitiveFields (httpResp .JSON200 )
323- if state .Auth , err = parseConfig (state .Auth , * httpResp .JSON200 ); err != nil {
322+ // Convert response to UpdateAuthConfigBody type for consistent marshaling
323+ resultBody := convertAuthResponse (ctx , httpResp .JSON200 )
324+ // Override sensitive fields with values from state
325+ copySensitiveFields (stateBody .UpdateAuthConfigBody , & resultBody )
326+
327+ if state .Auth , err = parseConfig (state .Auth , resultBody ); err != nil {
324328 msg := fmt .Sprintf ("Unable to read auth settings, got error: %s" , err )
325329 return diag.Diagnostics {diag .NewErrorDiagnostic ("Client Error" , msg )}
326330 }
@@ -342,11 +346,12 @@ func updateAuthConfig(ctx context.Context, plan *SettingsResourceModel, client *
342346 msg := fmt .Sprintf ("Unable to update auth settings, got status %d: %s" , httpResp .StatusCode (), httpResp .Body )
343347 return diag.Diagnostics {diag .NewErrorDiagnostic ("Client Error" , msg )}
344348 }
349+ // Convert response to UpdateAuthConfigBody type for consistent marshaling
350+ resultBody := convertAuthResponse (ctx , httpResp .JSON200 )
345351 // Copy over sensitive fields from TF plan
346- local := LocalAuthConfig {UpdateAuthConfigBody : body }
347- local .overrideSensitiveFields (httpResp .JSON200 )
352+ copySensitiveFields (body , & resultBody )
348353
349- if plan .Auth , err = parseConfig (plan .Auth , * httpResp . JSON200 ); err != nil {
354+ if plan .Auth , err = parseConfig (plan .Auth , resultBody ); err != nil {
350355 msg := fmt .Sprintf ("Unable to update auth settings, got error: %s" , err )
351356 return diag.Diagnostics {diag .NewErrorDiagnostic ("Client Error" , msg )}
352357 }
@@ -460,44 +465,69 @@ type LocalAuthConfig struct {
460465 api.UpdateAuthConfigBody
461466}
462467
463- func (c LocalAuthConfig ) overrideSensitiveFields (resp * api.AuthConfigResponse ) {
468+ // convertAuthResponse converts AuthConfigResponse to UpdateAuthConfigBody using JSON marshaling.
469+ // This ensures we use consistent JSON tags (with omitempty) for marshaling.
470+ func convertAuthResponse (ctx context.Context , resp * api.AuthConfigResponse ) api.UpdateAuthConfigBody {
471+ // Marshal the response to JSON and unmarshal into UpdateAuthConfigBody
472+ // This handles field mapping and type conversions automatically
473+ data , err := json .Marshal (resp )
474+ if err != nil {
475+ tflog .Error (ctx , "Failed to marshal auth config response" , map [string ]interface {}{
476+ "error" : err .Error (),
477+ })
478+ return api.UpdateAuthConfigBody {}
479+ }
480+
481+ var body api.UpdateAuthConfigBody
482+ if err := json .Unmarshal (data , & body ); err != nil {
483+ tflog .Error (ctx , "Failed to unmarshal auth config to UpdateAuthConfigBody" , map [string ]interface {}{
484+ "error" : err .Error (),
485+ })
486+ return api.UpdateAuthConfigBody {}
487+ }
488+
489+ return body
490+ }
491+
492+ // copySensitiveFields copies sensitive field values from source to target.
493+ func copySensitiveFields (source api.UpdateAuthConfigBody , target * api.UpdateAuthConfigBody ) {
464494 // Email provider secrets
465- resp .SmtpPass = c .SmtpPass
495+ target .SmtpPass = source .SmtpPass
466496 // SMS provider secrets
467- resp .SmsTwilioAuthToken = c .SmsTwilioAuthToken
468- resp .SmsTwilioVerifyAuthToken = c .SmsTwilioVerifyAuthToken
469- resp .SmsMessagebirdAccessKey = c .SmsMessagebirdAccessKey
470- resp .SmsTextlocalApiKey = c .SmsTextlocalApiKey
471- resp .SmsVonageApiSecret = c .SmsVonageApiSecret
497+ target .SmsTwilioAuthToken = source .SmsTwilioAuthToken
498+ target .SmsTwilioVerifyAuthToken = source .SmsTwilioVerifyAuthToken
499+ target .SmsMessagebirdAccessKey = source .SmsMessagebirdAccessKey
500+ target .SmsTextlocalApiKey = source .SmsTextlocalApiKey
501+ target .SmsVonageApiSecret = source .SmsVonageApiSecret
472502 // Captcha provider secrets
473- resp .SecurityCaptchaSecret = c .SecurityCaptchaSecret
503+ target .SecurityCaptchaSecret = source .SecurityCaptchaSecret
474504 // External provider secrets
475- resp .ExternalAppleSecret = c .ExternalAppleSecret
476- resp .ExternalAzureSecret = c .ExternalAzureSecret
477- resp .ExternalBitbucketSecret = c .ExternalBitbucketSecret
478- resp .ExternalDiscordSecret = c .ExternalDiscordSecret
479- resp .ExternalFacebookSecret = c .ExternalFacebookSecret
480- resp .ExternalFigmaSecret = c .ExternalFigmaSecret
481- resp .ExternalGithubSecret = c .ExternalGithubSecret
482- resp .ExternalGitlabSecret = c .ExternalGitlabSecret
483- resp .ExternalGoogleSecret = c .ExternalGoogleSecret
484- resp .ExternalKakaoSecret = c .ExternalKakaoSecret
485- resp .ExternalKeycloakSecret = c .ExternalKeycloakSecret
486- resp .ExternalLinkedinOidcSecret = c .ExternalLinkedinOidcSecret
487- resp .ExternalNotionSecret = c .ExternalNotionSecret
488- resp .ExternalSlackOidcSecret = c .ExternalSlackOidcSecret
489- resp .ExternalSlackSecret = c .ExternalSlackSecret
490- resp .ExternalSpotifySecret = c .ExternalSpotifySecret
491- resp .ExternalTwitchSecret = c .ExternalTwitchSecret
492- resp .ExternalTwitterSecret = c .ExternalTwitterSecret
493- resp .ExternalWorkosSecret = c .ExternalWorkosSecret
494- resp .ExternalZoomSecret = c .ExternalZoomSecret
505+ target .ExternalAppleSecret = source .ExternalAppleSecret
506+ target .ExternalAzureSecret = source .ExternalAzureSecret
507+ target .ExternalBitbucketSecret = source .ExternalBitbucketSecret
508+ target .ExternalDiscordSecret = source .ExternalDiscordSecret
509+ target .ExternalFacebookSecret = source .ExternalFacebookSecret
510+ target .ExternalFigmaSecret = source .ExternalFigmaSecret
511+ target .ExternalGithubSecret = source .ExternalGithubSecret
512+ target .ExternalGitlabSecret = source .ExternalGitlabSecret
513+ target .ExternalGoogleSecret = source .ExternalGoogleSecret
514+ target .ExternalKakaoSecret = source .ExternalKakaoSecret
515+ target .ExternalKeycloakSecret = source .ExternalKeycloakSecret
516+ target .ExternalLinkedinOidcSecret = source .ExternalLinkedinOidcSecret
517+ target .ExternalNotionSecret = source .ExternalNotionSecret
518+ target .ExternalSlackOidcSecret = source .ExternalSlackOidcSecret
519+ target .ExternalSlackSecret = source .ExternalSlackSecret
520+ target .ExternalSpotifySecret = source .ExternalSpotifySecret
521+ target .ExternalTwitchSecret = source .ExternalTwitchSecret
522+ target .ExternalTwitterSecret = source .ExternalTwitterSecret
523+ target .ExternalWorkosSecret = source .ExternalWorkosSecret
524+ target .ExternalZoomSecret = source .ExternalZoomSecret
495525 // Hook provider secrets
496- resp .HookCustomAccessTokenSecrets = c .HookCustomAccessTokenSecrets
497- resp .HookMfaVerificationAttemptSecrets = c .HookMfaVerificationAttemptSecrets
498- resp .HookPasswordVerificationAttemptSecrets = c .HookPasswordVerificationAttemptSecrets
499- resp .HookSendEmailSecrets = c .HookSendEmailSecrets
500- resp .HookSendSmsSecrets = c .HookSendSmsSecrets
526+ target .HookCustomAccessTokenSecrets = source .HookCustomAccessTokenSecrets
527+ target .HookMfaVerificationAttemptSecrets = source .HookMfaVerificationAttemptSecrets
528+ target .HookPasswordVerificationAttemptSecrets = source .HookPasswordVerificationAttemptSecrets
529+ target .HookSendEmailSecrets = source .HookSendEmailSecrets
530+ target .HookSendSmsSecrets = source .HookSendSmsSecrets
501531}
502532
503533type NetworkConfig struct {
0 commit comments