• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

supabase / cli / 12715729910

10 Jan 2025 07:10PM UTC coverage: 58.508% (-0.02%) from 58.531%
12715729910

Pull #3029

github

web-flow
Merge 9cb374f78 into 88cd60986
Pull Request #3029: fix: skip hashing unloaded env reference

8 of 38 new or added lines in 3 files covered. (21.05%)

5 existing lines in 1 file now uncovered.

7585 of 12964 relevant lines covered (58.51%)

202.72 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

58.85
/pkg/config/auth.go
1
package config
2

3
import (
4
        "strconv"
5
        "strings"
6
        "time"
7

8
        v1API "github.com/supabase/cli/pkg/api"
9
        "github.com/supabase/cli/pkg/cast"
10
        "github.com/supabase/cli/pkg/diff"
11
)
12

13
type PasswordRequirements string
14

15
const (
16
        NoRequirements                 PasswordRequirements = ""
17
        LettersDigits                  PasswordRequirements = "letters_digits"
18
        LowerUpperLettersDigits        PasswordRequirements = "lower_upper_letters_digits"
19
        LowerUpperLettersDigitsSymbols PasswordRequirements = "lower_upper_letters_digits_symbols"
20
)
21

22
func (r PasswordRequirements) ToChar() v1API.UpdateAuthConfigBodyPasswordRequiredCharacters {
2✔
23
        switch r {
2✔
24
        case LettersDigits:
×
25
                return v1API.AbcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789
×
26
        case LowerUpperLettersDigits:
×
27
                return v1API.AbcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567891
×
28
        case LowerUpperLettersDigitsSymbols:
×
29
                return v1API.AbcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567892
×
30
        }
31
        return v1API.Empty
2✔
32
}
33

34
func NewPasswordRequirement(c v1API.UpdateAuthConfigBodyPasswordRequiredCharacters) PasswordRequirements {
26✔
35
        switch c {
26✔
36
        case v1API.AbcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789:
2✔
37
                return LettersDigits
2✔
38
        case v1API.AbcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567891:
×
39
                return LowerUpperLettersDigits
×
40
        case v1API.AbcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567892:
×
41
                return LowerUpperLettersDigitsSymbols
×
42
        }
43
        return NoRequirements
24✔
44
}
45

46
type (
47
        auth struct {
48
                Enabled bool   `toml:"enabled"`
49
                Image   string `toml:"-"`
50

51
                SiteUrl                    string               `toml:"site_url" mapstructure:"site_url"`
52
                AdditionalRedirectUrls     []string             `toml:"additional_redirect_urls"`
53
                JwtExpiry                  uint                 `toml:"jwt_expiry"`
54
                EnableRefreshTokenRotation bool                 `toml:"enable_refresh_token_rotation"`
55
                RefreshTokenReuseInterval  uint                 `toml:"refresh_token_reuse_interval"`
56
                EnableManualLinking        bool                 `toml:"enable_manual_linking"`
57
                EnableSignup               bool                 `toml:"enable_signup"`
58
                EnableAnonymousSignIns     bool                 `toml:"enable_anonymous_sign_ins"`
59
                MinimumPasswordLength      uint                 `toml:"minimum_password_length"`
60
                PasswordRequirements       PasswordRequirements `toml:"password_requirements"`
61

62
                Hook     hook     `toml:"hook"`
63
                MFA      mfa      `toml:"mfa"`
64
                Sessions sessions `toml:"sessions"`
65
                Email    email    `toml:"email"`
66
                Sms      sms      `toml:"sms"`
67
                External external `toml:"external"`
68

69
                // Custom secrets can be injected from .env file
70
                JwtSecret      string `toml:"-" mapstructure:"jwt_secret"`
71
                AnonKey        string `toml:"-" mapstructure:"anon_key"`
72
                ServiceRoleKey string `toml:"-" mapstructure:"service_role_key"`
73

74
                ThirdParty thirdParty `toml:"third_party"`
75
        }
76

77
        external map[string]provider
78

79
        thirdParty struct {
80
                Firebase tpaFirebase `toml:"firebase"`
81
                Auth0    tpaAuth0    `toml:"auth0"`
82
                Cognito  tpaCognito  `toml:"aws_cognito"`
83
        }
84

85
        tpaFirebase struct {
86
                Enabled bool `toml:"enabled"`
87

88
                ProjectID string `toml:"project_id"`
89
        }
90

91
        tpaAuth0 struct {
92
                Enabled bool `toml:"enabled"`
93

94
                Tenant       string `toml:"tenant"`
95
                TenantRegion string `toml:"tenant_region"`
96
        }
97

98
        tpaCognito struct {
99
                Enabled bool `toml:"enabled"`
100

101
                UserPoolID     string `toml:"user_pool_id"`
102
                UserPoolRegion string `toml:"user_pool_region"`
103
        }
104

105
        email struct {
106
                EnableSignup         bool                     `toml:"enable_signup"`
107
                DoubleConfirmChanges bool                     `toml:"double_confirm_changes"`
108
                EnableConfirmations  bool                     `toml:"enable_confirmations"`
109
                SecurePasswordChange bool                     `toml:"secure_password_change"`
110
                Template             map[string]emailTemplate `toml:"template"`
111
                Smtp                 *smtp                    `toml:"smtp"`
112
                MaxFrequency         time.Duration            `toml:"max_frequency"`
113
                OtpLength            uint                     `toml:"otp_length"`
114
                OtpExpiry            uint                     `toml:"otp_expiry"`
115
        }
116

117
        smtp struct {
118
                Enabled    *bool  `toml:"enabled"`
119
                Host       string `toml:"host"`
120
                Port       uint16 `toml:"port"`
121
                User       string `toml:"user"`
122
                Pass       Secret `toml:"pass"`
123
                AdminEmail string `toml:"admin_email"`
124
                SenderName string `toml:"sender_name"`
125
        }
126

127
        emailTemplate struct {
128
                Subject *string `toml:"subject"`
129
                Content *string `toml:"content"`
130
                // Only content path is accepted in config.toml
131
                ContentPath string `toml:"content_path"`
132
        }
133

134
        sms struct {
135
                EnableSignup        bool              `toml:"enable_signup"`
136
                EnableConfirmations bool              `toml:"enable_confirmations"`
137
                Template            string            `toml:"template"`
138
                Twilio              twilioConfig      `toml:"twilio" mapstructure:"twilio"`
139
                TwilioVerify        twilioConfig      `toml:"twilio_verify" mapstructure:"twilio_verify"`
140
                Messagebird         messagebirdConfig `toml:"messagebird" mapstructure:"messagebird"`
141
                Textlocal           textlocalConfig   `toml:"textlocal" mapstructure:"textlocal"`
142
                Vonage              vonageConfig      `toml:"vonage" mapstructure:"vonage"`
143
                TestOTP             map[string]string `toml:"test_otp"`
144
                MaxFrequency        time.Duration     `toml:"max_frequency"`
145
        }
146

147
        hook struct {
148
                MFAVerificationAttempt      *hookConfig `toml:"mfa_verification_attempt"`
149
                PasswordVerificationAttempt *hookConfig `toml:"password_verification_attempt"`
150
                CustomAccessToken           *hookConfig `toml:"custom_access_token"`
151
                SendSMS                     *hookConfig `toml:"send_sms"`
152
                SendEmail                   *hookConfig `toml:"send_email"`
153
        }
154

155
        factorTypeConfiguration struct {
156
                EnrollEnabled bool `toml:"enroll_enabled"`
157
                VerifyEnabled bool `toml:"verify_enabled"`
158
        }
159

160
        phoneFactorTypeConfiguration struct {
161
                factorTypeConfiguration
162
                OtpLength    uint          `toml:"otp_length"`
163
                Template     string        `toml:"template"`
164
                MaxFrequency time.Duration `toml:"max_frequency"`
165
        }
166

167
        mfa struct {
168
                TOTP               factorTypeConfiguration      `toml:"totp"`
169
                Phone              phoneFactorTypeConfiguration `toml:"phone"`
170
                WebAuthn           factorTypeConfiguration      `toml:"web_authn"`
171
                MaxEnrolledFactors uint                         `toml:"max_enrolled_factors"`
172
        }
173

174
        hookConfig struct {
175
                Enabled bool   `toml:"enabled"`
176
                URI     string `toml:"uri"`
177
                Secrets Secret `toml:"secrets"`
178
        }
179

180
        sessions struct {
181
                Timebox           time.Duration `toml:"timebox"`
182
                InactivityTimeout time.Duration `toml:"inactivity_timeout"`
183
        }
184

185
        twilioConfig struct {
186
                Enabled           bool   `toml:"enabled"`
187
                AccountSid        string `toml:"account_sid"`
188
                MessageServiceSid string `toml:"message_service_sid"`
189
                AuthToken         Secret `toml:"auth_token" mapstructure:"auth_token"`
190
        }
191

192
        messagebirdConfig struct {
193
                Enabled    bool   `toml:"enabled"`
194
                Originator string `toml:"originator"`
195
                AccessKey  Secret `toml:"access_key" mapstructure:"access_key"`
196
        }
197

198
        textlocalConfig struct {
199
                Enabled bool   `toml:"enabled"`
200
                Sender  string `toml:"sender"`
201
                ApiKey  Secret `toml:"api_key" mapstructure:"api_key"`
202
        }
203

204
        vonageConfig struct {
205
                Enabled   bool   `toml:"enabled"`
206
                From      string `toml:"from"`
207
                ApiKey    string `toml:"api_key" mapstructure:"api_key"`
208
                ApiSecret Secret `toml:"api_secret" mapstructure:"api_secret"`
209
        }
210

211
        provider struct {
212
                Enabled        bool   `toml:"enabled"`
213
                ClientId       string `toml:"client_id"`
214
                Secret         Secret `toml:"secret"`
215
                Url            string `toml:"url"`
216
                RedirectUri    string `toml:"redirect_uri"`
217
                SkipNonceCheck bool   `toml:"skip_nonce_check"`
218
        }
219
)
220

