diff --git a/config.sample.yaml b/config.sample.yaml index b34bb5a..04311bd 100644 --- a/config.sample.yaml +++ b/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" diff --git a/src/github.com/matrix-org/go-neb/api.go b/src/github.com/matrix-org/go-neb/api.go index 0cde964..37f13c9 100644 --- a/src/github.com/matrix-org/go-neb/api.go +++ b/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) { diff --git a/src/github.com/matrix-org/go-neb/config.go b/src/github.com/matrix-org/go-neb/config.go index cfb8554..f63bae0 100644 --- a/src/github.com/matrix-org/go-neb/config.go +++ b/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 }