package database import ( "crypto/rsa" "git.xeserv.us/xena/route/routerpc" "git.xeserv.us/xena/route/utils" r "github.com/GoRethink/gorethink" ) // DB is the high level wrapper to the datastore. type DB struct { s *r.Session } // New takes a rethinkdb host and databasea and sets up a connection. func New(host, database string) (*DB, error) { session, err := r.Connect(r.ConnectOpts{ Address: host, Database: database, }) if err != nil { return nil, err } db := &DB{ s: session, } return db, nil } var tables = []string{ "certs", "routes", } // Route is a single route object serialized to rethinkdb. type Route struct { ID string `gorethink:"id,omitempty"` Hostname string `gorethink:"hostname"` OnionHostname string `gorethink:"onionhostname"` Token string `gorethink:"token"` OnionKey []byte `gorethink:"onionKey"` // PEM-encoded } // SaveRoute adds the route to the database. func (db *DB) SaveRoute(resp *routerpc.AddHostResponse) error { bytes := utils.RSAPrivateKeyToPem(resp.PrivKey.(*rsa.PrivateKey)) rt := &Route{ Hostname: resp.Hostname, OnionHostname: resp.OnionHostname, Token: resp.Token, OnionKey: bytes, } // TODO: check if OnionHostname or Hostname actually exists in // the database. RethinkDB doesn't support unique secondary indexes. _, err := r.Table("routes").Insert(rt).RunWrite(db.s) if err != nil { return err } return nil } func (db *DB) GetRouteForHost(name string) (*Route, error) { rows, err := r.Table("routes").Filter(map[string]interface{}{"hostname": name}).Run(db.s) if err != nil { return nil, err } result := &Route{} err = rows.One(result) if err != nil { return nil, err } return result, nil } // GetAllRoutes fetches all of the route entries from the database // and returns them. This is intended for the startup process or // admin tooling. func (db *DB) GetAllRoutes() ([]Route, error) { rows, err := r.Table("routes").Run(db.s) if err != nil { return nil, err } var routes []Route err = rows.All(&routes) if err != nil { return nil, err } return routes, nil }