221
func (a *auth) ToUpdateAuthConfigBody() v1API.UpdateAuthConfigBody {
2✔
222
        body := v1API.UpdateAuthConfigBody{
2✔
223
                SiteUrl:                           &a.SiteUrl,
2✔
224
                UriAllowList:                      cast.Ptr(strings.Join(a.AdditionalRedirectUrls, ",")),
2✔
225
                JwtExp:                            cast.UintToIntPtr(&a.JwtExpiry),
2✔
226
                RefreshTokenRotationEnabled:       &a.EnableRefreshTokenRotation,
2✔
227
                SecurityRefreshTokenReuseInterval: cast.UintToIntPtr(&a.RefreshTokenReuseInterval),
2✔
228
                SecurityManualLinkingEnabled:      &a.EnableManualLinking,
2✔
229
                DisableSignup:                     cast.Ptr(!a.EnableSignup),
2✔
230
                ExternalAnonymousUsersEnabled:     &a.EnableAnonymousSignIns,
2✔
231
                PasswordMinLength:                 cast.UintToIntPtr(&a.MinimumPasswordLength),
2✔
232
                PasswordRequiredCharacters:        cast.Ptr(a.PasswordRequirements.ToChar()),
2✔
233
        }
2✔
234
        a.Hook.toAuthConfigBody(&body)
2✔
235
        a.MFA.toAuthConfigBody(&body)
2✔
236
        a.Sessions.toAuthConfigBody(&body)
2✔
237
        a.Email.toAuthConfigBody(&body)
2✔
238
        a.Sms.toAuthConfigBody(&body)
2✔
239
        a.External.toAuthConfigBody(&body)
2✔
240
        return body
2✔
241
}
2✔
242

243
func (a *auth) FromRemoteAuthConfig(remoteConfig v1API.AuthConfigResponse) {
26✔
244
        a.SiteUrl = cast.Val(remoteConfig.SiteUrl, "")
26✔
245
        a.AdditionalRedirectUrls = strToArr(cast.Val(remoteConfig.UriAllowList, ""))
26✔
246
        a.JwtExpiry = cast.IntToUint(cast.Val(remoteConfig.JwtExp, 0))
26✔
247
        a.EnableRefreshTokenRotation = cast.Val(remoteConfig.RefreshTokenRotationEnabled, false)
26✔
248
        a.RefreshTokenReuseInterval = cast.IntToUint(cast.Val(remoteConfig.SecurityRefreshTokenReuseInterval, 0))
26✔
249
        a.EnableManualLinking = cast.Val(remoteConfig.SecurityManualLinkingEnabled, false)
26✔
250
        a.EnableSignup = !cast.Val(remoteConfig.DisableSignup, false)
26✔
251
        a.EnableAnonymousSignIns = cast.Val(remoteConfig.ExternalAnonymousUsersEnabled, false)
26✔
252
        a.MinimumPasswordLength = cast.IntToUint(cast.Val(remoteConfig.PasswordMinLength, 0))
26✔
253
        prc := cast.Val(remoteConfig.PasswordRequiredCharacters, "")
26✔
254
        a.PasswordRequirements = NewPasswordRequirement(v1API.UpdateAuthConfigBodyPasswordRequiredCharacters(prc))
26✔
255
        a.Hook.fromAuthConfig(remoteConfig)
26✔
256
        a.MFA.fromAuthConfig(remoteConfig)
26✔
257
        a.Sessions.fromAuthConfig(remoteConfig)
26✔
258
        a.Email.fromAuthConfig(remoteConfig)
26✔
259
        a.Sms.fromAuthConfig(remoteConfig)
26✔
260
        a.External.fromAuthConfig(remoteConfig)
26✔
261
}
26✔
262

