[#7815] fixed oauth2 providers config merge

This commit is contained in:
Gani Georgiev committed 2026-08-24 17:07:51 +03:00
1 parent 04ed202c78
commit d763d3dff1
4 files changed
+170 -2

No files matched your search

+63
View File
@@ -1,6 +1,9 @@
package core
import (
"encoding/json/v2"
"errors"
"slices"
"strconv"
"strings"
"time"
@@ -409,6 +412,66 @@ type OAuth2Config struct {
Enabled bool `form:"enabled" json:"enabled"`
}
// UnmarshalJSON implements the [json.Unmarshaler] interface.
//
// The main difference from the standrad unmarshalization is that
// instead of replacing the entire providers config slice, we ensure
// that parially submitted provider data (e.g. without clientSecret)
// is merged on per config level based on the provider name
// (https://github.com/pocketbase/pocketbase/issues/7815).
func (c *OAuth2Config) UnmarshalJSON(b []byte) error {
originalProviders := slices.Clone(c.Providers)
type alias OAuth2Config
err := json.Unmarshal(b, (*alias)(c))
if err != nil {
return err
}
if len(c.Providers) == 0 {
return nil
}
// unmarshal again but this time into a plain array of objects
// so that we have only the submitted fields and no zero defaults
plain := struct {
Providers []map[string]any `json:"providers"`
}{}
err = json.Unmarshal(b, &plain)
if err != nil {
return err
}
if len(c.Providers) != len(plain.Providers) {
return errors.New("the length of the plain unmarshalized providers and the ones from the config doesn't match")
}
ProvidersMergeLoop:
for i, plain := range plain.Providers {
for _, original := range originalProviders {
if original.Name == plain["name"] {
raw, err := json.Marshal(plain)
if err != nil {
return err
}
// unmarshal the new plain data on top of the original one
err = json.Unmarshal(raw, &original)
if err != nil {
return err
}
// reassigne to the updated original
c.Providers[i] = original
continue ProvidersMergeLoop
}
}
}
return nil
}
// GetProviderConfig returns the first OAuth2ProviderConfig that matches the specified name.
//
// Returns false and zero config if no such provider is available in c.Providers.