@@ -319,15 +319,19 @@ func readAuthConfig(ctx context.Context, state *SettingsResourceModel, client *a
319319 msg := fmt .Sprintf ("Unable to read auth settings, got status %d: %s" , httpResp .StatusCode (), httpResp .Body )
320320 return diag.Diagnostics {diag .NewErrorDiagnostic ("Client Error" , msg )}
321321 }
322- // API treats sensitive fields as write-only
323- var body LocalAuthConfig
322+ // API treats sensitive fields as write-only, preserve them from state
323+ var stateBody LocalAuthConfig
324324 if ! state .Auth .IsNull () {
325- if diags := state .Auth .Unmarshal (& body ); diags .HasError () {
325+ if diags := state .Auth .Unmarshal (& stateBody ); diags .HasError () {
326326 return diags
327327 }
328328 }
329- body .overrideSensitiveFields (httpResp .JSON200 )
330- if state .Auth , err = parseConfig (state .Auth , * httpResp .JSON200 ); err != nil {
329+ // Convert response to UpdateAuthConfigBody type for consistent marshaling
330+ resultBody := convertAuthResponse (ctx , httpResp .JSON200 )
331+ // Override sensitive fields with values from state
332+ copySensitiveFields (stateBody .UpdateAuthConfigBody , & resultBody )
333+
334+ if state .Auth , err = parseConfig (state .Auth , resultBody ); err != nil {
331335 msg := fmt .Sprintf ("Unable to read auth settings, got error: %s" , err )
332336 return diag.Diagnostics {diag .NewErrorDiagnostic ("Client Error" , msg )}
333337 }
@@ -349,11 +353,12 @@ func updateAuthConfig(ctx context.Context, plan *SettingsResourceModel, client *
349353 msg := fmt .Sprintf ("Unable to update auth settings, got status %d: %s" , httpResp .StatusCode (), httpResp .Body )
350354 return diag.Diagnostics {diag .NewErrorDiagnostic ("Client Error" , msg )}
351355 }
356+ // Convert response to UpdateAuthConfigBody type for consistent marshaling
357+ resultBody := convertAuthResponse (ctx , httpResp .JSON200 )
352358 // Copy over sensitive fields from TF plan
353- local := LocalAuthConfig {UpdateAuthConfigBody : body }
354- local .overrideSensitiveFields (httpResp .JSON200 )
359+ copySensitiveFields (body , & resultBody )
355360
356- if plan .Auth , err = parseConfig (plan .Auth , * httpResp . JSON200 ); err != nil {
361+ if plan .Auth , err = parseConfig (plan .Auth , resultBody ); err != nil {
357362 msg := fmt .Sprintf ("Unable to update auth settings, got error: %s" , err )
358363 return diag.Diagnostics {diag .NewErrorDiagnostic ("Client Error" , msg )}
359364 }
@@ -467,44 +472,69 @@ type LocalAuthConfig struct {
467472 api.UpdateAuthConfigBody
468473}
469474
470- func (c LocalAuthConfig ) overrideSensitiveFields (resp * api.AuthConfigResponse ) {
475+ // convertAuthResponse converts AuthConfigResponse to UpdateAuthConfigBody using JSON marshaling.
476+ // This ensures we use consistent JSON tags (with omitempty) for marshaling.
477+ func convertAuthResponse (ctx context.Context , resp * api.AuthConfigResponse ) api.UpdateAuthConfigBody {
478+ // Marshal the response to JSON and unmarshal into UpdateAuthConfigBody
479+ // This handles field mapping and type conversions automatically
480+ data , err := json .Marshal (resp )
481+ if err != nil {
482+ tflog .Error (ctx , "Failed to marshal auth config response" , map [string ]interface {}{
483+ "error" : err .Error (),
484+ })
485+ return api.UpdateAuthConfigBody {}
486+ }
487+
488+ var body api.UpdateAuthConfigBody
489+ if err := json .Unmarshal (data , & body ); err != nil {
490+ tflog .Error (ctx , "Failed to unmarshal auth config to UpdateAuthConfigBody" , map [string ]interface {}{
491+ "error" : err .Error (),
492+ })
493+ return api.UpdateAuthConfigBody {}
494+ }
495+
496+ return body
497+ }
498+
499+ // copySensitiveFields copies sensitive field values from source to target.
500+ func copySensitiveFields (source api.UpdateAuthConfigBody , target * api.UpdateAuthConfigBody ) {
471501 // Email provider secrets
472- resp .SmtpPass = c .SmtpPass
502+ target .SmtpPass = source .SmtpPass
473503 // SMS provider secrets
474- resp .SmsTwilioAuthToken = c .SmsTwilioAuthToken
475- resp .SmsTwilioVerifyAuthToken = c .SmsTwilioVerifyAuthToken
476- resp .SmsMessagebirdAccessKey = c .SmsMessagebirdAccessKey
477- resp .SmsTextlocalApiKey = c .SmsTextlocalApiKey
478- resp .SmsVonageApiSecret = c .SmsVonageApiSecret
504+ target .SmsTwilioAuthToken = source .SmsTwilioAuthToken
505+ target .SmsTwilioVerifyAuthToken = source .SmsTwilioVerifyAuthToken
506+ target .SmsMessagebirdAccessKey = source .SmsMessagebirdAccessKey
507+ target .SmsTextlocalApiKey = source .SmsTextlocalApiKey
508+ target .SmsVonageApiSecret = source .SmsVonageApiSecret
479509 // Captcha provider secrets
480- resp .SecurityCaptchaSecret = c .SecurityCaptchaSecret
510+ target .SecurityCaptchaSecret = source .SecurityCaptchaSecret
481511 // External provider secrets
482- resp .ExternalAppleSecret = c .ExternalAppleSecret
483- resp .ExternalAzureSecret = c .ExternalAzureSecret
484- resp .ExternalBitbucketSecret = c .ExternalBitbucketSecret
485- resp .ExternalDiscordSecret = c .ExternalDiscordSecret
486- resp .ExternalFacebookSecret = c .ExternalFacebookSecret
487- resp .ExternalFigmaSecret = c .ExternalFigmaSecret
488- resp .ExternalGithubSecret = c .ExternalGithubSecret
489- resp .ExternalGitlabSecret = c .ExternalGitlabSecret
490- resp .ExternalGoogleSecret = c .ExternalGoogleSecret
491- resp .ExternalKakaoSecret = c .ExternalKakaoSecret
492- resp .ExternalKeycloakSecret = c .ExternalKeycloakSecret
493- resp .ExternalLinkedinOidcSecret = c .ExternalLinkedinOidcSecret
494- resp .ExternalNotionSecret = c .ExternalNotionSecret
495- resp .ExternalSlackOidcSecret = c .ExternalSlackOidcSecret
496- resp .ExternalSlackSecret = c .ExternalSlackSecret
497- resp .ExternalSpotifySecret = c .ExternalSpotifySecret
498- resp .ExternalTwitchSecret = c .ExternalTwitchSecret
499- resp .ExternalTwitterSecret = c .ExternalTwitterSecret
500- resp .ExternalWorkosSecret = c .ExternalWorkosSecret
501- resp .ExternalZoomSecret = c .ExternalZoomSecret
512+ target .ExternalAppleSecret = source .ExternalAppleSecret
513+ target .ExternalAzureSecret = source .ExternalAzureSecret
514+ target .ExternalBitbucketSecret = source .ExternalBitbucketSecret
515+ target .ExternalDiscordSecret = source .ExternalDiscordSecret
516+ target .ExternalFacebookSecret = source .ExternalFacebookSecret
517+ target .ExternalFigmaSecret = source .ExternalFigmaSecret
518+ target .ExternalGithubSecret = source .ExternalGithubSecret
519+ target .ExternalGitlabSecret = source .ExternalGitlabSecret
520+ target .ExternalGoogleSecret = source .ExternalGoogleSecret
521+ target .ExternalKakaoSecret = source .ExternalKakaoSecret
522+ target .ExternalKeycloakSecret = source .ExternalKeycloakSecret
523+ target .ExternalLinkedinOidcSecret = source .ExternalLinkedinOidcSecret
524+ target .ExternalNotionSecret = source .ExternalNotionSecret
525+ target .ExternalSlackOidcSecret = source .ExternalSlackOidcSecret
526+ target .ExternalSlackSecret = source .ExternalSlackSecret
527+ target .ExternalSpotifySecret = source .ExternalSpotifySecret
528+ target .ExternalTwitchSecret = source .ExternalTwitchSecret
529+ target .ExternalTwitterSecret = source .ExternalTwitterSecret
530+ target .ExternalWorkosSecret = source .ExternalWorkosSecret
531+ target .ExternalZoomSecret = source .ExternalZoomSecret
502532 // Hook provider secrets
503- resp .HookCustomAccessTokenSecrets = c .HookCustomAccessTokenSecrets
504- resp .HookMfaVerificationAttemptSecrets = c .HookMfaVerificationAttemptSecrets
505- resp .HookPasswordVerificationAttemptSecrets = c .HookPasswordVerificationAttemptSecrets
506- resp .HookSendEmailSecrets = c .HookSendEmailSecrets
507- resp .HookSendSmsSecrets = c .HookSendSmsSecrets
533+ target .HookCustomAccessTokenSecrets = source .HookCustomAccessTokenSecrets
534+ target .HookMfaVerificationAttemptSecrets = source .HookMfaVerificationAttemptSecrets
535+ target .HookPasswordVerificationAttemptSecrets = source .HookPasswordVerificationAttemptSecrets
536+ target .HookSendEmailSecrets = source .HookSendEmailSecrets
537+ target .HookSendSmsSecrets = source .HookSendSmsSecrets
508538}
509539
510540type NetworkConfig struct {
0 commit comments