-
-
Notifications
You must be signed in to change notification settings - Fork 3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix(config): support dynamic map keys with dots #8096
base: master
Are you sure you want to change the base?
Conversation
This adds support for alternative map notation which has to be used when the map key is a string with a dot, for example: Gateway.PublicGateways["gw.example.com"].UseSubdomains Pinning.RemoteServices["pins.example.org"].Policies.MFS.Enable Context: ipfs/ipfs-webui#1770
repo/common/common.go
Outdated
// Normalization for supporting arbitrary dynamic keys with dots: | ||
// Gateway.PublicGateways["gw.example.com"].UseSubdomains | ||
// Pinning.RemoteServices["pins.example.org"].Policies.MFS.Enable | ||
func keyToLookupData(key string) (normalizedKey string, dynamicKeys map[string]string) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Putting this here isn't sufficient since we need to deal with things like https://github.com/ipfs/go-ipfs/blob/eea198f0811f50ab14c4f713de07ce93dffec9af/core/commands/config.go#L90 that exist above this level.
We'll either need to export some of this behavior from here, or move the other behavior here and export it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sharness tests fail on CI but pass locally, I'm suspecting different versions of jq
, needs another look.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I made our CI use the latest jq
instead of old 1.5, and it is green now.
This adds fallback to new notation from ipfs/kubo#8096 We default to old one because new one matters only when '.' is present in service name
// Gateway.PublicGateways["gw.example.com"].UseSubdomains | ||
// Pinning.RemoteServices["pins.example.org"].Policies.MFS.Enable |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this notation standard/used in other software or are we just making this up this form of escaping? Either way we'd need to document this in the config
command.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is how keys in JSON objects are addressed on the web, and since we use JSON for config anyway, means we don't invent anything new, but follow existing JSON convention.:
( {"foo.bar":{"a": "buz"}} )["foo.bar"].a → "buz"
I've added note about this notation to ipfs config --help
in 0a2336e
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The return value is not documented accurately on a public method. What about dynamicKeys?
Thanks for tackling this, a little weird that this hasn't come up previously. I guess it means people have mostly been manipulating the raw JSON regarding config sections like for Gateways. |
This ensures we dont leak access tokens of remote pinning services.
This adds quick test to ensure secrets are not leaked when alternative JSON notation is used for accessing service details when name includes a dot.
6a409fb
to
6d295eb
Compare
f713b01
to
8eb4f00
Compare
56a34b5
to
c772215
Compare
Making jq verbose so we see what failed + using updated version for sharness.
c772215
to
36b62c1
Compare
This adds fallback to new notation from ipfs/kubo#8096 We default to old one because new one matters only when '.' is present in the service name
* fix: work around dot in pin service name This is a temporary workaround that maintains most of the functionality and works with go-ipfs 0.8.0 Context: #1770 * refactor: support Pinning.RemoteServices["name"] This adds fallback to new notation from ipfs/kubo#8096 We default to old one because new one matters only when '.' is present in the service name
@@ -157,7 +163,8 @@ Set the value of the 'Datastore.Path' key: | |||
// matchesGlobPrefix("foo.bar.baz", []string{"*", "bar"}) returns true | |||
// matchesGlobPrefix("foo.bar", []string{"baz", "*"}) returns false | |||
func matchesGlobPrefix(key string, glob []string) bool { | |||
k := strings.Split(key, ".") | |||
normalizedKey, _ := ConfigKeyToLookupData(key) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
strings.EqualFold (below) no longer works, since now it is applied to a rewritten key which has UUIDs.
) | ||
|
||
// Find dynamic map key names passed with Parent["foo"] notation | ||
var bracketsRe = regexp.MustCompile(`\["([^\["\]]*)"\]`) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This regular expression does not support escape sequences. I wouldn't advice writing your own quoted string parser. It's hard. I would advice using a JS parser library for parsing the ENTIRE glob, e.g. https://pkg.go.dev/github.com/robertkrimen/otto/parser, and then work with the AST.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alternatively, you can use the Go language parser for the glob. It has a different set of escape sequences than JS, but is still better than rolling your own.
// Gateway.PublicGateways["gw.example.com"].UseSubdomains | ||
// Pinning.RemoteServices["pins.example.org"].Policies.MFS.Enable |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The return value is not documented accurately on a public method. What about dynamicKeys?
mapKey = strings.TrimSuffix(mapKey, `"]`) | ||
placeholder := uuid.New().String() | ||
dynamicKeys[placeholder] = mapKey | ||
normalizedKey = strings.Replace(normalizedKey, mapKeySegment, fmt.Sprintf(".%s", placeholder), 1) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will convert a glob string like: ["abc"]["def"] into .UUID1.UUID2
Is this your intention? Specifically, I am referring to the first key.
func MapGetKV(v map[string]interface{}, key string) (interface{}, error) { | ||
var ok bool | ||
var mcursor map[string]interface{} | ||
var cursor interface{} = v | ||
|
||
parts := strings.Split(key, ".") | ||
normalizedKey, dynamicKeys := ConfigKeyToLookupData(key) | ||
parts := strings.Split(normalizedKey, ".") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fails of normalizedKey starts with a ".", which technically it can.
Note for myself or someone else who will pick this up again at some point:
|
This PR adds support for alternative map notation in
ipfs config
command,which enables access to values behind a map key that includes a dot, for example:
ipfs config 'Gateway.PublicGateways["dweb.link"].UseSubdomains'
ipfs config 'Pinning.RemoteServices["nft.storage"].Policies'
Context: ipfs/ipfs-webui#1770 (cc @alanshaw @aschmahmann)
Included sharness test + confirmed accessing fields like this works over HTTP API with regular curl as well: