hotfix(storage): JSON provider versioning safety
This commit is contained in:
@@ -1,21 +1,12 @@
|
|||||||
package storage
|
package storage
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strconv"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/qdm12/gluetun/internal/constants/providers"
|
"github.com/qdm12/gluetun/internal/constants/providers"
|
||||||
"github.com/qdm12/gluetun/internal/models"
|
"github.com/qdm12/gluetun/internal/models"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *Storage) logVersionDiff(provider string, hardcodedVersion, persistedVersion uint16) {
|
|
||||||
message := provider + " servers from file discarded because they have version " +
|
|
||||||
strconv.Itoa(int(persistedVersion)) +
|
|
||||||
" and hardcoded servers have version " +
|
|
||||||
strconv.Itoa(int(hardcodedVersion))
|
|
||||||
s.logger.Info(message)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Storage) logTimeDiff(provider string, persistedUnix, hardcodedUnix int64) {
|
func (s *Storage) logTimeDiff(provider string, persistedUnix, hardcodedUnix int64) {
|
||||||
diff := time.Unix(persistedUnix, 0).Sub(time.Unix(hardcodedUnix, 0))
|
diff := time.Unix(persistedUnix, 0).Sub(time.Unix(hardcodedUnix, 0))
|
||||||
if diff < 0 {
|
if diff < 0 {
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package storage
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
@@ -78,26 +77,37 @@ func (s *Storage) extractServersFromBytes(b []byte, hardcodedVersions map[string
|
|||||||
return servers, nil
|
return servers, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
|
||||||
errDecodeProvider = errors.New("cannot decode servers for provider")
|
|
||||||
)
|
|
||||||
|
|
||||||
func (s *Storage) readServers(provider string, hardcodedVersion uint16,
|
func (s *Storage) readServers(provider string, hardcodedVersion uint16,
|
||||||
rawMessage json.RawMessage, titleCaser cases.Caser) (servers models.Servers,
|
rawMessage json.RawMessage, titleCaser cases.Caser) (servers models.Servers,
|
||||||
versionsMatch bool, err error) {
|
versionsMatch bool, err error) {
|
||||||
provider = titleCaser.String(provider)
|
provider = titleCaser.String(provider)
|
||||||
|
|
||||||
var persistedServers models.Servers
|
var versionObject struct {
|
||||||
err = json.Unmarshal(rawMessage, &persistedServers)
|
Version uint16 `json:"version"`
|
||||||
if err != nil {
|
|
||||||
return servers, false, fmt.Errorf("%w: %s: %s", errDecodeProvider, provider, err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
versionsMatch = hardcodedVersion == persistedServers.Version
|
err = json.Unmarshal(rawMessage, &versionObject)
|
||||||
|
if err != nil {
|
||||||
|
return servers, false, fmt.Errorf("cannot decode servers version for provider %s: %w",
|
||||||
|
provider, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
persistedVersion := versionObject.Version
|
||||||
|
|
||||||
|
versionsMatch = hardcodedVersion == persistedVersion
|
||||||
if !versionsMatch {
|
if !versionsMatch {
|
||||||
s.logVersionDiff(provider, hardcodedVersion, persistedServers.Version)
|
s.logger.Info(fmt.Sprintf(
|
||||||
|
"%s servers from file discarded because they have "+
|
||||||
|
"version %d and hardcoded servers have version %d",
|
||||||
|
provider, persistedVersion, hardcodedVersion))
|
||||||
return servers, versionsMatch, nil
|
return servers, versionsMatch, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return persistedServers, versionsMatch, nil
|
err = json.Unmarshal(rawMessage, &servers)
|
||||||
|
if err != nil {
|
||||||
|
return servers, false, fmt.Errorf("cannot decode servers for provider %s: %w",
|
||||||
|
provider, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return servers, versionsMatch, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,8 +60,14 @@ func Test_extractServersFromBytes(t *testing.T) {
|
|||||||
"bad provider JSON": {
|
"bad provider JSON": {
|
||||||
b: []byte(`{"cyberghost": "garbage"}`),
|
b: []byte(`{"cyberghost": "garbage"}`),
|
||||||
hardcodedVersions: populateProviderToVersion(1, map[string]uint16{}),
|
hardcodedVersions: populateProviderToVersion(1, map[string]uint16{}),
|
||||||
errMessage: "cannot decode servers for provider: Cyberghost: " +
|
errMessage: "cannot decode servers version for provider Cyberghost: " +
|
||||||
"json: cannot unmarshal string into Go value of type models.Servers",
|
"json: cannot unmarshal string into Go value of type struct { Version uint16 \"json:\\\"version\\\"\" }",
|
||||||
|
},
|
||||||
|
"bad servers array JSON": {
|
||||||
|
b: []byte(`{"cyberghost": {"version": 1, "servers": "garbage"}}`),
|
||||||
|
hardcodedVersions: populateProviderToVersion(1, map[string]uint16{}),
|
||||||
|
errMessage: "cannot decode servers for provider Cyberghost: " +
|
||||||
|
"json: cannot unmarshal string into Go struct field Servers.servers of type []models.Server",
|
||||||
},
|
},
|
||||||
"absent provider keys": {
|
"absent provider keys": {
|
||||||
b: []byte(`{}`),
|
b: []byte(`{}`),
|
||||||
|
|||||||
Reference in New Issue
Block a user