Enable persistent request variables

It is now possible to set a variable on a connection, and use that variable in multiple subsequent queries. This ensures that websockets can make use of state variables for detecting logged-in, and non-logged-in clients.
This commit is contained in:
Tobie Morgan Hitchcock 2018-02-12 21:53:48 +00:00
parent 15e9f77434
commit e073bf2775
5 changed files with 38 additions and 4 deletions

View file

@ -207,6 +207,13 @@ func Process(fib *fibre.Context, ast *sql.Query, vars map[string]interface{}) (o
ctx = context.WithValue(ctx, ctxKeyId, id) ctx = context.WithValue(ctx, ctxKeyId, id)
// Assign any global connection variables
// to the context so that we can retrieve
// the variables from within any queries.
keep := fib.Get(varKeyKeep).(*data.Doc)
ctx = context.WithValue(ctx, ctxKeyKeep, keep)
// Assign the authentication data to the // Assign the authentication data to the
// context so that we can log the auth kind // context so that we can log the auth kind
// and the auth variable data to the request. // and the auth variable data to the request.

View file

@ -40,7 +40,9 @@ func setupDB() {
func setupKV() *fibre.Context { func setupKV() *fibre.Context {
auth := &cnf.Auth{} keep := new(data.Doc)
auth := new(cnf.Auth)
auth.Kind = cnf.AuthKV auth.Kind = cnf.AuthKV
auth.Possible.NS = "*" auth.Possible.NS = "*"
auth.Selected.NS = "*" auth.Selected.NS = "*"
@ -52,6 +54,7 @@ func setupKV() *fibre.Context {
ctx := fibre.NewContext(req, res, nil) ctx := fibre.NewContext(req, res, nil)
ctx.Set("auth", auth) ctx.Set("auth", auth)
ctx.Set("keep", keep)
return ctx return ctx
@ -59,7 +62,9 @@ func setupKV() *fibre.Context {
func setupSC() *fibre.Context { func setupSC() *fibre.Context {
auth := &cnf.Auth{} keep := new(data.Doc)
auth := new(cnf.Auth)
auth.Kind = cnf.AuthSC auth.Kind = cnf.AuthSC
auth.Possible.NS = "*" auth.Possible.NS = "*"
auth.Selected.NS = "*" auth.Selected.NS = "*"
@ -71,6 +76,7 @@ func setupSC() *fibre.Context {
ctx := fibre.NewContext(req, res, nil) ctx := fibre.NewContext(req, res, nil)
ctx.Set("auth", auth) ctx.Set("auth", auth)
ctx.Set("keep", keep)
return ctx return ctx

View file

@ -41,6 +41,7 @@ const (
ctxKeyVars = "vars" ctxKeyVars = "vars"
ctxKeySubs = "subs" ctxKeySubs = "subs"
ctxKeySpec = "spec" ctxKeySpec = "spec"
ctxKeyKeep = "keep"
ctxKeyAuth = "auth" ctxKeyAuth = "auth"
ctxKeyKind = "kind" ctxKeyKind = "kind"
ctxKeyScope = "scope" ctxKeyScope = "scope"
@ -50,6 +51,7 @@ const (
varKeyId = "id" varKeyId = "id"
varKeyIp = "ip" varKeyIp = "ip"
varKeyAuth = "auth" varKeyAuth = "auth"
varKeyKeep = "keep"
varKeyThis = "this" varKeyThis = "this"
varKeyScope = "scope" varKeyScope = "scope"
varKeyValue = "value" varKeyValue = "value"
@ -65,5 +67,5 @@ var (
queryNotExecuted = errors.New("Query not executed") queryNotExecuted = errors.New("Query not executed")
queryIdentFailed = errors.New("Found ident but no doc available") queryIdentFailed = errors.New("Found ident but no doc available")
featureNotImplemented = errors.New("Feature is not yet implemented") featureNotImplemented = errors.New("Feature is not yet implemented")
paramSearchKeys = []string{ctxKeySpec, ctxKeySubs, ctxKeyVars} paramSearchKeys = []string{ctxKeySpec, ctxKeySubs, ctxKeyVars, ctxKeyKeep}
) )

View file

@ -31,6 +31,8 @@ import (
"github.com/abcum/surreal/sql" "github.com/abcum/surreal/sql"
"github.com/dgrijalva/jwt-go" "github.com/dgrijalva/jwt-go"
"github.com/gorilla/websocket" "github.com/gorilla/websocket"
"github.com/abcum/surreal/util/data"
) )
var ignore = func() error { var ignore = func() error {
@ -47,6 +49,7 @@ const (
varKeyTb = "TB" varKeyTb = "TB"
varKeyId = "ID" varKeyId = "ID"
varKeyAuth = "auth" varKeyAuth = "auth"
varKeyKeep = "keep"
varKeyUser = "user" varKeyUser = "user"
varKeyPass = "pass" varKeyPass = "pass"
varKeyOrigin = "origin" varKeyOrigin = "origin"
@ -65,7 +68,18 @@ func auth() fibre.MiddlewareFunc {
return func(h fibre.HandlerFunc) fibre.HandlerFunc { return func(h fibre.HandlerFunc) fibre.HandlerFunc {
return func(c *fibre.Context) (err error) { return func(c *fibre.Context) (err error) {
auth := &cnf.Auth{} // Initialise any session level variables
// which will be valid across all requests
// which are made over this connection.
vars := new(data.Doc)
c.Set(varKeyKeep, vars)
// Initialise the connection authentication
// information which will store whether the
// connection has authenticated or not.
auth := new(cnf.Auth)
c.Set(varKeyAuth, auth) c.Set(varKeyAuth, auth)
// Start off with an authentication level // Start off with an authentication level

View file

@ -19,6 +19,7 @@ import (
"github.com/abcum/surreal/cnf" "github.com/abcum/surreal/cnf"
"github.com/abcum/surreal/db" "github.com/abcum/surreal/db"
"github.com/abcum/surreal/sql" "github.com/abcum/surreal/sql"
"github.com/abcum/surreal/util/data"
"github.com/abcum/surreal/util/rand" "github.com/abcum/surreal/util/rand"
) )
@ -36,6 +37,10 @@ func (r *rpc) Auth(c *fibre.Context, auth string) (interface{}, error) {
return c.Get("auth").(*cnf.Auth).Data, checkBearer(c, auth, ignore) return c.Get("auth").(*cnf.Auth).Data, checkBearer(c, auth, ignore)
} }
func (r *rpc) Let(c *fibre.Context, key string, val interface{}) (interface{}, error) {
return c.Get("keep").(*data.Doc).Set(val, key)
}
func (r *rpc) Query(c *fibre.Context, sql string, vars map[string]interface{}) (interface{}, error) { func (r *rpc) Query(c *fibre.Context, sql string, vars map[string]interface{}) (interface{}, error) {
return db.Execute(c, sql, vars) return db.Execute(c, sql, vars)
} }