263
func (h hook) toAuthConfigBody(body *v1API.UpdateAuthConfigBody) {
2✔
264
        // When local config is not set, we assume platform defaults should not change
2✔
265
        if hook := h.CustomAccessToken; hook != nil {
2✔
266
                if body.HookCustomAccessTokenEnabled = &hook.Enabled; hook.Enabled {
×
267
                        body.HookCustomAccessTokenUri = &hook.URI
×
NEW
268
                        if len(hook.Secrets.SHA256) > 0 {
×
269
                                body.HookCustomAccessTokenSecrets = &hook.Secrets.Value
×
270
                        }
×
271
                }
272
        }
273
        if hook := h.SendEmail; hook != nil {
2✔
274
                if body.HookSendEmailEnabled = &hook.Enabled; hook.Enabled {
×
275
                        body.HookSendEmailUri = &hook.URI
×
NEW
276
                        if len(hook.Secrets.SHA256) > 0 {
×
277
                                body.HookSendEmailSecrets = &hook.Secrets.Value
×
278
                        }
×
279
                }
280
        }
281
        if hook := h.SendSMS; hook != nil {
2✔
282
                if body.HookSendSmsEnabled = &hook.Enabled; hook.Enabled {
×
283
                        body.HookSendSmsUri = &hook.URI
×
NEW
284
                        if len(hook.Secrets.SHA256) > 0 {
×
285
                                body.HookSendSmsSecrets = &hook.Secrets.Value
×
286
                        }
×
287
                }
288
        }
289
        // Enterprise and team only features
290
        if hook := h.MFAVerificationAttempt; hook != nil {
2✔
291
                if body.HookMfaVerificationAttemptEnabled = &hook.Enabled; hook.Enabled {
×
292
                        body.HookMfaVerificationAttemptUri = &hook.URI
×
NEW
293
                        if len(hook.Secrets.SHA256) > 0 {
×
294
                                body.HookMfaVerificationAttemptSecrets = &hook.Secrets.Value
×
295
                        }
×
296
                }
297
        }
298
        if hook := h.PasswordVerificationAttempt; hook != nil {
2✔
299
                if body.HookPasswordVerificationAttemptEnabled = &hook.Enabled; hook.Enabled {
×
300
                        body.HookPasswordVerificationAttemptUri = &hook.URI
×
NEW
301
                        if len(hook.Secrets.SHA256) > 0 {
×
302
                                body.HookPasswordVerificationAttemptSecrets = &hook.Secrets.Value
×
303
                        }
×
304
                }
305
        }
306
}
307
func (h *hook) fromAuthConfig(remoteConfig v1API.AuthConfigResponse) {
26✔
308
        // When local config is not set, we assume platform defaults should not change
26✔
309
        if hook := h.CustomAccessToken; hook != nil {
30✔
310
                // Ignore disabled hooks because their envs are not loaded
4✔
311
                if hook.Enabled {
6✔
312
                        hook.URI = cast.Val(remoteConfig.HookCustomAccessTokenUri, "")
2✔
313
                        if len(hook.Secrets.SHA256) > 0 {
4✔
314
                                hook.Secrets.SHA256 = cast.Val(remoteConfig.HookCustomAccessTokenSecrets, "")
2✔
315
                        }
2✔
316
                }
317
                hook.Enabled = cast.Val(remoteConfig.HookCustomAccessTokenEnabled, false)
4✔
318
        }
319
        if hook := h.SendEmail; hook != nil {
30✔
320
                if hook.Enabled {
6✔
321
                        hook.URI = cast.Val(remoteConfig.HookSendEmailUri, "")
2✔
322
                        if len(hook.Secrets.SHA256) > 0 {
3✔
323
                                hook.Secrets.SHA256 = cast.Val(remoteConfig.HookSendEmailSecrets, "")
1✔
324
                        }
1✔
325
                }
326
                hook.Enabled = cast.Val(remoteConfig.HookSendEmailEnabled, false)
4✔
327
        }
328
        if hook := h.SendSMS; hook != nil {
30✔
329
                if hook.Enabled {
6✔
330
                        hook.URI = cast.Val(remoteConfig.HookSendSmsUri, "")
2✔
331
                        if len(hook.Secrets.SHA256) > 0 {
4✔
332
                                hook.Secrets.SHA256 = cast.Val(remoteConfig.HookSendSmsSecrets, "")
2✔
333
                        }
2✔
334
                }
335
                hook.Enabled = cast.Val(remoteConfig.HookSendSmsEnabled, false)
4✔
336
        }
337
        // Enterprise and team only features
338
        if hook := h.MFAVerificationAttempt; hook != nil {
30✔
339
                if hook.Enabled {
6✔
340
                        hook.URI = cast.Val(remoteConfig.HookMfaVerificationAttemptUri, "")
2✔
341
                        if len(hook.Secrets.SHA256) > 0 {
3✔
342
                                hook.Secrets.SHA256 = cast.Val(remoteConfig.HookMfaVerificationAttemptSecrets, "")
1✔
343
                        }
1✔
344
                }
345
                hook.Enabled = cast.Val(remoteConfig.HookMfaVerificationAttemptEnabled, false)
4✔
346
        }
347
        if hook := h.PasswordVerificationAttempt; hook != nil {
28✔
348
                if hook.Enabled {
3✔
349
                        hook.URI = cast.Val(remoteConfig.HookPasswordVerificationAttemptUri, "")
1✔
350
                        if len(hook.Secrets.SHA256) > 0 {
1✔
351
                                hook.Secrets.SHA256 = cast.Val(remoteConfig.HookPasswordVerificationAttemptSecrets, "")
×
352
                        }
×
353
                }
354
                hook.Enabled = cast.Val(remoteConfig.HookPasswordVerificationAttemptEnabled, false)
2✔
355
        }
356
}
357

358
func (m mfa) toAuthConfigBody(body *v1API.UpdateAuthConfigBody) {
2✔
359
        body.MfaMaxEnrolledFactors = cast.UintToIntPtr(&m.MaxEnrolledFactors)
2✔
360
        body.MfaTotpEnrollEnabled = &m.TOTP.EnrollEnabled
2✔
361
        body.MfaTotpVerifyEnabled = &m.TOTP.VerifyEnabled
2✔
362
        body.MfaPhoneEnrollEnabled = &m.Phone.EnrollEnabled
2✔
363
        body.MfaPhoneVerifyEnabled = &m.Phone.VerifyEnabled
2✔
364
        body.MfaPhoneOtpLength = cast.UintToIntPtr(&m.Phone.OtpLength)
2✔
365
        body.MfaPhoneTemplate = &m.Phone.Template
2✔
366
        body.MfaPhoneMaxFrequency = cast.Ptr(int(m.Phone.MaxFrequency.Seconds()))
2✔
367
        body.MfaWebAuthnEnrollEnabled = &m.WebAuthn.EnrollEnabled
2✔
368
        body.MfaWebAuthnVerifyEnabled = &m.WebAuthn.VerifyEnabled
2✔
369
}
2✔
370

371
func (m *mfa) fromAuthConfig(remoteConfig v1API.AuthConfigResponse) {
26✔
372
        m.MaxEnrolledFactors = cast.IntToUint(cast.Val(remoteConfig.MfaMaxEnrolledFactors, 0))
26✔
373
        m.TOTP.EnrollEnabled = cast.Val(remoteConfig.MfaTotpEnrollEnabled, false)
26✔
374
        m.TOTP.VerifyEnabled = cast.Val(remoteConfig.MfaTotpVerifyEnabled, false)
26✔
375
        m.Phone.EnrollEnabled = cast.Val(remoteConfig.MfaPhoneEnrollEnabled, false)
26✔
376
        m.Phone.VerifyEnabled = cast.Val(remoteConfig.MfaPhoneVerifyEnabled, false)
26✔
377
        m.Phone.OtpLength = cast.IntToUint(remoteConfig.MfaPhoneOtpLength)
26✔
378
        m.Phone.Template = cast.Val(remoteConfig.MfaPhoneTemplate, "")
26✔
379
        m.Phone.MaxFrequency = time.Duration(cast.Val(remoteConfig.MfaPhoneMaxFrequency, 0)) * time.Second
26✔
380
        m.WebAuthn.EnrollEnabled = cast.Val(remoteConfig.MfaWebAuthnEnrollEnabled, false)
26✔
381
        m.WebAuthn.VerifyEnabled = cast.Val(remoteConfig.MfaWebAuthnVerifyEnabled, false)
26✔
382
}
26✔
383

384
func (s sessions) toAuthConfigBody(body *v1API.UpdateAuthConfigBody) {
2✔
385
        body.SessionsTimebox = cast.Ptr(int(s.Timebox.Seconds()))
2✔
386
        body.SessionsInactivityTimeout = cast.Ptr(int(s.InactivityTimeout.Seconds()))
2✔
387
}
2✔
388

389
func (s *sessions) fromAuthConfig(remoteConfig v1API.AuthConfigResponse) {
26✔
390
        s.Timebox = time.Duration(cast.Val(remoteConfig.SessionsTimebox, 0)) * time.Second
26✔
391
        s.InactivityTimeout = time.Duration(cast.Val(remoteConfig.SessionsInactivityTimeout, 0)) * time.Second
26✔
392
}
26✔
393

