diff --git a/server_structs/director.go b/server_structs/director.go index cdbd60c82..0ccc6bdf2 100644 --- a/server_structs/director.go +++ b/server_structs/director.go @@ -51,13 +51,28 @@ type ( CredentialIssuer url.URL `json:"issuer"` } - // Note that the json are kept in uppercase for backward compatibility Capabilities struct { - PublicReads bool `json:"PublicRead"` - Reads bool `json:"Read"` - Writes bool `json:"Write"` - Listings bool `json:"Listing"` - DirectReads bool `json:"FallBackRead"` + PublicReads bool `json:"PublicReads"` + Reads bool `json:"Reads"` + Writes bool `json:"Writes"` + Listings bool `json:"Listings"` + DirectReads bool `json:"DirectReads"` + } + + // Supports both old and new JSON field names + capabilitiesCompat struct { + // New field names + PublicReads bool `json:"PublicReads"` + Reads bool `json:"Reads"` + Writes bool `json:"Writes"` + Listings bool `json:"Listings"` + DirectReads bool `json:"DirectReads"` + // Old field names (for backward compatibility) + PublicRead bool `json:"PublicRead"` + Read bool `json:"Read"` + Write bool `json:"Write"` + Listing bool `json:"Listing"` + FallBackRead bool `json:"FallBackRead"` } NamespaceAdV2 struct { @@ -322,6 +337,24 @@ const ( // We chose -1 to avoid the default value (0) of the int64 type const IndefiniteEndTime int64 = -1 +// Custom JSON unmarshalling for Capabilities to support backward compatibility. +// Old field names from origins/caches running Pelican earlier than v7.22.0 will be converted to the new field names. +func (c *Capabilities) UnmarshalJSON(data []byte) error { + var compat capabilitiesCompat + if err := json.Unmarshal(data, &compat); err != nil { + return err + } + + // Use new field names if set, otherwise fall back to old field names + c.PublicReads = compat.PublicReads || compat.PublicRead + c.Reads = compat.Reads || compat.Read + c.Writes = compat.Writes || compat.Write + c.Listings = compat.Listings || compat.Listing + c.DirectReads = compat.DirectReads || compat.FallBackRead + + return nil +} + func (x XPelNs) GetName() string { return "X-Pelican-Namespace" } diff --git a/web_ui/frontend/components/CapabilitiesDisplay.tsx b/web_ui/frontend/components/CapabilitiesDisplay.tsx index a575ab632..a36aeb6b1 100644 --- a/web_ui/frontend/components/CapabilitiesDisplay.tsx +++ b/web_ui/frontend/components/CapabilitiesDisplay.tsx @@ -54,9 +54,7 @@ export const CapabilitiesChip = ({ overflow: 'hidden', }} > - - {CAPABILITY_LABEL_MAP[name] || name} - + {name} {value ? : } @@ -74,11 +72,3 @@ export const CapabilityChipStyle = { border: '1px 1px solid black', backgroundColor: green[300], }; - -const CAPABILITY_LABEL_MAP: Record = { - PublicRead: 'PublicReads', - Read: 'Reads', - Write: 'Writes', - Listing: 'Listings', - FallBackRead: 'DirectReads', -}; diff --git a/web_ui/frontend/types.ts b/web_ui/frontend/types.ts index f8d093e45..294b82f09 100644 --- a/web_ui/frontend/types.ts +++ b/web_ui/frontend/types.ts @@ -1,9 +1,9 @@ export interface Capabilities { - PublicRead: boolean; - Read: boolean; - Write: boolean; - Listing: boolean; - FallBackRead: boolean; + PublicReads: boolean; + Reads: boolean; + Writes: boolean; + Listings: boolean; + DirectReads: boolean; } export interface TokenGeneration {