Browse Source

Glue everything together

pull/98/head
Kegan Dougal 8 years ago
parent
commit
0fce8aea09
  1. 26
      src/github.com/matrix-org/go-neb/api/api.go
  2. 50
      src/github.com/matrix-org/go-neb/database/db.go
  3. 51
      src/github.com/matrix-org/go-neb/goneb.go
  4. 10
      src/github.com/matrix-org/go-neb/handlers.go

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

@ -6,12 +6,14 @@ import (
"net/url"
)
// ConfigureAuthRealmRequest is a request to /configureAuthRealm
type ConfigureAuthRealmRequest struct {
ID string
Type string
Config json.RawMessage
}
// ConfigureServiceRequest is a request to /configureService
type ConfigureServiceRequest struct {
ID string
Type string
@ -19,7 +21,8 @@ type ConfigureServiceRequest struct {
Config json.RawMessage
}
// A ClientConfig is the configuration for a matrix client for a bot to use.
// A ClientConfig is the configuration for a matrix client for a bot to use. It is
// a request to /configureClient
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
@ -45,6 +48,27 @@ type ConfigFile struct {
Sessions []SessionRequest
}
func (c *ConfigureServiceRequest) Check() error {
if c.ID == "" || c.Type == "" || c.UserID == "" || c.Config == nil {
return errors.New(`Must supply an "ID", a "Type", a "UserID" and a "Config"`)
}
return nil
}
func (c *ConfigureAuthRealmRequest) Check() error {
if c.ID == "" || c.Type == "" || c.Config == nil {
return errors.New(`Must supply a "ID", a "Type" and a "Config"`)
}
return nil
}
func (c *SessionRequest) Check() error {
if c.SessionID == "" || c.UserID == "" || c.RealmID == "" || c.Config == nil {
return errors.New(`Must supply a "SessionID", a "RealmID", a "UserID" and a "Config"`)
}
return nil
}
// Check that the client has the correct fields.
func (c *ClientConfig) Check() error {
if c.UserID == "" || c.HomeserverURL == "" || c.AccessToken == "" {

50
src/github.com/matrix-org/go-neb/database/db.go

@ -2,6 +2,8 @@ package database
import (
"database/sql"
"encoding/json"
"fmt"
"github.com/matrix-org/go-neb/api"
"github.com/matrix-org/go-neb/types"
"time"
@ -273,7 +275,55 @@ func (d *ServiceDB) StoreBotOptions(opts types.BotOptions) (oldOpts types.BotOpt
return
}
// InsertFromConfig inserts entries from the config file into the database. This only really
// makes sense for in-memory databases.
func (d *ServiceDB) InsertFromConfig(cfg *api.ConfigFile) error {
// Insert clients
for _, cli := range cfg.Clients {
if _, err := d.StoreMatrixClientConfig(cli); err != nil {
return err
}
}
// Keep a map of realms for inserting sessions
realms := map[string]types.AuthRealm{} // by realm ID
// Insert realms
for _, r := range cfg.Realms {
if err := r.Check(); err != nil {
return err
}
realm, err := types.CreateAuthRealm(r.ID, r.Type, r.Config)
if err != nil {
return err
}
if _, err := d.StoreAuthRealm(realm); err != nil {
return err
}
realms[realm.ID()] = realm
}
// Insert sessions
for _, s := range cfg.Sessions {
if err := s.Check(); err != nil {
return err
}
r := realms[s.RealmID]
if r == nil {
return fmt.Errorf("Session %s specifies an unknown realm ID %s", s.SessionID, s.RealmID)
}
session := r.AuthSession(s.SessionID, s.UserID, s.RealmID)
// dump the raw JSON config directly into the session. This is what
// selectAuthSessionByUserTxn does.
if err := json.Unmarshal(s.Config, session); err != nil {
return err
}
if _, err := d.StoreAuthSession(session); err != nil {
return err
}
}
// Do not insert services yet, they require more work to set up.
return nil
}

51
src/github.com/matrix-org/go-neb/goneb.go

@ -99,6 +99,33 @@ func convertKeysToStrings(iface interface{}) interface{} {
return iface // base type like string or number
}
func insertServicesFromConfig(clis *clients.Clients, services []api.ConfigureServiceRequest) error {
for i, s := range services {
if err := s.Check(); err != nil {
return fmt.Errorf("config: Service[%d] : %s", i, err)
}
service, err := types.CreateService(s.ID, s.Type, s.UserID, s.Config)
if err != nil {
return fmt.Errorf("config: Service[%d] : %s", i, err)
}
// Fetch the client for this service and register/poll
c, err := clis.Client(s.UserID)
if err != nil {
return fmt.Errorf("config: Service[%d] : %s", i, err)
}
if err = service.Register(nil, c); err != nil {
return fmt.Errorf("config: Service[%d] : %s", i, err)
}
if _, err := database.GetServiceDB().StoreService(service); err != nil {
return fmt.Errorf("config: Service[%d] : %s", i, err)
}
service.PostRegister(nil)
}
return nil
}
func main() {
bindAddress := os.Getenv("BIND_ADDRESS")
databaseType := os.Getenv("DATABASE_TYPE")
@ -136,14 +163,17 @@ func main() {
}
database.SetServiceDB(db)
if configYAML != "" {
var cfg *api.ConfigFile
if configYAML != "" {
if cfg, err = loadFromConfig(db, configYAML); err != nil {
log.WithError(err).WithField("config_file", configYAML).Panic("Failed to load config file")
}
if err := db.InsertFromConfig(cfg); err != nil {
log.WithError(err).Panic("Failed to persist config data into in-memory DB")
}
log.Info("Inserted ", len(cfg.Clients), " clients")
log.Info("Inserted ", len(cfg.Realms), " realms")
log.Info("Inserted ", len(cfg.Sessions), " sessions")
}
clients := clients.New(db)
@ -151,8 +181,21 @@ func main() {
log.WithError(err).Panic("Failed to start up clients")
}
// Handle non-admin paths for normal NEB functioning
http.Handle("/metrics", prometheus.Handler())
http.Handle("/test", prometheus.InstrumentHandler("test", server.MakeJSONAPI(&heartbeatHandler{})))
wh := &webhookHandler{db: db, clients: clients}
http.HandleFunc("/services/hooks/", prometheus.InstrumentHandlerFunc("webhookHandler", wh.handle))
rh := &realmRedirectHandler{db: db}
http.HandleFunc("/realms/redirects/", prometheus.InstrumentHandlerFunc("realmRedirectHandler", rh.handle))
if configYAML != "" {
if err := insertServicesFromConfig(clients, cfg.Services); err != nil {
log.WithError(err).Panic("Failed to insert services")
}
log.Info("Inserted ", len(cfg.Services), " services")
} else {
http.Handle("/admin/getService", prometheus.InstrumentHandler("getService", server.MakeJSONAPI(&getServiceHandler{db: db})))
http.Handle("/admin/getSession", prometheus.InstrumentHandler("getSession", server.MakeJSONAPI(&getSessionHandler{db: db})))
http.Handle("/admin/configureClient", prometheus.InstrumentHandler("configureClient", server.MakeJSONAPI(&configureClientHandler{db: db, clients: clients})))
@ -160,11 +203,7 @@ func main() {
http.Handle("/admin/configureAuthRealm", prometheus.InstrumentHandler("configureAuthRealm", server.MakeJSONAPI(&configureAuthRealmHandler{db: db})))
http.Handle("/admin/requestAuthSession", prometheus.InstrumentHandler("requestAuthSession", server.MakeJSONAPI(&requestAuthSessionHandler{db: db})))
http.Handle("/admin/removeAuthSession", prometheus.InstrumentHandler("removeAuthSession", server.MakeJSONAPI(&removeAuthSessionHandler{db: db})))
wh := &webhookHandler{db: db, clients: clients}
http.HandleFunc("/services/hooks/", prometheus.InstrumentHandlerFunc("webhookHandler", wh.handle))
rh := &realmRedirectHandler{db: db}
http.HandleFunc("/realms/redirects/", prometheus.InstrumentHandlerFunc("realmRedirectHandler", rh.handle))
}
polling.SetClients(clients)
if err := polling.Start(); err != nil {
log.WithError(err).Panic("Failed to start polling")

10
src/github.com/matrix-org/go-neb/handlers.go

@ -142,8 +142,8 @@ func (h *configureAuthRealmHandler) OnIncomingRequest(req *http.Request) (interf
return nil, &errors.HTTPError{err, "Error parsing request JSON", 400}
}
if body.ID == "" || body.Type == "" || body.Config == nil {
return nil, &errors.HTTPError{nil, `Must supply a "ID", a "Type" and a "Config"`, 400}
if err := body.Check(); err != nil {
return nil, &errors.HTTPError{err, err.Error(), 400}
}
realm, err := types.CreateAuthRealm(body.ID, body.Type, body.Config)
@ -336,10 +336,8 @@ func (s *configureServiceHandler) createService(req *http.Request) (types.Servic
return nil, &errors.HTTPError{err, "Error parsing request JSON", 400}
}
if body.ID == "" || body.Type == "" || body.UserID == "" || body.Config == nil {
return nil, &errors.HTTPError{
nil, `Must supply an "ID", a "Type", a "UserID" and a "Config"`, 400,
}
if err := body.Check(); err != nil {
return nil, &errors.HTTPError{err, err.Error(), 400}
}
service, err := types.CreateService(body.ID, body.Type, body.UserID, body.Config)

Loading…
Cancel
Save