Browse Source

Convert YAML to NEB types via roundabout methods

pull/98/head
Kegan Dougal 8 years ago
parent
commit
56e92a9632
  1. 30
      config.sample.yaml
  2. 6
      src/github.com/matrix-org/go-neb/api.go
  3. 67
      src/github.com/matrix-org/go-neb/config.go

30
config.sample.yaml

@ -18,27 +18,27 @@
# Delete or modify this list as appropriate.
# See the docs for /configureClient for the full list of options.
clients:
- user_id: "@goneb:localhost"
access_token: "MDASDASJDIASDJASDAFGFRGER"
homeserver_url: "http://localhost:8008"
sync: true
auto_join_rooms: true
display_name: "Go-NEB!"
- UserID: "@goneb:localhost"
AccessToken: "MDASDASJDIASDJASDAFGFRGER"
HomeserverURL: "http://localhost:8008"
Sync: true
AutoJoinRooms: true
DisplayName: "Go-NEB!"
- user_id: "@another_goneb:localhost"
access_token: "MDASDASJDIASDJASDAFGFRGER"
homeserver_url: "http://localhost:8008"
sync: false
auto_join_rooms: false
display_name: "Go-NEB!"
- UserID: "@another_goneb:localhost"
AccessToken: "MDASDASJDIASDJASDAFGFRGER"
HomeserverURL: "http://localhost:8008"
Sync: false
AutoJoinRooms: false
DisplayName: "Go-NEB!"
# The list of realms which Go-NEB is aware of.
# Delete or modify this list as appropriate.
# See the docs for /configureAuthRealm for the full list of options.
realms:
- id: "github_realm"
type: "github"
config:
- ID: "github_realm"
Type: "github"
Config:
ClientSecret: "YOUR_CLIENT_SECRET"
ClientID: "YOUR_CLIENT_ID"

6
src/github.com/matrix-org/go-neb/api.go

@ -133,9 +133,9 @@ type configureAuthRealmHandler struct {
}
type configureAuthRealmRequest struct {
ID string `yaml:"id"`
Type string `yaml:"type"`
Config json.RawMessage `yaml:"config"`
ID string
Type string
Config json.RawMessage
}
func (h *configureAuthRealmHandler) OnIncomingRequest(req *http.Request) (interface{}, *errors.HTTPError) {

67
src/github.com/matrix-org/go-neb/config.go

@ -1,6 +1,7 @@
package main
import (
"encoding/json"
"fmt"
log "github.com/Sirupsen/logrus"
"github.com/matrix-org/go-neb/database"
@ -10,29 +11,77 @@ import (
)
type configFile struct {
Clients []types.ClientConfig `yaml:"clients"`
Realms []configureAuthRealmRequest `yaml:"realms"`
Clients []types.ClientConfig
Realms []configureAuthRealmRequest
// Sessions []sessionConfig `yaml:"sessions"`
// Services []serviceConfig `yaml:"services"`
// Services []serviceConfig
}
func loadFromConfig(db *database.ServiceDB, configFilePath string) (*configFile, error) {
logger := log.WithField("config_file", configFilePath)
logger.Info("Loading from config file")
// ::Horrible hacks ahead::
// The config is represented as YAML, and we want to convert that into NEB types.
// However, NEB types make liberal use of json.RawMessage which the YAML parser
// doesn't like. We can't implement MarshalYAML/UnmarshalYAML as a custom type easily
// because YAML is insane and supports numbers as keys. The YAML parser therefore has the
// generic form of map[interface{}]interface{} - but the JSON parser doesn't know
// how to parse that.
//
// The hack that follows gets around this by type asserting all parsed YAML keys as
// strings then re-encoding/decoding as JSON. That is:
// YAML bytes -> map[interface]interface -> map[string]interface -> JSON bytes -> NEB types
// Convert to YAML bytes
contents, err := ioutil.ReadFile(configFilePath)
if err != nil {
return nil, err
}
var cfg configFile
// Convert to map[interface]interface
var cfg map[interface{}]interface{}
if err = yaml.Unmarshal(contents, &cfg); err != nil {
return nil, err
return nil, fmt.Errorf("Failed to unmarshal YAML: %s", err)
}
// Convert to map[string]interface
dict := convertKeysToStrings(cfg)
// Convert to JSON bytes
b, err := json.Marshal(dict)
if err != nil {
return nil, fmt.Errorf("Failed to marshal config as JSON: %s", err)
}
// Finally, Convert to NEB types
var c configFile
if err := json.Unmarshal(b, &c); err != nil {
return nil, fmt.Errorf("Failed to convert to config file: %s", err)
}
log.Print(c.Realms)
// sanity check (at least 1 client and 1 service)
if len(cfg.Clients) == 0 {
if len(c.Clients) == 0 {
return nil, fmt.Errorf("At least 1 client and 1 service must be specified")
}
return &cfg, nil
return &c, nil
}
func convertKeysToStrings(iface interface{}) interface{} {
obj, isObj := iface.(map[interface{}]interface{})
if isObj {
strObj := make(map[string]interface{})
for k, v := range obj {
strObj[k.(string)] = convertKeysToStrings(v) // handle nested objects
}
return strObj
}
arr, isArr := iface.([]interface{})
if isArr {
for i := range arr {
arr[i] = convertKeysToStrings(arr[i]) // handle nested objects
}
return arr
}
return iface // base type like string or number
}
Loading…
Cancel
Save