mirror of https://github.com/matrix-org/go-neb.git
Browse Source
Add 'api' package and move HTTP API requests there
Add 'api' package and move HTTP API requests there
This will make docs easier in addition to allowing the 'database' package not circular-dep.pull/98/head
Kegan Dougal
8 years ago
8 changed files with 160 additions and 139 deletions
-
57src/github.com/matrix-org/go-neb/api/api.go
-
9src/github.com/matrix-org/go-neb/clients/clients.go
-
87src/github.com/matrix-org/go-neb/config.go
-
11src/github.com/matrix-org/go-neb/database/db.go
-
11src/github.com/matrix-org/go-neb/database/schema.go
-
80src/github.com/matrix-org/go-neb/goneb.go
-
22src/github.com/matrix-org/go-neb/handlers.go
-
22src/github.com/matrix-org/go-neb/types/types.go
@ -0,0 +1,57 @@ |
|||
package api |
|||
|
|||
import ( |
|||
"encoding/json" |
|||
"errors" |
|||
"net/url" |
|||
) |
|||
|
|||
type ConfigureAuthRealmRequest struct { |
|||
ID string |
|||
Type string |
|||
Config json.RawMessage |
|||
} |
|||
|
|||
type ConfigureServiceRequest struct { |
|||
ID string |
|||
Type string |
|||
UserID string |
|||
Config json.RawMessage |
|||
} |
|||
|
|||
// A ClientConfig is the configuration for a matrix client for a bot to use.
|
|||
type ClientConfig struct { |
|||
UserID string // The matrix UserId to connect with.
|
|||
HomeserverURL string // A URL with the host and port of the matrix server. E.g. https://matrix.org:8448
|
|||
AccessToken string // The matrix access token to authenticate the requests with.
|
|||
Sync bool // True to start a sync stream for this user
|
|||
AutoJoinRooms bool // True to automatically join all rooms for this user
|
|||
DisplayName string // The display name to set for the matrix client
|
|||
} |
|||
|
|||
// SessionRequest are usually multi-stage things so this type only exists for the config form
|
|||
type SessionRequest struct { |
|||
SessionID string |
|||
RealmID string |
|||
UserID string |
|||
Config json.RawMessage |
|||
} |
|||
|
|||
// ConfigFile represents config.sample.yaml
|
|||
type ConfigFile struct { |
|||
Clients []ClientConfig |
|||
Realms []ConfigureAuthRealmRequest |
|||
Services []ConfigureServiceRequest |
|||
Sessions []SessionRequest |
|||
} |
|||
|
|||
// Check that the client has the correct fields.
|
|||
func (c *ClientConfig) Check() error { |
|||
if c.UserID == "" || c.HomeserverURL == "" || c.AccessToken == "" { |
|||
return errors.New(`Must supply a "UserID", a "HomeserverURL", and an "AccessToken"`) |
|||
} |
|||
if _, err := url.Parse(c.HomeserverURL); err != nil { |
|||
return err |
|||
} |
|||
return nil |
|||
} |
@ -1,87 +0,0 @@ |
|||
package main |
|||
|
|||
import ( |
|||
"encoding/json" |
|||
"fmt" |
|||
log "github.com/Sirupsen/logrus" |
|||
"github.com/matrix-org/go-neb/database" |
|||
"github.com/matrix-org/go-neb/types" |
|||
"gopkg.in/yaml.v2" |
|||
"io/ioutil" |
|||
) |
|||
|
|||
type configFile struct { |
|||
Clients []types.ClientConfig |
|||
Realms []configureAuthRealmRequest |
|||
// Sessions []sessionConfig `yaml:"sessions"`
|
|||
// Services []serviceConfig
|
|||
} |
|||
|
|||
func loadFromConfig(db *database.ServiceDB, configFilePath string) (*configFile, error) { |
|||
// ::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 |
|||
} |
|||
|
|||
// Convert to map[interface]interface
|
|||
var cfg map[interface{}]interface{} |
|||
if err = yaml.Unmarshal(contents, &cfg); err != nil { |
|||
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(c.Clients) == 0 { |
|||
return nil, fmt.Errorf("At least 1 client and 1 service must be specified") |
|||
} |
|||
|
|||
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
|
|||
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue