adding sessions api

This commit is contained in:
stremovsky
2019-12-16 17:44:35 +02:00
parent cda6a9c6c7
commit c77a67960a
4 changed files with 83 additions and 30 deletions

13
API.md
View File

@@ -165,9 +165,9 @@ This API is used to create new user app record and if the request is successful
| Resource / HTTP method | POST (create) | GET (read) | PUT (update) | DELETE (delete) |
| ---------------------------- | ------------------ | -------------- | -------------- | --------------- |
| /v1/session/token/{token} | Create new session | Get sessions | Error | Error |
| /v1/session/token/{token} | Create new session | Get sessions | Error | Error |
| /v1/session/session/:session | Error | Get session | Error?? | Error?? |
| /v1/session/clientip/:ip | Error | Get sessions | Error | Error |
## Create user session record
@@ -183,6 +183,9 @@ user ip, mobile device info, user agent, etc...
You can send the data as JSON POST or as regular POST parameters when working with this API.
Additional parameter is **expiration** that specifies TTL for this session record.
## Get user session record
### `GET /v1/session/session/:session`
@@ -198,12 +201,6 @@ This API returns session data.
This API returns an array of sessions of the same user.
## Get session records by ip address.
### `GET /v1/session/clientip/:ipaddress`
### Explanation
This API returns an array of user sessions by IP address. These sessions can be of different people.
---

View File

@@ -810,7 +810,7 @@ func initSessions(db *sql.DB) error {
CREATE TABLE IF NOT EXISTS sessions (
token STRING,
session STRING,
meta STRING,
data STRING,
when int,
endtime int
);

View File

@@ -1,13 +1,72 @@
package main
import (
"encoding/json"
"fmt"
"net/http"
"reflect"
"github.com/julienschmidt/httprouter"
)
func (e mainEnv) newSession(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
token := ps.ByName("token")
event := audit("create new session", token, "token", token)
address := ps.ByName("address")
mode := ps.ByName("mode")
event := audit("create new session", address, mode, address)
defer func() { event.submit(e.db) }()
if e.enforceAuth(w, r, event) == false {
return
}
userTOKEN := ""
if mode == "token" {
if enforceUUID(w, address, event) == false {
return
}
userBson, _ := e.db.lookupUserRecord(address)
if userBson == nil {
// if token not found, exit from here
return
}
userTOKEN = address
} else {
// TODO: decode url in code!
userBson, _ := e.db.lookupUserRecordByIndex(mode, address, e.conf)
if userBson != nil {
userTOKEN = userBson["token"].(string)
event.Record = userTOKEN
}
}
expiration := ""
records, err := getJSONPostData(r)
if err != nil {
returnError(w, r, "failed to decode request body", 405, err, event)
return
}
if len(records) == 0 {
returnError(w, r, "empty body", 405, nil, event)
return
}
if value, ok := records["expiration"]; ok {
if reflect.TypeOf(value) == reflect.TypeOf("string") {
expiration = value.(string)
} else {
returnError(w, r, "failed to parse expiration field", 405, err, event)
return
}
}
jsonData, err := json.Marshal(records)
if err != nil {
returnError(w, r, "internal error", 405, err, event)
return
}
sessionID, err := e.db.createSessionRecord(userTOKEN, expiration, jsonData)
if err != nil {
returnError(w, r, "internal error", 405, err, event)
return
}
w.Header().Set("Content-Type", "application/json; charset=utf-8")
w.WriteHeader(200)
fmt.Fprintf(w, `{"status":"ok","session":"%s"}`, sessionID)
return
}

View File

@@ -1,7 +1,6 @@
package main
import (
"crypto/sha256"
"encoding/base64"
"errors"
"time"
@@ -12,18 +11,19 @@ import (
type sessionEvent struct {
When int32
Meta []byte
Data string
}
func (dbobj dbcon) generateUserSession(userTOKEN string, clientip string, expiration string, meta []byte) (string, error) {
if len(expiration) == 0 {
return "", errors.New("failed to parse expiration")
func (dbobj dbcon) createSessionRecord(userTOKEN string, expiration string, data []byte) (string, error) {
var endtime int32 = 0
var err error
if len(expiration) > 0 {
endtime, err = parseExpiration(expiration)
if err != nil {
return "", err
}
}
endtime, err := parseExpiration(expiration)
if err != nil {
return "", err
}
encodedStr, err := dbobj.userEncrypt(userTOKEN, meta)
encodedStr, err := dbobj.userEncrypt(userTOKEN, data)
if err != nil {
return "", err
}
@@ -32,15 +32,12 @@ func (dbobj dbcon) generateUserSession(userTOKEN string, clientip string, expira
return "", err
}
bdoc := bson.M{}
now := int32(time.Now().Unix())
bdoc["token"] = userTOKEN
bdoc["session"] = tokenUUID
bdoc["endtime"] = endtime
bdoc["meta"] = encodedStr
if len(clientip) > 0 {
idxString := append(dbobj.hash, []byte(clientip)...)
idxStringHash := sha256.Sum256(idxString)
bdoc["clientipidx"] = base64.StdEncoding.EncodeToString(idxStringHash[:])
}
bdoc["when"] = now
bdoc["data"] = encodedStr
_, err = dbobj.createRecord(TblName.Sessions, bdoc)
if err != nil {
return "", err
@@ -59,7 +56,7 @@ func (dbobj dbcon) getUserSession(sessionUUID string) ([]byte, error) {
return nil, errors.New("session expired")
}
userTOKEN := record["token"].(string)
encData0 := record["meta"].(string)
encData0 := record["data"].(string)
decrypted, err := dbobj.userDecrypt(userTOKEN, encData0)
if err != nil {
return nil, err
@@ -92,10 +89,10 @@ func (dbobj dbcon) getUserSessionByToken(userTOKEN string) ([]*sessionEvent, int
var results []*sessionEvent
for _, element := range records {
encData0 := element["meta"].(string)
encData0 := element["data"].(string)
encData, _ := base64.StdEncoding.DecodeString(encData0)
decrypted, _ := decrypt(dbobj.masterKey, recordKey, encData)
sEvent := sessionEvent{0, decrypted}
sEvent := sessionEvent{0, string(decrypted)}
results = append(results, &sEvent)
}