From 6954850ffb4b9024e26f3324cc8d052625c2e53e Mon Sep 17 00:00:00 2001 From: stremovsky Date: Mon, 16 Dec 2019 22:15:22 +0200 Subject: [PATCH] add session API --- create-test-user.sh | 19 ++++++++++++++++++- src/bunker.go | 3 +++ src/sessions_api.go | 21 +++++++++++++-------- src/sessions_db.go | 33 ++++++++++++++++++--------------- 4 files changed, 52 insertions(+), 24 deletions(-) diff --git a/create-test-user.sh b/create-test-user.sh index 29a83c0..2d930b3 100755 --- a/create-test-user.sh +++ b/create-test-user.sh @@ -1,5 +1,4 @@ #!/bin/sh -set -x DATABUNKER_APIKEY=$1 if [ -z $DATABUNKER_APIKEY ]; then @@ -61,3 +60,21 @@ echo "View all user consents: $RESULT" RESULT=`curl -s http://localhost:3000/v1/consents/send-sms \ -H "X-Bunker-Token: "$DATABUNKER_APIKEY -H "Content-Type: application/json"` echo "View all users with send-sms consent on: $RESULT" + +RESULT=`curl -s http://localhost:3000/v1/session/token/$TOKEN -XPOST \ + -H "X-Bunker-Token: "$DATABUNKER_APIKEY -H "Content-Type: application/json" \ + -d '{"clientip":"1.1.1.1","x-forwarded-for":"2.2.2.2"}'` +echo "Create session 1: $RESULT" + +RESULT=`curl -s http://localhost:3000/v1/session/email/test@paranoidguy.com -XPOST \ + -H "X-Bunker-Token: "$DATABUNKER_APIKEY -H "Content-Type: application/json" \ + -d '{"clientip":"1.1.1.1","x-forwarded-for":"2.2.2.2","info":"email"}'` +echo "Create session 1: $RESULT" + +RESULT=`curl -s http://localhost:3000/v1/session/session/7a77ffad-2010-4e47-abbe-bcd04509f784 \ + -H "X-Bunker-Token: "$DATABUNKER_APIKEY -H "Content-Type: application/json"` +echo "Get session: $RESULT" + +RESULT=`curl -s http://localhost:3000/v1/session/phone/4444 \ + -H "X-Bunker-Token: "$DATABUNKER_APIKEY -H "Content-Type: application/json"` +echo "Get sessions: $RESULT" diff --git a/src/bunker.go b/src/bunker.go index 602acf1..5d4694a 100644 --- a/src/bunker.go +++ b/src/bunker.go @@ -148,6 +148,9 @@ func (e mainEnv) setupRouter() *httprouter.Router { router.GET("/v1/userapp/token/:token", e.userappList) router.GET("/v1/userapps", e.appList) + router.POST("/v1/session/:mode/:address", e.newSession) + router.GET("/v1/session/:mode/:address", e.getUserSessions) + router.GET("/v1/metrics", e.metrics) router.GET("/v1/audit/list/:token", e.getAuditEvents) diff --git a/src/sessions_api.go b/src/sessions_api.go index cb4fbe0..85079e2 100644 --- a/src/sessions_api.go +++ b/src/sessions_api.go @@ -5,6 +5,7 @@ import ( "fmt" "net/http" "reflect" + "strings" "github.com/julienschmidt/httprouter" ) @@ -40,7 +41,7 @@ func (e mainEnv) newSession(w http.ResponseWriter, r *http.Request, ps httproute return } } - expiration := "" + expiration := "1d" records, err := getJSONPostData(r) if err != nil { returnError(w, r, "failed to decode request body", 405, err, event) @@ -77,6 +78,10 @@ func (e mainEnv) newSession(w http.ResponseWriter, r *http.Request, ps httproute func (e mainEnv) getUserSessions(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { address := ps.ByName("address") mode := ps.ByName("mode") + if mode == "session" { + e.getSession(w, r, address) + return + } event := audit("get all user sessions", address, mode, address) defer func() { event.submit(e.db) }() @@ -110,29 +115,29 @@ func (e mainEnv) getUserSessions(w http.ResponseWriter, r *http.Request, ps http returnError(w, r, "internal error", 405, err, event) return } - resultJSON, err := json.Marshal(records) + data := strings.Join(records, ",") w.Header().Set("Content-Type", "application/json; charset=utf-8") w.WriteHeader(200) - fmt.Fprintf(w, `{"status":"ok","count":"%d","rows":"%"}`, count, resultJSON) + fmt.Fprintf(w, `{"status":"ok","count":"%d","rows":%s}`, count, data) return } -func (e mainEnv) getSession(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { - session := ps.ByName("session") +func (e mainEnv) getSession(w http.ResponseWriter, r *http.Request, session string) { event := audit("get session", session, "session", session) defer func() { event.submit(e.db) }() if e.enforceAuth(w, r, event) == false { return } - record, userTOKEN, err := e.db.getUserSession(session) + when, record, userTOKEN, err := e.db.getUserSession(session) if err != nil { - returnError(w, r, "internal error", 405, err, event) + fmt.Printf("error: %s\n", err) + returnError(w, r, err.Error(), 405, err, event) return } event.Record = userTOKEN w.Header().Set("Content-Type", "application/json; charset=utf-8") w.WriteHeader(200) - fmt.Fprintf(w, `{"status":"ok","session":"%s","data":"%"}`, session, record) + fmt.Fprintf(w, `{"status":"ok","session":"%s","when":%d,"data":%s}`, session, when, record) return } diff --git a/src/sessions_db.go b/src/sessions_db.go index 1e50494..f409cbb 100644 --- a/src/sessions_db.go +++ b/src/sessions_db.go @@ -3,6 +3,7 @@ package main import ( "encoding/base64" "errors" + "fmt" "time" uuid "github.com/hashicorp/go-uuid" @@ -10,8 +11,8 @@ import ( ) type sessionEvent struct { - When int32 - Data string + When int32 `json:"when"` + Data string `json:"data"` } func (dbobj dbcon) createSessionRecord(userTOKEN string, expiration string, data []byte) (string, error) { @@ -27,14 +28,14 @@ func (dbobj dbcon) createSessionRecord(userTOKEN string, expiration string, data if err != nil { return "", err } - tokenUUID, err := uuid.GenerateUUID() + sessionUUID, err := uuid.GenerateUUID() if err != nil { return "", err } bdoc := bson.M{} now := int32(time.Now().Unix()) bdoc["token"] = userTOKEN - bdoc["session"] = tokenUUID + bdoc["session"] = sessionUUID bdoc["endtime"] = endtime bdoc["when"] = now bdoc["data"] = encodedStr @@ -42,32 +43,33 @@ func (dbobj dbcon) createSessionRecord(userTOKEN string, expiration string, data if err != nil { return "", err } - return tokenUUID, nil + return sessionUUID, nil } -func (dbobj dbcon) getUserSession(sessionUUID string) ([]byte, string, error) { +func (dbobj dbcon) getUserSession(sessionUUID string) (int32, []byte, string, error) { record, err := dbobj.getRecord(TblName.Sessions, "session", sessionUUID) if err != nil { - return nil, "", err + return 0, nil, "", err } if record == nil { - return nil, "", errors.New("not found") + return 0, nil, "", errors.New("not found") } // check expiration now := int32(time.Now().Unix()) if now > record["endtime"].(int32) { - return nil, "", errors.New("session expired") + return 0, nil, "", errors.New("session expired") } + when := record["when"].(int32) userTOKEN := record["token"].(string) encData0 := record["data"].(string) decrypted, err := dbobj.userDecrypt(userTOKEN, encData0) if err != nil { - return nil, "", err + return 0, nil, "", err } - return decrypted, userTOKEN, err + return when, decrypted, userTOKEN, err } -func (dbobj dbcon) getUserSessionByToken(userTOKEN string) ([]*sessionEvent, int64, error) { +func (dbobj dbcon) getUserSessionByToken(userTOKEN string) ([]string, int64, error) { userBson, err := dbobj.lookupUserRecord(userTOKEN) if userBson == nil || err != nil { @@ -90,13 +92,14 @@ func (dbobj dbcon) getUserSessionByToken(userTOKEN string) ([]*sessionEvent, int return nil, 0, err } - var results []*sessionEvent + var results []string for _, element := range records { + when := element["when"].(int32) encData0 := element["data"].(string) encData, _ := base64.StdEncoding.DecodeString(encData0) decrypted, _ := decrypt(dbobj.masterKey, recordKey, encData) - sEvent := sessionEvent{0, string(decrypted)} - results = append(results, &sEvent) + sEvent := fmt.Sprintf(`{"when":%d,"data":%s}`, when, string(decrypted)) + results = append(results, sEvent) } return results, count, err