394
func (e email) toAuthConfigBody(body *v1API.UpdateAuthConfigBody) {
2✔
395
        body.ExternalEmailEnabled = &e.EnableSignup
2✔
396
        body.MailerSecureEmailChangeEnabled = &e.DoubleConfirmChanges
2✔
397
        body.MailerAutoconfirm = cast.Ptr(!e.EnableConfirmations)
2✔
398
        body.MailerOtpLength = cast.UintToIntPtr(&e.OtpLength)
2✔
399
        body.MailerOtpExp = cast.UintToIntPtr(&e.OtpExpiry)
2✔
400
        body.SecurityUpdatePasswordRequireReauthentication = &e.SecurePasswordChange
2✔
401
        body.SmtpMaxFrequency = cast.Ptr(int(e.MaxFrequency.Seconds()))
2✔
402
        // When local config is not set, we assume platform defaults should not change
2✔
403
        if e.Smtp != nil {
2✔
404
                e.Smtp.toAuthConfigBody(body)
×
405
        }
×
406
        if len(e.Template) == 0 {
4✔
407
                return
2✔
408
        }
2✔
409
        var tmpl *emailTemplate
×
410
        tmpl = cast.Ptr(e.Template["invite"])
×
411
        body.MailerSubjectsInvite = tmpl.Subject
×
412
        body.MailerTemplatesInviteContent = tmpl.Content
×
413
        tmpl = cast.Ptr(e.Template["confirmation"])
×
414
        body.MailerSubjectsConfirmation = tmpl.Subject
×
415
        body.MailerTemplatesConfirmationContent = tmpl.Content
×
416
        tmpl = cast.Ptr(e.Template["recovery"])
×
417
        body.MailerSubjectsRecovery = tmpl.Subject
×
418
        body.MailerTemplatesRecoveryContent = tmpl.Content
×
419
        tmpl = cast.Ptr(e.Template["magic_link"])
×
420
        body.MailerSubjectsMagicLink = tmpl.Subject
×
421
        body.MailerTemplatesMagicLinkContent = tmpl.Content
×
422
        tmpl = cast.Ptr(e.Template["email_change"])
×
423
        body.MailerSubjectsEmailChange = tmpl.Subject
×
424
        body.MailerTemplatesEmailChangeContent = tmpl.Content
×
425
        tmpl = cast.Ptr(e.Template["reauthentication"])
×
426
        body.MailerSubjectsReauthentication = tmpl.Subject
×
427
        body.MailerTemplatesReauthenticationContent = tmpl.Content
×
428
}
429

430
func (e *email) fromAuthConfig(remoteConfig v1API.AuthConfigResponse) {
26✔
431
        e.EnableSignup = cast.Val(remoteConfig.ExternalEmailEnabled, false)
26✔
432
        e.DoubleConfirmChanges = cast.Val(remoteConfig.MailerSecureEmailChangeEnabled, false)
26✔
433
        e.EnableConfirmations = !cast.Val(remoteConfig.MailerAutoconfirm, false)
26✔
434
        e.OtpLength = cast.IntToUint(cast.Val(remoteConfig.MailerOtpLength, 0))
26✔
435
        e.OtpExpiry = cast.IntToUint(remoteConfig.MailerOtpExp)
26✔
436
        e.SecurePasswordChange = cast.Val(remoteConfig.SecurityUpdatePasswordRequireReauthentication, false)
26✔
437
        e.MaxFrequency = time.Duration(cast.Val(remoteConfig.SmtpMaxFrequency, 0)) * time.Second
26✔
438
        // When local config is not set, we assume platform defaults should not change
26✔
439
        if e.Smtp != nil {
29✔
440
                e.Smtp.fromAuthConfig(remoteConfig)
3✔
441
        }
3✔
442
        if len(e.Template) == 0 {
48✔
443
                return
22✔
444
        }
22✔
445
        var tmpl emailTemplate
4✔
446
        tmpl = e.Template["invite"]
4✔
447
        if tmpl.Subject != nil {
6✔
448
                tmpl.Subject = remoteConfig.MailerSubjectsInvite
2✔
449
        }
2✔
450
        if tmpl.Content != nil {
6✔
451
                tmpl.Content = remoteConfig.MailerTemplatesInviteContent
2✔
452
        }
2✔
453
        e.Template["invite"] = tmpl
4✔
454

4✔
455
        tmpl = e.Template["confirmation"]
4✔
456
        if tmpl.Subject != nil {
6✔
457
                tmpl.Subject = remoteConfig.MailerSubjectsConfirmation
2✔
458
        }
2✔
459
        if tmpl.Content != nil {
5✔
460
                tmpl.Content = remoteConfig.MailerTemplatesConfirmationContent
1✔
461
        }
1✔
462
        e.Template["confirmation"] = tmpl
4✔
463

4✔
464
        tmpl = e.Template["recovery"]
4✔
465
        if tmpl.Subject != nil {
5✔
466
                tmpl.Subject = remoteConfig.MailerSubjectsRecovery
1✔
467
        }
1✔
468
        if tmpl.Content != nil {
6✔
469
                tmpl.Content = remoteConfig.MailerTemplatesRecoveryContent
2✔
470
        }
2✔
471
        e.Template["recovery"] = tmpl
4✔
472

4✔
473
        tmpl = e.Template["magic_link"]
4✔
474
        if tmpl.Subject != nil {
6✔
475
                tmpl.Subject = remoteConfig.MailerSubjectsMagicLink
2✔
476
        }
2✔
477
        if tmpl.Content != nil {
6✔
478
                tmpl.Content = remoteConfig.MailerTemplatesMagicLinkContent
2✔
479
        }
2✔
480
        e.Template["magic_link"] = tmpl
4✔
481

4✔
482
        tmpl = e.Template["email_change"]
4✔
483
        if tmpl.Subject != nil {
6✔
484
                tmpl.Subject = remoteConfig.MailerSubjectsEmailChange
2✔
485
        }
2✔
486
        if tmpl.Content != nil {
6✔
487
                tmpl.Content = remoteConfig.MailerTemplatesEmailChangeContent
2✔
488
        }
2✔
489
        e.Template["email_change"] = tmpl
4✔
490

4✔
491
        tmpl = e.Template["reauthentication"]
4✔
492
        if tmpl.Subject != nil {
6✔
493
                tmpl.Subject = remoteConfig.MailerSubjectsReauthentication
2✔
494
        }
2✔
495
        if tmpl.Content != nil {
6✔
496
                tmpl.Content = remoteConfig.MailerTemplatesReauthenticationContent
2✔
497
        }
2✔
498
        e.Template["reauthentication"] = tmpl
4✔
499
}
500

501
func (s smtp) IsEnabled() bool {
5✔
502
        // If Enabled is not defined, or defined and set to true
5✔
503
        return cast.Val(s.Enabled, true)
5✔
504
}
5✔
505

506
func (s smtp) toAuthConfigBody(body *v1API.UpdateAuthConfigBody) {
×
507
        if !s.IsEnabled() {
×
508
                // Setting a single empty string disables SMTP
×
509
                body.SmtpHost = cast.Ptr("")
×
510
                return
×
511
        }
×
512
        body.SmtpHost = &s.Host
×
513
        body.SmtpPort = cast.Ptr(strconv.Itoa(int(s.Port)))
×
514
        body.SmtpUser = &s.User
×
NEW
515
        if len(s.Pass.SHA256) > 0 {
×
516
                body.SmtpPass = &s.Pass.Value
×
517
        }
×
518
        body.SmtpAdminEmail = &s.AdminEmail
×
519
        body.SmtpSenderName = &s.SenderName
×
520
}
521

522
func (s *smtp) fromAuthConfig(remoteConfig v1API.AuthConfigResponse) {
3✔
523
        showDiff := s.IsEnabled()
3✔
524
        // Api resets all values when SMTP is disabled
3✔
525
        if enabled := remoteConfig.SmtpHost != nil; s.Enabled != nil {
5✔
526
                *s.Enabled = enabled
2✔
527
        }
2✔
528
        if !showDiff {
4✔
529
                return
1✔
530
        }
1✔
531
        s.Host = cast.Val(remoteConfig.SmtpHost, "")
2✔
532
        s.User = cast.Val(remoteConfig.SmtpUser, "")
2✔
533
        if len(s.Pass.SHA256) > 0 {
4✔
534
                s.Pass.SHA256 = cast.Val(remoteConfig.SmtpPass, "")
2✔
535
        }
2✔
536
        s.AdminEmail = cast.Val(remoteConfig.SmtpAdminEmail, "")
2✔
537
        s.SenderName = cast.Val(remoteConfig.SmtpSenderName, "")
2✔
538
        portStr := cast.Val(remoteConfig.SmtpPort, "0")
2✔
539
        if port, err := strconv.ParseUint(portStr, 10, 16); err == nil {
4✔
540
                s.Port = uint16(port)
2✔
541
        }
2✔
542
}
543

544
func (s sms) toAuthConfigBody(body *v1API.UpdateAuthConfigBody) {
2✔
545
        body.ExternalPhoneEnabled = &s.EnableSignup
2✔
546
        body.SmsMaxFrequency = cast.Ptr(int(s.MaxFrequency.Seconds()))
2✔
547
        body.SmsAutoconfirm = &s.EnableConfirmations
2✔
548
        body.SmsTemplate = &s.Template
2✔
549
        if otpString := mapToEnv(s.TestOTP); len(otpString) > 0 {
2✔
550
                body.SmsTestOtp = &otpString
×
551
                // Set a 10 year validity for test OTP
×
552
                timestamp := time.Now().UTC().AddDate(10, 0, 0).Format(time.RFC3339)
×
553
                body.SmsTestOtpValidUntil = &timestamp
×
554
        }
×
555
        // Api only overrides configs of enabled providers
556
        switch {
2✔
557
        case s.Twilio.Enabled:
×
558
                body.SmsProvider = cast.Ptr("twilio")
×
NEW
559
                if len(s.Twilio.AuthToken.SHA256) > 0 {
×
560
                        body.SmsTwilioAuthToken = &s.Twilio.AuthToken.Value
×
561
                }
×
562
                body.SmsTwilioAccountSid = &s.Twilio.AccountSid
×
563
                body.SmsTwilioMessageServiceSid = &s.Twilio.MessageServiceSid
×
564
        case s.TwilioVerify.Enabled:
×
565
                body.SmsProvider = cast.Ptr("twilio_verify")
×
NEW
566
                if len(s.TwilioVerify.AuthToken.SHA256) > 0 {
×
567
                        body.SmsTwilioVerifyAuthToken = &s.TwilioVerify.AuthToken.Value
×
568
                }
×
569
                body.SmsTwilioVerifyAccountSid = &s.TwilioVerify.AccountSid
×
570
                body.SmsTwilioVerifyMessageServiceSid = &s.TwilioVerify.MessageServiceSid
×
571
        case s.Messagebird.Enabled:
×
572
                body.SmsProvider = cast.Ptr("messagebird")
×
NEW
573
                if len(s.Messagebird.AccessKey.SHA256) > 0 {
×
574
                        body.SmsMessagebirdAccessKey = &s.Messagebird.AccessKey.Value
×
575
                }
×
576
                body.SmsMessagebirdOriginator = &s.Messagebird.Originator
×
577
        case s.Textlocal.Enabled:
×
578
                body.SmsProvider = cast.Ptr("textlocal")
×
NEW
579
                if len(s.Textlocal.ApiKey.SHA256) > 0 {
×
580
                        body.SmsTextlocalApiKey = &s.Textlocal.ApiKey.Value
×
581
                }
×
582
                body.SmsTextlocalSender = &s.Textlocal.Sender
×
583
        case s.Vonage.Enabled:
×
584
                body.SmsProvider = cast.Ptr("vonage")
×
NEW
585
                if len(s.Vonage.ApiSecret.SHA256) > 0 {
×
586
                        body.SmsVonageApiSecret = &s.Vonage.ApiSecret.Value
×
587
                }
×
588
                body.SmsVonageApiKey = &s.Vonage.ApiKey
×
589
                body.SmsVonageFrom = &s.Vonage.From
×
590
        }
591
}
592

593
func (s *sms) fromAuthConfig(remoteConfig v1API.AuthConfigResponse) {
26✔
594
        s.EnableSignup = cast.Val(remoteConfig.ExternalPhoneEnabled, false)
26✔
595
        s.MaxFrequency = time.Duration(cast.Val(remoteConfig.SmsMaxFrequency, 0)) * time.Second
26✔
596
        s.EnableConfirmations = cast.Val(remoteConfig.SmsAutoconfirm, false)
26✔
597
        s.Template = cast.Val(remoteConfig.SmsTemplate, "")
26✔
598
        s.TestOTP = envToMap(cast.Val(remoteConfig.SmsTestOtp, ""))
26✔
599
        // We are only interested in the provider that's enabled locally
26✔
600
        switch {
26✔
601
        case s.Twilio.Enabled:
1✔
602
                if len(s.Twilio.AuthToken.SHA256) > 0 {
2✔
603
                        s.Twilio.AuthToken.SHA256 = cast.Val(remoteConfig.SmsTwilioAuthToken, "")
1✔
604
                }
1✔
605
                s.Twilio.AccountSid = cast.Val(remoteConfig.SmsTwilioAccountSid, "")
1✔
606
                s.Twilio.MessageServiceSid = cast.Val(remoteConfig.SmsTwilioMessageServiceSid, "")
1✔
607
        case s.TwilioVerify.Enabled:
×
608
                if len(s.TwilioVerify.AuthToken.SHA256) > 0 {
×
609
                        s.TwilioVerify.AuthToken.SHA256 = cast.Val(remoteConfig.SmsTwilioVerifyAuthToken, "")
×
610
                }
×
611
                s.TwilioVerify.AccountSid = cast.Val(remoteConfig.SmsTwilioVerifyAccountSid, "")
×
612
                s.TwilioVerify.MessageServiceSid = cast.Val(remoteConfig.SmsTwilioVerifyMessageServiceSid, "")
×
613
        case s.Messagebird.Enabled:
2✔
614
                if len(s.Messagebird.AccessKey.SHA256) > 0 {
3✔
615
                        s.Messagebird.AccessKey.SHA256 = cast.Val(remoteConfig.SmsMessagebirdAccessKey, "")
1✔
616
                }
1✔
617
                s.Messagebird.Originator = cast.Val(remoteConfig.SmsMessagebirdOriginator, "")
2✔
618
        case s.Textlocal.Enabled:
×
619
                if len(s.Textlocal.ApiKey.SHA256) > 0 {
×
620
                        s.Textlocal.ApiKey.SHA256 = cast.Val(remoteConfig.SmsTextlocalApiKey, "")
×
621
                }
×
622
                s.Textlocal.Sender = cast.Val(remoteConfig.SmsTextlocalSender, "")
×
623
        case s.Vonage.Enabled:
×
624
                if len(s.Vonage.ApiSecret.SHA256) > 0 {
×
625
                        s.Vonage.ApiSecret.SHA256 = cast.Val(remoteConfig.SmsVonageApiSecret, "")
×
626
                }
×
627
                s.Vonage.ApiKey = cast.Val(remoteConfig.SmsVonageApiKey, "")
×
628
                s.Vonage.From = cast.Val(remoteConfig.SmsVonageFrom, "")
×
629
        case !s.EnableSignup:
22✔
630
                // Nothing to do if both local and remote providers are disabled.
22✔
631
                return
22✔
632
        }
633
        if provider := cast.Val(remoteConfig.SmsProvider, ""); len(provider) > 0 {
8✔
634
                s.Twilio.Enabled = provider == "twilio"
4✔
635
                s.TwilioVerify.Enabled = provider == "twilio_verify"
4✔
636
                s.Messagebird.Enabled = provider == "messagebird"
4✔
637
                s.Textlocal.Enabled = provider == "textlocal"
4✔
638
                s.Vonage.Enabled = provider == "vonage"
4✔
639
        }
4✔
640
}
641

642
func (e external) toAuthConfigBody(body *v1API.UpdateAuthConfigBody) {
2✔
643
        if len(e) == 0 {
4✔
644
                return
2✔
645
        }
2✔
646
        // Ignore configs of disabled providers because their envs are not loaded
647
        if p, ok := e["apple"]; ok {
×
648
                if body.ExternalAppleEnabled = &p.Enabled; *body.ExternalAppleEnabled {
×
649
                        body.ExternalAppleClientId = &p.ClientId
×
NEW
650
                        if len(p.Secret.SHA256) > 0 {
×
651
                                body.ExternalAppleSecret = &p.Secret.Value
×
652
                        }
×
653
                }
654
        }
655
        if p, ok := e["azure"]; ok {
×
656
                if body.ExternalAzureEnabled = &p.Enabled; *body.ExternalAzureEnabled {
×
657
                        body.ExternalAzureClientId = &p.ClientId
×
NEW
658
                        if len(p.Secret.SHA256) > 0 {
×
659
                                body.ExternalAzureSecret = &p.Secret.Value
×
660
                        }
×
661
                        body.ExternalAzureUrl = &p.Url
×
662
                }
663
        }
664
        if p, ok := e["bitbucket"]; ok {
×
665
                if body.ExternalBitbucketEnabled = &p.Enabled; *body.ExternalBitbucketEnabled {
×
666
                        body.ExternalBitbucketClientId = &p.ClientId
×
NEW
667
                        if len(p.Secret.SHA256) > 0 {
×
668
                                body.ExternalBitbucketSecret = &p.Secret.Value
×
669
                        }
×
670
                }
671
        }
672
        if p, ok := e["discord"]; ok {
×
673
                if body.ExternalDiscordEnabled = &p.Enabled; *body.ExternalDiscordEnabled {
×
674
                        body.ExternalDiscordClientId = &p.ClientId
×
NEW
675
                        if len(p.Secret.SHA256) > 0 {
×
676
                                body.ExternalDiscordSecret = &p.Secret.Value
×
677
                        }
×
678
                }
679
        }
680
        if p, ok := e["facebook"]; ok {
×
681
                if body.ExternalFacebookEnabled = &p.Enabled; *body.ExternalFacebookEnabled {
×
682
                        body.ExternalFacebookClientId = &p.ClientId
×
NEW
683
                        if len(p.Secret.SHA256) > 0 {
×
684
                                body.ExternalFacebookSecret = &p.Secret.Value
×
685
                        }
×
686
                }
687
        }
688
        if p, ok := e["figma"]; ok {
×
689
                if body.ExternalFigmaEnabled = &p.Enabled; *body.ExternalFigmaEnabled {
×
690
                        body.ExternalFigmaClientId = &p.ClientId
×
NEW
691
                        if len(p.Secret.SHA256) > 0 {
×
692
                                body.ExternalFigmaSecret = &p.Secret.Value
×
693
                        }
×
694
                }
695
        }
696
        if p, ok := e["github"]; ok {
×
697
                if body.ExternalGithubEnabled = &p.Enabled; *body.ExternalGithubEnabled {
×
698
                        body.ExternalGithubClientId = &p.ClientId
×
NEW
699
                        if len(p.Secret.SHA256) > 0 {
×
700
                                body.ExternalGithubSecret = &p.Secret.Value
×
701
                        }
×
702
                }
703
        }
704
        if p, ok := e["gitlab"]; ok {
×
705
                if body.ExternalGitlabEnabled = &p.Enabled; *body.ExternalGitlabEnabled {
×
706
                        body.ExternalGitlabClientId = &p.ClientId
×
NEW
707
                        if len(p.Secret.SHA256) > 0 {
×
708
                                body.ExternalGitlabSecret = &p.Secret.Value
×
709
                        }
×
710
                        body.ExternalGitlabUrl = &p.Url
×
711
                }
712
        }
713
        if p, ok := e["google"]; ok {
×
714
                if body.ExternalGoogleEnabled = &p.Enabled; *body.ExternalGoogleEnabled {
×
715
                        body.ExternalGoogleClientId = &p.ClientId
×
NEW
716
                        if len(p.Secret.SHA256) > 0 {
×
717
                                body.ExternalGoogleSecret = &p.Secret.Value
×
718
                        }
×
719
                        body.ExternalGoogleSkipNonceCheck = &p.SkipNonceCheck
×
720
                }
721
        }
722
        if p, ok := e["kakao"]; ok {
×
723
                if body.ExternalKakaoEnabled = &p.Enabled; *body.ExternalKakaoEnabled {
×
724
                        body.ExternalKakaoClientId = &p.ClientId
×
NEW
725
                        if len(p.Secret.SHA256) > 0 {
×
726
                                body.ExternalKakaoSecret = &p.Secret.Value
×
727
                        }
×
728
                }
729
        }
730
        if p, ok := e["keycloak"]; ok {
×
731
                if body.ExternalKeycloakEnabled = &p.Enabled; *body.ExternalKeycloakEnabled {
×
732
                        body.ExternalKeycloakClientId = &p.ClientId
×
NEW
733
                        if len(p.Secret.SHA256) > 0 {
×
734
                                body.ExternalKeycloakSecret = &p.Secret.Value
×
735
                        }
×
736
                        body.ExternalKeycloakUrl = &p.Url
×
737
                }
738
        }
739
        if p, ok := e["linkedin_oidc"]; ok {
×
740
                if body.ExternalLinkedinOidcEnabled = &p.Enabled; *body.ExternalLinkedinOidcEnabled {
×
741
                        body.ExternalLinkedinOidcClientId = &p.ClientId
×
NEW
742
                        if len(p.Secret.SHA256) > 0 {
×
743
                                body.ExternalLinkedinOidcSecret = &p.Secret.Value
×
744
                        }
×
745
                }
746
        }
747
        if p, ok := e["notion"]; ok {
×
748
                if body.ExternalNotionEnabled = &p.Enabled; *body.ExternalNotionEnabled {
×
749
                        body.ExternalNotionClientId = &p.ClientId
×
NEW
750
                        if len(p.Secret.SHA256) > 0 {
×
751
                                body.ExternalNotionSecret = &p.Secret.Value
×
752
                        }
×
753
                }
754
        }
755
        if p, ok := e["slack_oidc"]; ok {
×
756
                if body.ExternalSlackOidcEnabled = &p.Enabled; *body.ExternalSlackOidcEnabled {
×
757
                        body.ExternalSlackOidcClientId = &p.ClientId
×
NEW
758
                        if len(p.Secret.SHA256) > 0 {
×
759
                                body.ExternalSlackOidcSecret = &p.Secret.Value
×
760
                        }
×
761
                }
762
        }
763
        if p, ok := e["spotify"]; ok {
×
764
                if body.ExternalSpotifyEnabled = &p.Enabled; *body.ExternalSpotifyEnabled {
×
765
                        body.ExternalSpotifyClientId = &p.ClientId
×
NEW
766
                        if len(p.Secret.SHA256) > 0 {
×
767
                                body.ExternalSpotifySecret = &p.Secret.Value
×
768
                        }
×
769
                }
770
        }
771
        if p, ok := e["twitch"]; ok {
×
772
                if body.ExternalTwitchEnabled = &p.Enabled; *body.ExternalTwitchEnabled {
×
773
                        body.ExternalTwitchClientId = &p.ClientId
×
NEW
774
                        if len(p.Secret.SHA256) > 0 {
×
775
                                body.ExternalTwitchSecret = &p.Secret.Value
×
776
                        }
×
777
                }
778
        }
779
        if p, ok := e["twitter"]; ok {
×
780
                if body.ExternalTwitterEnabled = &p.Enabled; *body.ExternalTwitterEnabled {
×
781
                        body.ExternalTwitterClientId = &p.ClientId
×
NEW
782
                        if len(p.Secret.SHA256) > 0 {
×
783
                                body.ExternalTwitterSecret = &p.Secret.Value
×
784
                        }
×
785
                }
786
        }
787
        if p, ok := e["workos"]; ok {
×
788
                if body.ExternalWorkosEnabled = &p.Enabled; *body.ExternalWorkosEnabled {
×
789
                        body.ExternalWorkosClientId = &p.ClientId
×
NEW
790
                        if len(p.Secret.SHA256) > 0 {
×
791
                                body.ExternalWorkosSecret = &p.Secret.Value
×
792
                        }
×
793
                        body.ExternalWorkosUrl = &p.Url
×
794
                }
795
        }
796
        if p, ok := e["zoom"]; ok {
×
797
                if body.ExternalZoomEnabled = &p.Enabled; *body.ExternalZoomEnabled {
×
798
                        body.ExternalZoomClientId = &p.ClientId
×
NEW
799
                        if len(p.Secret.SHA256) > 0 {
×
800
                                body.ExternalZoomSecret = &p.Secret.Value
×
801
                        }
×
802
                }
803
        }
804
}
805

806
func (e external) fromAuthConfig(remoteConfig v1API.AuthConfigResponse) {
26✔
807
        if len(e) == 0 {
49✔
808
                return
23✔
809
        }
23✔
810
        // Ignore configs of disabled providers because their envs are not loaded
811
        if p, ok := e["apple"]; ok {
6✔
812
                if p.Enabled {
5✔
813
                        p.ClientId = cast.Val(remoteConfig.ExternalAppleClientId, "")
2✔
814
                        if ids := cast.Val(remoteConfig.ExternalAppleAdditionalClientIds, ""); len(ids) > 0 {
3✔
815
                                p.ClientId += "," + ids
1✔
816
                        }
1✔
817
                        if len(p.Secret.SHA256) > 0 {
3✔
818
                                p.Secret.SHA256 = cast.Val(remoteConfig.ExternalAppleSecret, "")
1✔
819
                        }
1✔
820
                }
821
                p.Enabled = cast.Val(remoteConfig.ExternalAppleEnabled, false)
3✔
822
                e["apple"] = p
3✔
823
        }
824

825
        if p, ok := e["azure"]; ok {
6✔
826
                if p.Enabled {
5✔
827
                        p.ClientId = cast.Val(remoteConfig.ExternalAzureClientId, "")
2✔
828
                        if len(p.Secret.SHA256) > 0 {
3✔
829
                                p.Secret.SHA256 = cast.Val(remoteConfig.ExternalAzureSecret, "")
1✔
830
                        }
1✔
831
                        p.Url = cast.Val(remoteConfig.ExternalAzureUrl, "")
2✔
832
                }
833
                p.Enabled = cast.Val(remoteConfig.ExternalAzureEnabled, false)
3✔
834
                e["azure"] = p
3✔
835
        }
836

837
        if p, ok := e["bitbucket"]; ok {
6✔
838
                if p.Enabled {
4✔
839
                        p.ClientId = cast.Val(remoteConfig.ExternalBitbucketClientId, "")
1✔
840
                        if len(p.Secret.SHA256) > 0 {
1✔
841
                                p.Secret.SHA256 = cast.Val(remoteConfig.ExternalBitbucketSecret, "")
×
842
                        }
×
843
                }
844
                p.Enabled = cast.Val(remoteConfig.ExternalBitbucketEnabled, false)
3✔
845
                e["bitbucket"] = p
3✔
846
        }
847

848
        if p, ok := e["discord"]; ok {
6✔
849
                if p.Enabled {
4✔
850
                        p.ClientId = cast.Val(remoteConfig.ExternalDiscordClientId, "")
1✔
851
                        if len(p.Secret.SHA256) > 0 {
1✔
852
                                p.Secret.SHA256 = cast.Val(remoteConfig.ExternalDiscordSecret, "")
×
853
                        }
×
854
                }
855
                p.Enabled = cast.Val(remoteConfig.ExternalDiscordEnabled, false)
3✔
856
                e["discord"] = p
3✔
857
        }
858

859
        if p, ok := e["facebook"]; ok {
6✔
860
                if p.Enabled {
4✔
861
                        p.ClientId = cast.Val(remoteConfig.ExternalFacebookClientId, "")
1✔
862
                        if len(p.Secret.SHA256) > 0 {
1✔
863
                                p.Secret.SHA256 = cast.Val(remoteConfig.ExternalFacebookSecret, "")
×
864
                        }
×
865
                }
866
                p.Enabled = cast.Val(remoteConfig.ExternalFacebookEnabled, false)
3✔
867
                e["facebook"] = p
3✔
868
        }
869

870
        if p, ok := e["figma"]; ok {
6✔
871
                if p.Enabled {
4✔
872
                        p.ClientId = cast.Val(remoteConfig.ExternalFigmaClientId, "")
1✔
873
                        if len(p.Secret.SHA256) > 0 {
1✔
874
                                p.Secret.SHA256 = cast.Val(remoteConfig.ExternalFigmaSecret, "")
×
875
                        }
×
876
                }
877
                p.Enabled = cast.Val(remoteConfig.ExternalFigmaEnabled, false)
3✔
878
                e["figma"] = p
3✔
879
        }
880

881
        if p, ok := e["github"]; ok {
6✔
882
                if p.Enabled {
4✔
883
                        p.ClientId = cast.Val(remoteConfig.ExternalGithubClientId, "")
1✔
884
                        if len(p.Secret.SHA256) > 0 {
1✔
885
                                p.Secret.SHA256 = cast.Val(remoteConfig.ExternalGithubSecret, "")
×
886
                        }
×
887
                }
888
                p.Enabled = cast.Val(remoteConfig.ExternalGithubEnabled, false)
3✔
889
                e["github"] = p
3✔
890
        }
891

892
        if p, ok := e["gitlab"]; ok {
6✔
893
                if p.Enabled {
4✔
894
                        p.ClientId = cast.Val(remoteConfig.ExternalGitlabClientId, "")
1✔
895
                        if len(p.Secret.SHA256) > 0 {
1✔
896
                                p.Secret.SHA256 = cast.Val(remoteConfig.ExternalGitlabSecret, "")
×
897
                        }
×
898
                        p.Url = cast.Val(remoteConfig.ExternalGitlabUrl, "")
1✔
899
                }
900
                p.Enabled = cast.Val(remoteConfig.ExternalGitlabEnabled, false)
3✔
901
                e["gitlab"] = p
3✔
902
        }
903

904
        if p, ok := e["google"]; ok {
6✔
905
                if p.Enabled {
4✔
906
                        p.ClientId = cast.Val(remoteConfig.ExternalGoogleClientId, "")
1✔
907
                        if ids := cast.Val(remoteConfig.ExternalGoogleAdditionalClientIds, ""); len(ids) > 0 {
1✔
908
                                p.ClientId += "," + ids
×
909
                        }
×
910
                        if len(p.Secret.SHA256) > 0 {
1✔
911
                                p.Secret.SHA256 = cast.Val(remoteConfig.ExternalGoogleSecret, "")
×
912
                        }
×
913
                        p.SkipNonceCheck = cast.Val(remoteConfig.ExternalGoogleSkipNonceCheck, false)
1✔
914
                }
915
                p.Enabled = cast.Val(remoteConfig.ExternalGoogleEnabled, false)
3✔
916
                e["google"] = p
3✔
917
        }
918

919
        if p, ok := e["kakao"]; ok {
5✔
920
                if p.Enabled {
3✔
921
                        p.ClientId = cast.Val(remoteConfig.ExternalKakaoClientId, "")
1✔
922
                        if len(p.Secret.SHA256) > 0 {
1✔
923
                                p.Secret.SHA256 = cast.Val(remoteConfig.ExternalKakaoSecret, "")
×
924
                        }
×
925
                }
926
                p.Enabled = cast.Val(remoteConfig.ExternalKakaoEnabled, false)
2✔
927
                e["kakao"] = p
2✔
928
        }
929

930
        if p, ok := e["keycloak"]; ok {
6✔
931
                if p.Enabled {
4✔
932
                        p.ClientId = cast.Val(remoteConfig.ExternalKeycloakClientId, "")
1✔
933
                        if len(p.Secret.SHA256) > 0 {
1✔
934
                                p.Secret.SHA256 = cast.Val(remoteConfig.ExternalKeycloakSecret, "")
×
935
                        }
×
936
                        p.Url = cast.Val(remoteConfig.ExternalKeycloakUrl, "")
1✔
937
                }
938
                p.Enabled = cast.Val(remoteConfig.ExternalKeycloakEnabled, false)
3✔
939
                e["keycloak"] = p
3✔
940
        }
941

942
        if p, ok := e["linkedin_oidc"]; ok {
6✔
943
                if p.Enabled {
4✔
944
                        p.ClientId = cast.Val(remoteConfig.ExternalLinkedinOidcClientId, "")
1✔
945
                        if len(p.Secret.SHA256) > 0 {
1✔
946
                                p.Secret.SHA256 = cast.Val(remoteConfig.ExternalLinkedinOidcSecret, "")
×
947
                        }
×
948
                }
949
                p.Enabled = cast.Val(remoteConfig.ExternalLinkedinOidcEnabled, false)
3✔
950
                e["linkedin_oidc"] = p
3✔
951
        }
952

953
        if p, ok := e["notion"]; ok {
6✔
954
                if p.Enabled {
4✔
955
                        p.ClientId = cast.Val(remoteConfig.ExternalNotionClientId, "")
1✔
956
                        if len(p.Secret.SHA256) > 0 {
1✔
957
                                p.Secret.SHA256 = cast.Val(remoteConfig.ExternalNotionSecret, "")
×
958
                        }
×
959
                }
960
                p.Enabled = cast.Val(remoteConfig.ExternalNotionEnabled, false)
3✔
961
                e["notion"] = p
3✔
962
        }
963

964
        if p, ok := e["slack_oidc"]; ok {
6✔
965
                if p.Enabled {
4✔
966
                        p.ClientId = cast.Val(remoteConfig.ExternalSlackOidcClientId, "")
1✔
967
                        if len(p.Secret.SHA256) > 0 {
1✔
968
                                p.Secret.SHA256 = cast.Val(remoteConfig.ExternalSlackOidcSecret, "")
×
969
                        }
×
970
                }
971
                p.Enabled = cast.Val(remoteConfig.ExternalSlackOidcEnabled, false)
3✔
972
                e["slack_oidc"] = p
3✔
973
        }
974

975
        if p, ok := e["spotify"]; ok {
6✔
976
                if p.Enabled {
4✔
977
                        p.ClientId = cast.Val(remoteConfig.ExternalSpotifyClientId, "")
1✔
978
                        if len(p.Secret.SHA256) > 0 {
1✔
979
                                p.Secret.SHA256 = cast.Val(remoteConfig.ExternalSpotifySecret, "")
×
980
                        }
×
981
                }
982
                p.Enabled = cast.Val(remoteConfig.ExternalSpotifyEnabled, false)
3✔
983
                e["spotify"] = p
3✔
984
        }
985

986
        if p, ok := e["twitch"]; ok {
6✔
987
                if p.Enabled {
4✔
988
                        p.ClientId = cast.Val(remoteConfig.ExternalTwitchClientId, "")
1✔
989
                        if len(p.Secret.SHA256) > 0 {
1✔
990
                                p.Secret.SHA256 = cast.Val(remoteConfig.ExternalTwitchSecret, "")
×
991
                        }
×
992
                }
993
                p.Enabled = cast.Val(remoteConfig.ExternalTwitchEnabled, false)
3✔
994
                e["twitch"] = p
3✔
995
        }
996

997
        if p, ok := e["twitter"]; ok {
6✔
998
                if p.Enabled {
4✔
999
                        p.ClientId = cast.Val(remoteConfig.ExternalTwitterClientId, "")
1✔
1000
                        if len(p.Secret.SHA256) > 0 {
1✔
1001
                                p.Secret.SHA256 = cast.Val(remoteConfig.ExternalTwitterSecret, "")
×
1002
                        }
×
1003
                }
1004
                p.Enabled = cast.Val(remoteConfig.ExternalTwitterEnabled, false)
3✔
1005
                e["twitter"] = p
3✔
1006
        }
1007

1008
        if p, ok := e["workos"]; ok {
6✔
1009
                if p.Enabled {
4✔
1010
                        p.ClientId = cast.Val(remoteConfig.ExternalWorkosClientId, "")
1✔
1011
                        if len(p.Secret.SHA256) > 0 {
1✔
1012
                                p.Secret.SHA256 = cast.Val(remoteConfig.ExternalWorkosSecret, "")
×
1013
                        }
×
1014
                        p.Url = cast.Val(remoteConfig.ExternalWorkosUrl, "")
1✔
1015
                }
1016
                p.Enabled = cast.Val(remoteConfig.ExternalWorkosEnabled, false)
3✔
1017
                e["workos"] = p
3✔
1018
        }
1019

1020
        if p, ok := e["zoom"]; ok {
6✔
1021
                if p.Enabled {
4✔
1022
                        p.ClientId = cast.Val(remoteConfig.ExternalZoomClientId, "")
1✔
1023
                        if len(p.Secret.SHA256) > 0 {
1✔
1024
                                p.Secret.SHA256 = cast.Val(remoteConfig.ExternalZoomSecret, "")
×
1025
                        }
×
1026
                }
1027
                p.Enabled = cast.Val(remoteConfig.ExternalZoomEnabled, false)
3✔
1028
                e["zoom"] = p
3✔
1029
        }
1030
}
1031

1032
func (a *auth) DiffWithRemote(remoteConfig v1API.AuthConfigResponse) ([]byte, error) {
26✔
1033
        copy := a.Clone()
26✔
1034
        // Convert the config values into easily comparable remoteConfig values
26✔
1035
        currentValue, err := ToTomlBytes(copy)
26✔
1036
        if err != nil {
26✔
1037
                return nil, err
×
1038
        }
×
1039
        copy.FromRemoteAuthConfig(remoteConfig)
26✔
1040
        remoteCompare, err := ToTomlBytes(copy)
26✔
1041
        if err != nil {
26✔
1042
                return nil, err
×
1043
        }
×
1044
        return diff.Diff("remote[auth]", remoteCompare, "local[auth]", currentValue), nil
26✔
1045
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc