code cleanup patch from pro

This commit is contained in:
yuli
2025-02-20 10:39:46 +02:00
parent 31e91c270f
commit 922cce5e7a
23 changed files with 416 additions and 674 deletions

View File

@@ -16,16 +16,25 @@ func (e mainEnv) agreementAccept(w http.ResponseWriter, r *http.Request, ps http
identity := ps.ByName("identity") identity := ps.ByName("identity")
brief := ps.ByName("brief") brief := ps.ByName("brief")
mode := ps.ByName("mode") mode := ps.ByName("mode")
event := audit.CreateAuditEvent("accept agreement by "+brief, identity, mode, identity)
brief = utils.NormalizeBrief(brief)
event := audit.CreateAuditEvent("accept agreement for "+brief, identity, mode, identity)
defer func() { SaveAuditEvent(event, e.db, e.conf) }() defer func() { SaveAuditEvent(event, e.db, e.conf) }()
if utils.ValidateMode(mode) == false { strictCheck := true
utils.ReturnError(w, r, "bad mode", 405, nil, event) if mode == "phone" || mode == "email" {
strictCheck = false
}
userTOKEN, _, err := e.getUserToken(w, r, mode, identity, event, strictCheck)
if strictCheck == true && userTOKEN == "" {
return return
} }
brief = utils.NormalizeBrief(brief) if err != nil {
return
}
if utils.CheckValidBrief(brief) == false { if utils.CheckValidBrief(brief) == false {
utils.ReturnError(w, r, "bad brief format", 405, nil, event) utils.ReturnError(w, r, "incorrect brief format", 405, nil, event)
return return
} }
exists, err := e.db.checkLegalBasis(brief) exists, err := e.db.checkLegalBasis(brief)
@@ -37,64 +46,32 @@ func (e mainEnv) agreementAccept(w http.ResponseWriter, r *http.Request, ps http
utils.ReturnError(w, r, "not found", 404, nil, event) utils.ReturnError(w, r, "not found", 404, nil, event)
return return
} }
userTOKEN := "" postData, err := utils.GetJSONPostMap(r)
if mode == "token" {
if utils.EnforceUUID(w, identity, event) == false {
return
}
userBson, err := e.db.lookupUserRecord(identity)
if err != nil || userBson == nil {
utils.ReturnError(w, r, "internal error", 405, err, event)
return
}
if e.EnforceAuth(w, r, event) == "" {
return
}
userTOKEN = identity
} else {
userBson, err := e.db.lookupUserRecordByIndex(mode, identity, e.conf)
if err != nil {
utils.ReturnError(w, r, "internal error", 405, err, event)
return
}
if userBson != nil {
userTOKEN = userBson["token"].(string)
event.Record = userTOKEN
} else {
if mode == "login" {
utils.ReturnError(w, r, "internal error", 405, nil, event)
return
}
// else user not found - we allow to save consent for unlinked users!
}
}
records, err := utils.GetJSONPostMap(r)
if err != nil { if err != nil {
utils.ReturnError(w, r, "failed to decode request body", 405, err, event) utils.ReturnError(w, r, "failed to decode request body", 405, err, event)
return return
} }
starttime := int32(0) starttime := int32(0)
expiration := int32(0) expiration := int32(0)
referencecode := utils.GetStringValue(records["referencecode"]) referencecode := utils.GetStringValue(postData["referencecode"])
lastmodifiedby := utils.GetStringValue(records["lastmodifiedby"]) lastmodifiedby := utils.GetStringValue(postData["lastmodifiedby"])
agreementmethod := utils.GetStringValue(records["agreementmethod"]) agreementmethod := utils.GetStringValue(postData["agreementmethod"])
status := utils.GetStringValue(records["status"]) status := utils.GetStringValue(postData["status"])
if len(status) == 0 { if len(status) == 0 {
status = "yes" status = "yes"
} else { } else {
status = utils.NormalizeConsentValue(status) status = utils.NormalizeConsentValue(status)
} }
if value, ok := records["expiration"]; ok { if value, ok := postData["expiration"]; ok {
switch records["expiration"].(type) { switch postData["expiration"].(type) {
case string: case string:
expiration, _ = utils.ParseExpiration(value.(string)) expiration, _ = utils.ParseExpiration(value.(string))
case float64: case float64:
expiration = int32(value.(float64)) expiration = int32(value.(float64))
} }
} }
if value, ok := records["starttime"]; ok { if value, ok := postData["starttime"]; ok {
switch records["starttime"].(type) { switch postData["starttime"].(type) {
case string: case string:
starttime, _ = utils.ParseExpiration(value.(string)) starttime, _ = utils.ParseExpiration(value.(string))
case float64: case float64:
@@ -107,6 +84,7 @@ func (e mainEnv) agreementAccept(w http.ResponseWriter, r *http.Request, ps http
case "phone": case "phone":
identity = utils.NormalizePhone(identity, e.conf.Sms.DefaultCountry) identity = utils.NormalizePhone(identity, e.conf.Sms.DefaultCountry)
} }
log.Printf("Processing agreement, status: %s\n", status) log.Printf("Processing agreement, status: %s\n", status)
e.db.acceptAgreement(userTOKEN, mode, identity, brief, status, agreementmethod, e.db.acceptAgreement(userTOKEN, mode, identity, brief, status, agreementmethod,
referencecode, lastmodifiedby, starttime, expiration) referencecode, lastmodifiedby, starttime, expiration)
@@ -130,15 +108,23 @@ func (e mainEnv) agreementWithdraw(w http.ResponseWriter, r *http.Request, ps ht
identity := ps.ByName("identity") identity := ps.ByName("identity")
brief := ps.ByName("brief") brief := ps.ByName("brief")
mode := ps.ByName("mode") mode := ps.ByName("mode")
event := audit.CreateAuditEvent("withdraw agreement by "+brief, identity, mode, identity)
defer func() { SaveAuditEvent(event, e.db, e.conf) }()
if utils.ValidateMode(mode) == false {
utils.ReturnError(w, r, "bad mode", 405, nil, event)
return
}
brief = utils.NormalizeBrief(brief) brief = utils.NormalizeBrief(brief)
event := audit.CreateAuditEvent("withdraw agreement for "+brief, identity, mode, identity)
defer func() { SaveAuditEvent(event, e.db, e.conf) }()
strictCheck := true
if mode == "phone" || mode == "email" {
strictCheck = false
}
userTOKEN, userBSON, err := e.getUserToken(w, r, mode, identity, event, strictCheck)
if strictCheck == true && userTOKEN == "" {
//log.Printf("Strict check err")
return
}
if err != nil {
return
}
if utils.CheckValidBrief(brief) == false { if utils.CheckValidBrief(brief) == false {
utils.ReturnError(w, r, "bad brief format", 405, nil, event) utils.ReturnError(w, r, "bad brief format", 405, nil, event)
return return
@@ -152,42 +138,12 @@ func (e mainEnv) agreementWithdraw(w http.ResponseWriter, r *http.Request, ps ht
utils.ReturnError(w, r, "not found", 405, nil, event) utils.ReturnError(w, r, "not found", 405, nil, event)
return return
} }
userTOKEN := "" postData, err := utils.GetJSONPostMap(r)
authResult := ""
if mode == "token" {
if utils.EnforceUUID(w, identity, event) == false {
return
}
userBson, _ := e.db.lookupUserRecord(identity)
if userBson == nil {
utils.ReturnError(w, r, "internal error", 405, nil, event)
return
}
authResult = e.EnforceAuth(w, r, event)
if authResult == "" {
return
}
userTOKEN = identity
} else {
// TODO: decode url in code!
userBson, _ := e.db.lookupUserRecordByIndex(mode, identity, e.conf)
if userBson != nil {
userTOKEN = userBson["token"].(string)
event.Record = userTOKEN
} else {
if mode == "login" {
utils.ReturnError(w, r, "internal error", 405, nil, event)
return
}
// else user not found - we allow to save consent for unlinked users!
}
}
records, err := utils.GetJSONPostMap(r)
if err != nil { if err != nil {
utils.ReturnError(w, r, "failed to decode request body", 405, err, event) utils.ReturnError(w, r, "failed to decode request body", 405, err, event)
return return
} }
lastmodifiedby := utils.GetStringValue(records["lastmodifiedby"]) lastmodifiedby := utils.GetStringValue(postData["lastmodifiedby"])
selfService := false selfService := false
if value, ok := lbasis["usercontrol"]; ok { if value, ok := lbasis["usercontrol"]; ok {
if reflect.TypeOf(value).Kind() == reflect.Bool { if reflect.TypeOf(value).Kind() == reflect.Bool {
@@ -199,6 +155,7 @@ func (e mainEnv) agreementWithdraw(w http.ResponseWriter, r *http.Request, ps ht
} }
} }
} }
authResult := e.EnforceAuth(w, r, event)
if selfService == false { if selfService == false {
// user can change consent only for briefs defined in self-service // user can change consent only for briefs defined in self-service
if len(authResult) == 0 { if len(authResult) == 0 {
@@ -207,9 +164,8 @@ func (e mainEnv) agreementWithdraw(w http.ResponseWriter, r *http.Request, ps ht
} }
} }
} }
if authResult == "login" && selfService == false { if authResult == "login" && selfService == false {
rtoken, rstatus, err := e.db.saveUserRequest("agreement-withdraw", userTOKEN, "", brief, nil, e.conf) rtoken, rstatus, err := e.db.saveUserRequest("agreement-withdraw", userTOKEN, userBSON, "", brief, nil, e.conf)
if err != nil { if err != nil {
utils.ReturnError(w, r, "internal error", 405, err, event) utils.ReturnError(w, r, "internal error", 405, err, event)
return return
@@ -239,10 +195,10 @@ func (e mainEnv) agreementWithdraw(w http.ResponseWriter, r *http.Request, ps ht
func (e mainEnv) agreementRevokeAll(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { func (e mainEnv) agreementRevokeAll(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
brief := ps.ByName("brief") brief := ps.ByName("brief")
brief = utils.NormalizeBrief(brief)
if e.EnforceAdmin(w, r, nil) == "" { if e.EnforceAdmin(w, r, nil) == "" {
return return
} }
brief = utils.NormalizeBrief(brief)
if utils.CheckValidBrief(brief) == false { if utils.CheckValidBrief(brief) == false {
utils.ReturnError(w, r, "bad brief format", 405, nil, nil) utils.ReturnError(w, r, "bad brief format", 405, nil, nil)
return return
@@ -265,48 +221,11 @@ func (e mainEnv) agreementRevokeAll(w http.ResponseWriter, r *http.Request, ps h
func (e mainEnv) getUserAgreements(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { func (e mainEnv) getUserAgreements(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
identity := ps.ByName("identity") identity := ps.ByName("identity")
mode := ps.ByName("mode") mode := ps.ByName("mode")
event := audit.CreateAuditEvent("privacy agreements for "+mode, identity, mode, identity) event := audit.CreateAuditEvent("get agreements for "+mode, identity, mode, identity)
defer func() { SaveAuditEvent(event, e.db, e.conf) }() defer func() { SaveAuditEvent(event, e.db, e.conf) }()
if utils.ValidateMode(mode) == false { userTOKEN, _, _ := e.getUserToken(w, r, mode, identity, event, true)
utils.ReturnError(w, r, "bad mode", 405, nil, event) if userTOKEN == "" {
return
}
userTOKEN := ""
if mode == "token" {
if utils.EnforceUUID(w, identity, event) == false {
return
}
userBson, _ := e.db.lookupUserRecord(identity)
if userBson == nil {
utils.ReturnError(w, r, "internal error", 405, nil, event)
return
}
if e.EnforceAuth(w, r, event) == "" {
return
}
userTOKEN = identity
} else {
// TODO: decode url in code!
userBson, _ := e.db.lookupUserRecordByIndex(mode, identity, e.conf)
if userBson != nil {
userTOKEN = userBson["token"].(string)
event.Record = userTOKEN
if e.EnforceAuth(w, r, event) == "" {
return
}
} else {
if mode == "login" {
utils.ReturnError(w, r, "internal error", 405, nil, event)
return
}
// else user not found - we allow to save consent for unlinked users!
}
}
// make sure that user is logged in here, unless he wants to cancel emails
if e.EnforceAuth(w, r, event) == "" {
return return
} }
var resultJSON []byte var resultJSON []byte
@@ -317,6 +236,7 @@ func (e mainEnv) getUserAgreements(w http.ResponseWriter, r *http.Request, ps ht
} else { } else {
resultJSON, numRecords, err = e.db.listAgreementRecordsByIdentity(identity) resultJSON, numRecords, err = e.db.listAgreementRecordsByIdentity(identity)
} }
if err != nil { if err != nil {
utils.ReturnError(w, r, "internal error", 405, err, event) utils.ReturnError(w, r, "internal error", 405, err, event)
return return
@@ -331,14 +251,15 @@ func (e mainEnv) getUserAgreement(w http.ResponseWriter, r *http.Request, ps htt
identity := ps.ByName("identity") identity := ps.ByName("identity")
brief := ps.ByName("brief") brief := ps.ByName("brief")
mode := ps.ByName("mode") mode := ps.ByName("mode")
event := audit.CreateAuditEvent("privacy agreements for "+mode, identity, mode, identity)
brief = utils.NormalizeBrief(brief)
event := audit.CreateAuditEvent("get agreements for "+brief, identity, mode, identity)
defer func() { SaveAuditEvent(event, e.db, e.conf) }() defer func() { SaveAuditEvent(event, e.db, e.conf) }()
if utils.ValidateMode(mode) == false { userTOKEN, _, _ := e.getUserToken(w, r, mode, identity, event, true)
utils.ReturnError(w, r, "bad mode", 405, nil, event) if userTOKEN == "" {
return return
} }
brief = utils.NormalizeBrief(brief)
if utils.CheckValidBrief(brief) == false { if utils.CheckValidBrief(brief) == false {
utils.ReturnError(w, r, "bad brief format", 405, nil, event) utils.ReturnError(w, r, "bad brief format", 405, nil, event)
return return
@@ -352,43 +273,8 @@ func (e mainEnv) getUserAgreement(w http.ResponseWriter, r *http.Request, ps htt
utils.ReturnError(w, r, "not found", 404, nil, event) utils.ReturnError(w, r, "not found", 404, nil, event)
return return
} }
userTOKEN := ""
if mode == "token" { resultJSON, err := e.db.viewAgreementRecord(userTOKEN, brief)
if utils.EnforceUUID(w, identity, event) == false {
return
}
userBson, _ := e.db.lookupUserRecord(identity)
if userBson == nil {
utils.ReturnError(w, r, "internal error", 405, nil, event)
return
}
if e.EnforceAuth(w, r, event) == "" {
return
}
userTOKEN = identity
} else {
// TODO: decode url in code!
userBson, _ := e.db.lookupUserRecordByIndex(mode, identity, e.conf)
if userBson != nil {
userTOKEN = userBson["token"].(string)
event.Record = userTOKEN
if e.EnforceAuth(w, r, event) == "" {
return
}
} else {
if mode == "login" {
utils.ReturnError(w, r, "internal error", 405, nil, event)
return
}
// else user not found - we allow to save consent for unlinked users!
}
}
// make sure that user is logged in here, unless he wants to cancel emails
if e.EnforceAuth(w, r, event) == "" {
return
}
var resultJSON []byte
resultJSON, err = e.db.viewAgreementRecord(userTOKEN, brief)
if err != nil { if err != nil {
utils.ReturnError(w, r, "internal error", 405, err, event) utils.ReturnError(w, r, "internal error", 405, err, event)
return return
@@ -430,7 +316,7 @@ func (e mainEnv) consentUserRecord(w http.ResponseWriter, r *http.Request, ps ht
} else { } else {
userBson, _ = e.db.lookupUserRecordByIndex(mode, identity, e.conf) userBson, _ = e.db.lookupUserRecordByIndex(mode, identity, e.conf)
if userBson != nil { if userBson != nil {
userTOKEN = userBson["token"].(string) userTOKEN = utils.GetUuidString(userBson["token"])
event.Record = userTOKEN event.Record = userTOKEN
} }
} }

View File

@@ -95,7 +95,10 @@ func (dbobj dbcon) acceptAgreement(userTOKEN string, mode string, identity strin
func (dbobj dbcon) linkAgreementRecords(userTOKEN string, encIdentity string) error { func (dbobj dbcon) linkAgreementRecords(userTOKEN string, encIdentity string) error {
bdoc := bson.M{} bdoc := bson.M{}
bdoc["token"] = userTOKEN bdoc["token"] = userTOKEN
_, err := dbobj.store.UpdateRecord2(storage.TblName.Agreements, "token", "", "who", encIdentity, &bdoc, nil) _, err := dbobj.store.UpdateRecord(storage.TblName.Agreements, "who", encIdentity, &bdoc)
if err != nil {
log.Printf("db error: %s", err)
}
return err return err
} }
@@ -114,7 +117,6 @@ func (dbobj dbcon) withdrawAgreement(userTOKEN string, brief string, mode string
bdoc["status"] = "no" bdoc["status"] = "no"
bdoc["lastmodifiedby"] = lastmodifiedby bdoc["lastmodifiedby"] = lastmodifiedby
if len(userTOKEN) > 0 { if len(userTOKEN) > 0 {
log.Printf("%s %s\n", userTOKEN, brief)
dbobj.store.UpdateRecord2(storage.TblName.Agreements, "token", userTOKEN, "brief", brief, &bdoc, nil) dbobj.store.UpdateRecord2(storage.TblName.Agreements, "token", userTOKEN, "brief", brief, &bdoc, nil)
} else if len(identity) > 0 { } else if len(identity) > 0 {
dbobj.store.UpdateRecord2(storage.TblName.Agreements, "who", encIdentity, "brief", brief, &bdoc, nil) dbobj.store.UpdateRecord2(storage.TblName.Agreements, "who", encIdentity, "brief", brief, &bdoc, nil)
@@ -132,6 +134,7 @@ func (dbobj dbcon) listAgreementRecords(userTOKEN string) ([]byte, int, error) {
return []byte("[]"), 0, err return []byte("[]"), 0, err
} }
for _, rec := range records { for _, rec := range records {
rec["token"] = utils.GetUuidString(rec["token"])
encIdentity := rec["who"].(string) encIdentity := rec["who"].(string)
if len(encIdentity) > 0 { if len(encIdentity) > 0 {
identity, _ := utils.BasicStringDecrypt(encIdentity, dbobj.masterKey, dbobj.GetCode()) identity, _ := utils.BasicStringDecrypt(encIdentity, dbobj.masterKey, dbobj.GetCode())
@@ -159,6 +162,7 @@ func (dbobj dbcon) listAgreementRecordsByIdentity(identity string) ([]byte, int,
return []byte("[]"), 0, err return []byte("[]"), 0, err
} }
for _, rec := range records { for _, rec := range records {
rec["token"] = utils.GetUuidString(rec["token"])
rec["who"] = identity rec["who"] = identity
} }
resultJSON, err := json.Marshal(records) resultJSON, err := json.Marshal(records)
@@ -174,6 +178,7 @@ func (dbobj dbcon) viewAgreementRecord(userTOKEN string, brief string) ([]byte,
if record == nil || err != nil { if record == nil || err != nil {
return nil, err return nil, err
} }
record["token"] = utils.GetUuidString(record["token"])
encIdentity := record["who"].(string) encIdentity := record["who"].(string)
if len(encIdentity) > 0 { if len(encIdentity) > 0 {
identity, _ := utils.BasicStringDecrypt(encIdentity, dbobj.masterKey, dbobj.GetCode()) identity, _ := utils.BasicStringDecrypt(encIdentity, dbobj.masterKey, dbobj.GetCode())
@@ -200,7 +205,7 @@ func (dbobj dbcon) expireAgreementRecords(notifyURL string) error {
bdoc := bson.M{} bdoc := bson.M{}
bdoc["when"] = now bdoc["when"] = now
bdoc["status"] = "expired" bdoc["status"] = "expired"
userTOKEN := rec["token"].(string) userTOKEN := utils.GetUuidString(rec["token"])
brief := rec["brief"].(string) brief := rec["brief"].(string)
log.Printf("This agreement record is expired: %s - %s\n", userTOKEN, brief) log.Printf("This agreement record is expired: %s - %s\n", userTOKEN, brief)
if len(userTOKEN) > 0 { if len(userTOKEN) > 0 {

View File

@@ -176,8 +176,12 @@ func (dbobj dbcon) getAuditEvent(atoken string) (string, []byte, error) {
return userTOKEN, nil, errors.New("empty token") return userTOKEN, nil, errors.New("empty token")
} }
userTOKEN, _ = utils.BasicStringDecrypt(userTOKENEnc, dbobj.masterKey, dbobj.GetCode()) userTOKEN, _ = utils.BasicStringDecrypt(userTOKENEnc, dbobj.masterKey, dbobj.GetCode())
userBSON, err := dbobj.lookupUserRecord(userTOKEN)
if err != nil {
return "", nil, err
}
if len(before) > 0 { if len(before) > 0 {
before2, after2, _ := dbobj.userDecrypt2(userTOKEN, before, after) before2, after2, _ := dbobj.userDecrypt2(userBSON, before, after)
//log.Printf("before: %s", before2) //log.Printf("before: %s", before2)
//log.Printf("after: %s", after2) //log.Printf("after: %s", after2)
record["before"] = before2 record["before"] = before2
@@ -190,7 +194,7 @@ func (dbobj dbcon) getAuditEvent(atoken string) (string, []byte, error) {
return userTOKEN, []byte(result), nil return userTOKEN, []byte(result), nil
} }
if len(after) > 0 { if len(after) > 0 {
after2, _ := dbobj.userDecrypt(userTOKEN, after) after2, _ := dbobj.userDecrypt(userBSON, after)
//log.Printf("after: %s", after2) //log.Printf("after: %s", after2)
record["after"] = after2 record["after"] = after2
result := fmt.Sprintf(`{"after":%s,"debug":"%s"}`, after2, debug) result := fmt.Sprintf(`{"after":%s,"debug":"%s"}`, after2, debug)

View File

@@ -5,6 +5,7 @@ package main
import ( import (
"bytes" "bytes"
"compress/gzip" "compress/gzip"
"errors"
"io" "io"
"log" "log"
"math/rand" "math/rand"
@@ -22,7 +23,6 @@ import (
"github.com/securitybunker/databunker/src/autocontext" "github.com/securitybunker/databunker/src/autocontext"
"github.com/securitybunker/databunker/src/storage" "github.com/securitybunker/databunker/src/storage"
"github.com/securitybunker/databunker/src/utils" "github.com/securitybunker/databunker/src/utils"
"go.mongodb.org/mongo-driver/bson"
"gopkg.in/yaml.v2" "gopkg.in/yaml.v2"
) )
@@ -146,7 +146,7 @@ func (e mainEnv) metrics(w http.ResponseWriter, r *http.Request, ps httprouter.P
// backupDB API call. // backupDB API call.
func (e mainEnv) backupDB(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { func (e mainEnv) backupDB(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
if e.EnforceAuth(w, r, nil) == "" { if e.EnforceAdmin(w, r, nil) == "" {
return return
} }
w.WriteHeader(200) w.WriteHeader(200)
@@ -338,7 +338,7 @@ func (e mainEnv) setupRouter() *httprouter.Router {
router.NotFound = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { router.NotFound = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json; charset=utf-8") w.Header().Set("Content-Type", "application/json; charset=utf-8")
w.WriteHeader(http.StatusNotFound) w.WriteHeader(http.StatusNotFound)
w.Write([]byte(`{"status":"error", "message":"url not found"}`)) w.Write([]byte(`{"status":"error", "message":"endpoint is missing"}`))
}) })
router.GlobalOPTIONS = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { router.GlobalOPTIONS = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
//if r.Header.Get("Access-Control-Request-Method") != "" { //if r.Header.Get("Access-Control-Request-Method") != "" {
@@ -384,27 +384,44 @@ func (e mainEnv) dbCleanup() {
} }
// helper function to load user details by idex name // helper function to load user details by idex name
func (e mainEnv) loadUserToken(w http.ResponseWriter, r *http.Request, mode string, identity string, event *audit.AuditEvent) string { func (e mainEnv) getUserToken(w http.ResponseWriter, r *http.Request, mode string, identity string, event *audit.AuditEvent, strictCheck bool) (string, map[string]interface{}, error) {
var userBSON map[string]interface{}
var err error var err error
if utils.ValidateMode(mode) == false { if utils.ValidateMode(mode) == false {
utils.ReturnError(w, r, "bad mode", 405, nil, event) utils.ReturnError(w, r, "bad mode", 405, nil, event)
return "" return "", userBSON, errors.New("bad mode")
} }
var userBson bson.M
if mode == "token" { if mode == "token" {
if utils.EnforceUUID(w, identity, event) == false { if utils.EnforceUUID(w, identity, event) == false {
return "" return "", userBSON, errors.New("uuid is incorrect")
} }
userBson, err = e.db.lookupUserRecord(identity) userBSON, err = e.db.lookupUserRecord(identity)
} else { } else {
userBson, err = e.db.lookupUserRecordByIndex(mode, identity, e.conf) userBSON, err = e.db.lookupUserRecordByIndex(mode, identity, e.conf)
} }
if userBson == nil || err != nil { if err != nil {
utils.ReturnError(w, r, "internal error", 405, nil, event) utils.ReturnError(w, r, "internal error", 405, nil, event)
return "" return "", userBSON, err
} }
event.Record = userBson["token"].(string) userToken := utils.GetUuidString(userBSON["token"])
return event.Record if len(userToken) > 0 {
if event != nil {
event.Record = userToken
}
//log.Printf("getUserToken -> EnforceAuth()")
if e.EnforceAuth(w, r, event) == "" {
//log.Printf("XToken validation error")
return "", userBSON, errors.New("incorrect access token")
}
return userToken, userBSON, nil
}
// not found
if strictCheck == true {
utils.ReturnError(w, r, "not found", 405, nil, event)
return "", userBSON, errors.New("not found")
}
// make sure to check if user is admin
return "", userBSON, nil
} }
// CustomResponseWriter struct is a custom wrapper for ResponseWriter // CustomResponseWriter struct is a custom wrapper for ResponseWriter
@@ -484,7 +501,7 @@ func (e mainEnv) reqMiddleware(handler http.Handler) http.Handler {
} else { } else {
statusCounter = 0 statusCounter = 0
statusErrorCounter = 0 statusErrorCounter = 0
log.Printf("%d %s %s\n", w2.Code, r.Method, r.URL) log.Printf("[%d] %s %s\n", w2.Code, r.Method, r.URL)
} }
}) })
} }

View File

@@ -23,7 +23,7 @@ func helpServe0(request *http.Request) ([]byte, error) {
request.Header.Set("Content-Type", "application/json") request.Header.Set("Content-Type", "application/json")
rr := httptest.NewRecorder() rr := httptest.NewRecorder()
router.ServeHTTP(rr, request) router.ServeHTTP(rr, request)
log.Printf("[%d] %s%s\n", rr.Code, request.Host, request.URL.Path) log.Printf("[%d] %s %s\n", rr.Code, request.Method, request.URL.Path)
if rr.Code != 200 { if rr.Code != 200 {
return rr.Body.Bytes(), fmt.Errorf("wrong status: %d", rr.Code) return rr.Body.Bytes(), fmt.Errorf("wrong status: %d", rr.Code)
} }
@@ -35,7 +35,7 @@ func helpServe(request *http.Request) (map[string]interface{}, error) {
request.Header.Set("Content-Type", "application/json") request.Header.Set("Content-Type", "application/json")
rr := httptest.NewRecorder() rr := httptest.NewRecorder()
router.ServeHTTP(rr, request) router.ServeHTTP(rr, request)
log.Printf("[%d] %s%s %s\n", rr.Code, request.Host, request.URL.Path, rr.Body.Bytes()) log.Printf("[%d] %s %s %s\n", rr.Code, request.Method, request.URL.Path, rr.Body.Bytes())
var raw map[string]interface{} var raw map[string]interface{}
if rr.Body.Bytes()[0] == '{' { if rr.Body.Bytes()[0] == '{' {
json.Unmarshal(rr.Body.Bytes(), &raw) json.Unmarshal(rr.Body.Bytes(), &raw)
@@ -50,7 +50,7 @@ func helpServe2(request *http.Request) (map[string]interface{}, error) {
request.Header.Set("Content-Type", "application/x-www-form-urlencoded") request.Header.Set("Content-Type", "application/x-www-form-urlencoded")
rr := httptest.NewRecorder() rr := httptest.NewRecorder()
router.ServeHTTP(rr, request) router.ServeHTTP(rr, request)
log.Printf("[%d] %s%s %s\n", rr.Code, request.Host, request.URL.Path, rr.Body.Bytes()) log.Printf("[%d] %s %s %s\n", rr.Code, request.Method, request.URL.Path, rr.Body.Bytes())
var raw map[string]interface{} var raw map[string]interface{}
if rr.Body.Bytes()[0] == '{' { if rr.Body.Bytes()[0] == '{' {
json.Unmarshal(rr.Body.Bytes(), &raw) json.Unmarshal(rr.Body.Bytes(), &raw)
@@ -112,8 +112,8 @@ func TestAnonPage(t *testing.T) {
{"url": "/site/site.js", "pattern": "dateFormat"}, {"url": "/site/site.js", "pattern": "dateFormat"},
{"url": "/site/style.css", "pattern": "html"}, {"url": "/site/style.css", "pattern": "html"},
{"url": "/site/user-profile.html", "pattern": "profile"}, {"url": "/site/user-profile.html", "pattern": "profile"},
{"url": "/not-fund-page.html", "pattern": "not found"}, {"url": "/not-found-page.html", "pattern": "endpoint is missing"},
{"url": "/site/not-fund-page.html", "pattern": "not found"}, {"url": "/site/not-found-page.html", "pattern": "url not found"},
} }
for _, value := range goodJsons { for _, value := range goodJsons {
url := "http://localhost:3000" + value["url"].(string) url := "http://localhost:3000" + value["url"].(string)
@@ -121,7 +121,7 @@ func TestAnonPage(t *testing.T) {
request := httptest.NewRequest("GET", url, nil) request := httptest.NewRequest("GET", url, nil)
raw, _ := helpServe0(request) raw, _ := helpServe0(request)
if strings.Contains(string(raw), pattern) == false { if strings.Contains(string(raw), pattern) == false {
t.Fatalf("pattern detection failed\n") t.Fatalf("pattern detection failed for %s: %s\nresp: %s", url, pattern, string(raw))
} }
} }
} }

View File

@@ -64,6 +64,7 @@ func TestConsentCreateWithdraw(t *testing.T) {
if _, ok := raw["status"]; !ok || raw["status"].(string) != "ok" { if _, ok := raw["status"]; !ok || raw["status"].(string) != "ok" {
t.Fatalf("Failed to get all brief codes") t.Fatalf("Failed to get all brief codes")
} }
/*
raw, _ = helpGetAllUserAgreements("email", "moshe@moshe-int.com") raw, _ = helpGetAllUserAgreements("email", "moshe@moshe-int.com")
if _, ok := raw["status"]; !ok || raw["status"].(string) != "ok" { if _, ok := raw["status"]; !ok || raw["status"].(string) != "ok" {
t.Fatalf("Failed to get user consents") t.Fatalf("Failed to get user consents")
@@ -71,6 +72,7 @@ func TestConsentCreateWithdraw(t *testing.T) {
if raw["total"].(float64) != 0 { if raw["total"].(float64) != 0 {
t.Fatalf("Wrong number of user consents") t.Fatalf("Wrong number of user consents")
} }
*/
raw, _ = helpCreateLBasis("test0", `{"basistype":"consent","usercontrol":true}`) raw, _ = helpCreateLBasis("test0", `{"basistype":"consent","usercontrol":true}`)
if _, ok := raw["status"]; !ok || raw["status"].(string) != "ok" { if _, ok := raw["status"]; !ok || raw["status"].(string) != "ok" {
t.Fatalf("Failed to create consent") t.Fatalf("Failed to create consent")
@@ -85,6 +87,7 @@ func TestConsentCreateWithdraw(t *testing.T) {
if _, ok := raw["status"]; !ok || raw["status"].(string) != "ok" { if _, ok := raw["status"]; !ok || raw["status"].(string) != "ok" {
t.Fatalf("Failed to accept on consent") t.Fatalf("Failed to accept on consent")
} }
/*
raw, _ = helpGetAllUserAgreements("email", "moshe@moshe-int.com") raw, _ = helpGetAllUserAgreements("email", "moshe@moshe-int.com")
if _, ok := raw["status"]; !ok || raw["status"].(string) != "ok" { if _, ok := raw["status"]; !ok || raw["status"].(string) != "ok" {
t.Fatalf("Failed to get user consents") t.Fatalf("Failed to get user consents")
@@ -92,6 +95,7 @@ func TestConsentCreateWithdraw(t *testing.T) {
if raw["total"].(float64) != 1 { if raw["total"].(float64) != 1 {
t.Fatalf("Wrong number of user consents") t.Fatalf("Wrong number of user consents")
} }
*/
userJSON := `{"login":"moshe","email":"moshe@moshe-int.com","phone":"12345678"}` userJSON := `{"login":"moshe","email":"moshe@moshe-int.com","phone":"12345678"}`
raw, err := helpCreateUser(userJSON) raw, err := helpCreateUser(userJSON)
if err != nil { if err != nil {

View File

@@ -9,13 +9,12 @@ import (
"github.com/securitybunker/databunker/src/audit" "github.com/securitybunker/databunker/src/audit"
"github.com/securitybunker/databunker/src/storage" "github.com/securitybunker/databunker/src/storage"
"github.com/securitybunker/databunker/src/utils" "github.com/securitybunker/databunker/src/utils"
"go.mongodb.org/mongo-driver/bson"
) )
func (e mainEnv) expUsers() error { func (e mainEnv) expUsers() error {
records, err := e.db.store.GetExpiring(storage.TblName.Users, "expstatus", "wait") records, err := e.db.store.GetExpiring(storage.TblName.Users, "expstatus", "wait")
for _, rec := range records { for _, rec := range records {
userTOKEN := rec["token"].(string) userTOKEN := utils.GetUuidString(rec["token"])
resultJSON, userBSON, _ := e.db.getUser(userTOKEN) resultJSON, userBSON, _ := e.db.getUser(userTOKEN)
if resultJSON != nil { if resultJSON != nil {
email := utils.GetStringValue(userBSON["email"]) email := utils.GetStringValue(userBSON["email"])
@@ -32,31 +31,18 @@ func (e mainEnv) expUsers() error {
func (e mainEnv) expGetStatus(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { func (e mainEnv) expGetStatus(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
identity := ps.ByName("identity") identity := ps.ByName("identity")
mode := ps.ByName("mode") mode := ps.ByName("mode")
event := audit.CreateAuditEvent("get expiration status by "+mode, identity, mode, identity) event := audit.CreateAuditEvent("get expiration status by "+mode, identity, mode, identity)
defer func() { SaveAuditEvent(event, e.db, e.conf) }() defer func() { SaveAuditEvent(event, e.db, e.conf) }()
var err error
if utils.ValidateMode(mode) == false { userTOKEN, userBSON, _ := e.getUserToken(w, r, mode, identity, event, true)
utils.ReturnError(w, r, "bad mode", 405, nil, event) if userTOKEN == "" {
return return
} }
var userBson bson.M
if mode == "token" { expirationDate := utils.GetIntValue(userBSON["endtime"])
if utils.EnforceUUID(w, identity, event) == false { expirationStatus := utils.GetStringValue(userBSON["expstatus"])
return expirationToken := utils.GetStringValue(userBSON["exptoken"])
}
userBson, err = e.db.lookupUserRecord(identity)
} else {
userBson, err = e.db.lookupUserRecordByIndex(mode, identity, e.conf)
}
if userBson == nil || err != nil {
utils.ReturnError(w, r, "internal error", 405, nil, event)
return
}
userTOKEN := userBson["token"].(string)
event.Record = userTOKEN
expirationDate := utils.GetIntValue(userBson["endtime"])
expirationStatus := utils.GetStringValue(userBson["expstatus"])
expirationToken := utils.GetStringValue(userBson["exptoken"])
finalJSON := fmt.Sprintf(`{"status":"ok","exptime":%d,"expstatus":"%s","exptoken":"%s"}`, finalJSON := fmt.Sprintf(`{"status":"ok","exptime":%d,"expstatus":"%s","exptoken":"%s"}`,
expirationDate, expirationStatus, expirationToken) expirationDate, expirationStatus, expirationToken)
w.Header().Set("Content-Type", "application/json; charset=utf-8") w.Header().Set("Content-Type", "application/json; charset=utf-8")
@@ -70,28 +56,12 @@ func (e mainEnv) expCancel(w http.ResponseWriter, r *http.Request, ps httprouter
mode := ps.ByName("mode") mode := ps.ByName("mode")
event := audit.CreateAuditEvent("clear user expiration by "+mode, identity, mode, identity) event := audit.CreateAuditEvent("clear user expiration by "+mode, identity, mode, identity)
defer func() { SaveAuditEvent(event, e.db, e.conf) }() defer func() { SaveAuditEvent(event, e.db, e.conf) }()
if utils.ValidateMode(mode) == false {
utils.ReturnError(w, r, "bad mode", 405, nil, event) userTOKEN, _, _ := e.getUserToken(w, r, mode, identity, event, true)
return if userTOKEN == "" {
}
userTOKEN := identity
var userBson bson.M
if mode == "token" {
if utils.EnforceUUID(w, identity, event) == false {
return
}
userBson, err = e.db.lookupUserRecord(identity)
} else {
userBson, err = e.db.lookupUserRecordByIndex(mode, identity, e.conf)
if userBson != nil {
userTOKEN = userBson["token"].(string)
event.Record = userTOKEN
}
}
if userBson == nil || err != nil {
utils.ReturnError(w, r, "internal error", 405, nil, event)
return return
} }
status := "" status := ""
err = e.db.updateUserExpStatus(userTOKEN, status) err = e.db.updateUserExpStatus(userTOKEN, status)
if err != nil { if err != nil {
@@ -117,7 +87,7 @@ func (e mainEnv) expRetainData(w http.ResponseWriter, r *http.Request, ps httpro
utils.ReturnError(w, r, "internal error", 405, nil, event) utils.ReturnError(w, r, "internal error", 405, nil, event)
return return
} }
userTOKEN := userBson["token"].(string) userTOKEN := utils.GetUuidString(userBson["token"])
event.Record = userTOKEN event.Record = userTOKEN
status := "retain" status := "retain"
err = e.db.updateUserExpStatus(userTOKEN, status) err = e.db.updateUserExpStatus(userTOKEN, status)
@@ -164,22 +134,25 @@ func (e mainEnv) expStart(w http.ResponseWriter, r *http.Request, ps httprouter.
event := audit.CreateAuditEvent("initiate user record expiration by "+mode, identity, mode, identity) event := audit.CreateAuditEvent("initiate user record expiration by "+mode, identity, mode, identity)
defer func() { SaveAuditEvent(event, e.db, e.conf) }() defer func() { SaveAuditEvent(event, e.db, e.conf) }()
if e.EnforceAdmin(w, r, event) == "" { userTOKEN, _, _ := e.getUserToken(w, r, mode, identity, event, true)
return
}
userTOKEN := e.loadUserToken(w, r, mode, identity, event)
if userTOKEN == "" { if userTOKEN == "" {
return return
} }
records, err := utils.GetJSONPostMap(r) //only admin should do this request?
authResult := e.EnforceAdmin(w, r, event)
if authResult == "" {
return
}
postData, err := utils.GetJSONPostMap(r)
if err != nil { if err != nil {
utils.ReturnError(w, r, "failed to decode request body", 405, err, event) utils.ReturnError(w, r, "failed to decode request body", 405, err, event)
return return
} }
expirationStr := utils.GetStringValue(records["expiration"]) expirationStr := utils.GetStringValue(postData["expiration"])
expiration := utils.SetExpiration(e.conf.Policy.MaxUserRetentionPeriod, expirationStr) expiration := utils.SetExpiration(e.conf.Policy.MaxUserRetentionPeriod, expirationStr)
endtime, _ := utils.ParseExpiration(expiration) endtime, _ := utils.ParseExpiration(expiration)
status := utils.GetStringValue(records["status"]) status := utils.GetStringValue(postData["status"])
if len(status) == 0 { if len(status) == 0 {
status = "wait" status = "wait"
} }

View File

@@ -20,30 +20,30 @@ func (e mainEnv) createLegalBasis(w http.ResponseWriter, r *http.Request, ps htt
utils.ReturnError(w, r, "bad brief format", 405, nil, nil) utils.ReturnError(w, r, "bad brief format", 405, nil, nil)
return return
} }
records, err := utils.GetJSONPostMap(r) postData, err := utils.GetJSONPostMap(r)
if err != nil { if err != nil {
utils.ReturnError(w, r, "failed to decode request body", 405, err, nil) utils.ReturnError(w, r, "failed to decode request body", 405, err, nil)
return return
} }
newbrief := utils.GetStringValue(records["brief"]) newbrief := utils.GetStringValue(postData["brief"])
if len(newbrief) > 0 && newbrief != brief { if len(newbrief) > 0 && newbrief != brief {
if utils.CheckValidBrief(newbrief) == false { if utils.CheckValidBrief(newbrief) == false {
utils.ReturnError(w, r, "bad brief format", 405, nil, nil) utils.ReturnError(w, r, "bad brief format", 405, nil, nil)
return return
} }
} }
status := utils.GetStringValue(records["status"]) status := utils.GetStringValue(postData["status"])
module := utils.GetStringValue(records["module"]) module := utils.GetStringValue(postData["module"])
fulldesc := utils.GetStringValue(records["fulldesc"]) fulldesc := utils.GetStringValue(postData["fulldesc"])
shortdesc := utils.GetStringValue(records["shortdesc"]) shortdesc := utils.GetStringValue(postData["shortdesc"])
basistype := utils.GetStringValue(records["basistype"]) basistype := utils.GetStringValue(postData["basistype"])
requiredmsg := utils.GetStringValue(records["requiredmsg"]) requiredmsg := utils.GetStringValue(postData["requiredmsg"])
usercontrol := false usercontrol := false
requiredflag := false requiredflag := false
if status != "disabled" { if status != "disabled" {
status = "active" status = "active"
} }
if value, ok := records["usercontrol"]; ok { if value, ok := postData["usercontrol"]; ok {
if reflect.TypeOf(value).Kind() == reflect.Bool { if reflect.TypeOf(value).Kind() == reflect.Bool {
usercontrol = value.(bool) usercontrol = value.(bool)
} else { } else {
@@ -53,7 +53,7 @@ func (e mainEnv) createLegalBasis(w http.ResponseWriter, r *http.Request, ps htt
} }
} }
} }
if value, ok := records["requiredflag"]; ok { if value, ok := postData["requiredflag"]; ok {
if reflect.TypeOf(value).Kind() == reflect.Bool { if reflect.TypeOf(value).Kind() == reflect.Bool {
requiredflag = value.(bool) requiredflag = value.(bool)
} else { } else {

View File

@@ -172,7 +172,7 @@ func (dbobj dbcon) checkLegalBasis(brief string) (bool, error) {
return true, nil return true, nil
} }
func (dbobj dbcon) getLegalBasis(brief string) (bson.M, error) { func (dbobj dbcon) getLegalBasis(brief string) (map[string]interface{}, error) {
row, err := dbobj.store.GetRecord(storage.TblName.Legalbasis, "brief", brief) row, err := dbobj.store.GetRecord(storage.TblName.Legalbasis, "brief", brief)
if err != nil { if err != nil {
log.Printf("error to find: %s\n", err) log.Printf("error to find: %s\n", err)

View File

@@ -13,7 +13,8 @@ import (
// This function retrieves all requests that require admin approval. This function supports result pager. // This function retrieves all requests that require admin approval. This function supports result pager.
func (e mainEnv) getUserRequests(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { func (e mainEnv) getUserRequests(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
if e.EnforceAuth(w, r, nil) == "" { event := audit.CreateAuditEvent("view user requests", "", "", "")
if e.EnforceAdmin(w, r, event) == "" {
return return
} }
var offset int32 var offset int32
@@ -31,7 +32,7 @@ func (e mainEnv) getUserRequests(w http.ResponseWriter, r *http.Request, ps http
} }
resultJSON, counter, err := e.db.getRequests(status, offset, limit) resultJSON, counter, err := e.db.getRequests(status, offset, limit)
if err != nil { if err != nil {
utils.ReturnError(w, r, "internal error", 405, err, nil) utils.ReturnError(w, r, "internal error", 405, err, event)
return return
} }
w.Header().Set("Content-Type", "application/json; charset=utf-8") w.Header().Set("Content-Type", "application/json; charset=utf-8")
@@ -47,13 +48,11 @@ func (e mainEnv) getCustomUserRequests(w http.ResponseWriter, r *http.Request, p
event := audit.CreateAuditEvent("get user privacy requests", identity, mode, identity) event := audit.CreateAuditEvent("get user privacy requests", identity, mode, identity)
defer func() { SaveAuditEvent(event, e.db, e.conf) }() defer func() { SaveAuditEvent(event, e.db, e.conf) }()
if e.EnforceAuth(w, r, event) == "" { userTOKEN, _, _ := e.getUserToken(w, r, mode, identity, event, true)
return
}
userTOKEN := e.loadUserToken(w, r, mode, identity, event)
if userTOKEN == "" { if userTOKEN == "" {
return return
} }
var offset int32 var offset int32
var limit int32 = 10 var limit int32 = 10
args := r.URL.Query() args := r.URL.Query()
@@ -97,17 +96,22 @@ func (e mainEnv) getUserRequest(w http.ResponseWriter, r *http.Request, ps httpr
if len(userTOKEN) != 0 { if len(userTOKEN) != 0 {
event.Record = userTOKEN event.Record = userTOKEN
} }
if e.EnforceAdmin(w, r, event) == "" { if e.EnforceAuth(w, r, event) == "" {
return return
} }
change := utils.GetStringValue(requestInfo["change"])
appName := utils.GetStringValue(requestInfo["app"]) appName := utils.GetStringValue(requestInfo["app"])
brief := utils.GetStringValue(requestInfo["brief"]) brief := utils.GetStringValue(requestInfo["brief"])
if strings.HasPrefix(action, "plugin") { if strings.HasPrefix(action, "plugin") {
brief = "" brief = ""
} }
userBSON, err := e.db.lookupUserRecord(userTOKEN)
if err != nil {
utils.ReturnError(w, r, "internal error", 405, err, event)
return
}
if len(appName) > 0 { if len(appName) > 0 {
resultJSON, err = e.db.getUserApp(userTOKEN, appName, e.conf) resultJSON, err = e.db.getUserApp(userTOKEN, userBSON, appName, e.conf)
} else if len(brief) > 0 { } else if len(brief) > 0 {
resultJSON, err = e.db.viewAgreementRecord(userTOKEN, brief) resultJSON, err = e.db.viewAgreementRecord(userTOKEN, brief)
} else { } else {
@@ -134,8 +138,15 @@ func (e mainEnv) getUserRequest(w http.ResponseWriter, r *http.Request, ps httpr
if len(resultJSON) > 0 { if len(resultJSON) > 0 {
str = fmt.Sprintf(`%s,"original":%s`, str, resultJSON) str = fmt.Sprintf(`%s,"original":%s`, str, resultJSON)
} }
if len(change) > 0 { if value, ok := requestInfo["change"]; ok {
str = fmt.Sprintf(`%s,"change":%s`, str, change) change := value.(string)
//recBson := bson.M{}
if len(change) > 0 {
change2, _ := e.db.userDecrypt(userBSON, change)
//log.Printf("change: %s", change2)
requestInfo["change"] = change2
str = fmt.Sprintf(`%s,"change":%s`, str, string(change2))
}
} }
str = fmt.Sprintf(`{%s}`, str) str = fmt.Sprintf(`{%s}`, str)
//fmt.Printf("result: %s\n", str) //fmt.Printf("result: %s\n", str)
@@ -154,12 +165,12 @@ func (e mainEnv) approveUserRequest(w http.ResponseWriter, r *http.Request, ps h
if authResult == "" { if authResult == "" {
return return
} }
records, err := utils.GetJSONPostMap(r) postData, err := utils.GetJSONPostMap(r)
if err != nil { if err != nil {
utils.ReturnError(w, r, "failed to decode request body", 405, err, event) utils.ReturnError(w, r, "failed to decode request body", 405, err, event)
return return
} }
reason := utils.GetStringValue(records["reason"]) reason := utils.GetStringValue(postData["reason"])
requestInfo, err := e.db.getRequest(request) requestInfo, err := e.db.getRequest(request)
if err != nil { if err != nil {
utils.ReturnError(w, r, "internal error", 405, err, event) utils.ReturnError(w, r, "internal error", 405, err, event)
@@ -188,6 +199,16 @@ func (e mainEnv) approveUserRequest(w http.ResponseWriter, r *http.Request, ps h
utils.ReturnError(w, r, "not found", 405, err, event) utils.ReturnError(w, r, "not found", 405, err, event)
return return
} }
if value, ok := requestInfo["change"]; ok {
change := value.(string)
//recBson := bson.M{}
if len(change) > 0 {
change2, _ := e.db.userDecrypt(userBSON, change)
//log.Printf("change: %s", change2)
requestInfo["change"] = change2
}
}
if action == "forget-me" { if action == "forget-me" {
email := utils.GetStringValue(userBSON["email"]) email := utils.GetStringValue(userBSON["email"])
if len(email) > 0 { if len(email) > 0 {
@@ -220,7 +241,7 @@ func (e mainEnv) approveUserRequest(w http.ResponseWriter, r *http.Request, ps h
notifyProfileChange(notifyURL, oldJSON, newJSON, "token", userTOKEN) notifyProfileChange(notifyURL, oldJSON, newJSON, "token", userTOKEN)
} else if action == "change-app-data" { } else if action == "change-app-data" {
app := requestInfo["app"].(string) app := requestInfo["app"].(string)
_, err = e.db.updateAppRecord(requestInfo["change"].([]uint8), userTOKEN, app, event, e.conf) _, err = e.db.updateAppRecord(requestInfo["change"].([]uint8), userTOKEN, userBSON, app, event, e.conf)
if err != nil { if err != nil {
utils.ReturnError(w, r, "internal error", 405, err, event) utils.ReturnError(w, r, "internal error", 405, err, event)
return return
@@ -234,6 +255,7 @@ func (e mainEnv) approveUserRequest(w http.ResponseWriter, r *http.Request, ps h
pluginid := requestInfo["brief"].(string) pluginid := requestInfo["brief"].(string)
e.pluginUserDelete(pluginid, userTOKEN) e.pluginUserDelete(pluginid, userTOKEN)
} }
e.db.updateRequestStatus(request, "approved", reason) e.db.updateRequestStatus(request, "approved", reason)
w.Header().Set("Content-Type", "application/json; charset=utf-8") w.Header().Set("Content-Type", "application/json; charset=utf-8")
w.WriteHeader(200) w.WriteHeader(200)
@@ -248,12 +270,12 @@ func (e mainEnv) cancelUserRequest(w http.ResponseWriter, r *http.Request, ps ht
if utils.EnforceUUID(w, request, event) == false { if utils.EnforceUUID(w, request, event) == false {
return return
} }
records, err := utils.GetJSONPostMap(r) postData, err := utils.GetJSONPostMap(r)
if err != nil { if err != nil {
utils.ReturnError(w, r, "failed to decode request body", 405, err, event) utils.ReturnError(w, r, "failed to decode request body", 405, err, event)
return return
} }
reason := utils.GetStringValue(records["reason"]) reason := utils.GetStringValue(postData["reason"])
requestInfo, err := e.db.getRequest(request) requestInfo, err := e.db.getRequest(request)
if err != nil { if err != nil {
utils.ReturnError(w, r, "internal error", 405, err, event) utils.ReturnError(w, r, "internal error", 405, err, event)

View File

@@ -7,24 +7,11 @@ import (
uuid "github.com/hashicorp/go-uuid" uuid "github.com/hashicorp/go-uuid"
"github.com/securitybunker/databunker/src/storage" "github.com/securitybunker/databunker/src/storage"
"github.com/securitybunker/databunker/src/utils"
"go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/bson"
) )
type requestEvent struct { func (dbobj dbcon) saveUserRequest(action, token string, userBSON map[string]interface{}, app, brief string, change []byte, cfg Config) (string, string, error) {
// time for update?
Creationtime int32 `json:"creationtime"`
When int32 `json:"when"`
Token string `json:"token"`
App string `json:"app,omitempty"`
Brief string `json:"brief,omitempty"`
Action string `json:"action"`
Status string `json:"status"`
Change string `json:"change,omitempty"`
Rtoken string `json:"rtoken"`
Reason string `json:"reason"`
}
func (dbobj dbcon) saveUserRequest(action string, token string, app string, brief string, change []byte, cfg Config) (string, string, error) {
now := int32(time.Now().Unix()) now := int32(time.Now().Unix())
bdoc := bson.M{} bdoc := bson.M{}
bdoc["token"] = token bdoc["token"] = token
@@ -39,14 +26,14 @@ func (dbobj dbcon) saveUserRequest(action string, token string, app string, brie
record, err := dbobj.store.LookupRecord(storage.TblName.Requests, bdoc) record, err := dbobj.store.LookupRecord(storage.TblName.Requests, bdoc)
if record != nil { if record != nil {
fmt.Printf("This record already exists.\n") fmt.Printf("This record already exists.\n")
return record["rtoken"].(string), "request-exists", nil return utils.GetUuidString(record["rtoken"]), "request-exists", nil
} }
rtoken, _ := uuid.GenerateUUID() rtoken, _ := uuid.GenerateUUID()
bdoc["when"] = now bdoc["when"] = now
bdoc["rtoken"] = rtoken bdoc["rtoken"] = rtoken
bdoc["creationtime"] = now bdoc["creationtime"] = now
if change != nil { if change != nil {
encodedStr, err := dbobj.userEncrypt(token, change) encodedStr, err := dbobj.userEncrypt(userBSON, change)
if err != nil { if err != nil {
return "", "", err return "", "", err
} }
@@ -71,7 +58,6 @@ func (dbobj dbcon) getRequests(status string, offset int32, limit int32) ([]byte
if count == 0 { if count == 0 {
return []byte("[]"), 0, err return []byte("[]"), 0, err
} }
var results []bson.M
records, err := dbobj.store.GetList(storage.TblName.Requests, "status", status, offset, limit, "when") records, err := dbobj.store.GetList(storage.TblName.Requests, "status", status, offset, limit, "when")
if err != nil { if err != nil {
return nil, 0, err return nil, 0, err
@@ -82,7 +68,8 @@ func (dbobj dbcon) getRequests(status string, offset int32, limit int32) ([]byte
element["more"] = true element["more"] = true
delete(element, "change") delete(element, "change")
} }
results = append(results, element) element["token"] = utils.GetUuidString(element["token"])
element["rtoken"] = utils.GetUuidString(element["rtoken"])
} }
resultJSON, err := json.Marshal(records) resultJSON, err := json.Marshal(records)
@@ -109,6 +96,8 @@ func (dbobj dbcon) getUserRequests(userTOKEN string, offset int32, limit int32)
element["more"] = true element["more"] = true
delete(element, "change") delete(element, "change")
} }
element["token"] = userTOKEN
element["rtoken"] = utils.GetUuidString(element["rtoken"])
results = append(results, element) results = append(results, element)
} }
@@ -119,7 +108,7 @@ func (dbobj dbcon) getUserRequests(userTOKEN string, offset int32, limit int32)
return resultJSON, count, nil return resultJSON, count, nil
} }
func (dbobj dbcon) getRequest(rtoken string) (bson.M, error) { func (dbobj dbcon) getRequest(rtoken string) (map[string]interface{}, error) {
record, err := dbobj.store.GetRecord(storage.TblName.Requests, "rtoken", rtoken) record, err := dbobj.store.GetRecord(storage.TblName.Requests, "rtoken", rtoken)
if err != nil { if err != nil {
return record, err return record, err
@@ -129,19 +118,10 @@ func (dbobj dbcon) getRequest(rtoken string) (bson.M, error) {
} }
//fmt.Printf("request record: %s\n", record) //fmt.Printf("request record: %s\n", record)
userTOKEN := "" userTOKEN := ""
change := ""
if value, ok := record["token"]; ok { userTOKEN = utils.GetUuidString(record["token"])
userTOKEN = value.(string) record["token"] = userTOKEN
} record["rtoken"] = utils.GetUuidString(record["rtoken"])
if value, ok := record["change"]; ok {
change = value.(string)
}
//recBson := bson.M{}
if len(change) > 0 {
change2, _ := dbobj.userDecrypt(userTOKEN, change)
//log.Printf("change: %s", change2)
record["change"] = change2
}
return record, nil return record, nil
} }

View File

@@ -12,7 +12,6 @@ import (
"github.com/securitybunker/databunker/src/audit" "github.com/securitybunker/databunker/src/audit"
"github.com/securitybunker/databunker/src/storage" "github.com/securitybunker/databunker/src/storage"
"github.com/securitybunker/databunker/src/utils" "github.com/securitybunker/databunker/src/utils"
"go.mongodb.org/mongo-driver/bson"
) )
func (e mainEnv) createSession(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { func (e mainEnv) createSession(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
@@ -30,25 +29,25 @@ func (e mainEnv) createSession(w http.ResponseWriter, r *http.Request, ps httpro
if e.EnforceAdmin(w, r, event) == "" { if e.EnforceAdmin(w, r, event) == "" {
return return
} }
records, err := utils.GetJSONPostMap(r) postData, err := utils.GetJSONPostMap(r)
if err != nil { if err != nil {
utils.ReturnError(w, r, "failed to decode request body", 405, err, event) utils.ReturnError(w, r, "failed to decode request body", 405, err, event)
return return
} }
if len(records) == 0 { if len(postData) == 0 {
utils.ReturnError(w, r, "empty body", 405, nil, event) utils.ReturnError(w, r, "empty body", 405, nil, event)
return return
} }
expirationStr := utils.GetStringValue(records["expiration"]) expirationStr := utils.GetStringValue(postData["expiration"])
expiration := utils.SetExpiration(e.conf.Policy.MaxSessionRetentionPeriod, expirationStr) expiration := utils.SetExpiration(e.conf.Policy.MaxSessionRetentionPeriod, expirationStr)
log.Printf("Record expiration: %s", expiration) log.Printf("Record expiration: %s", expiration)
userToken := utils.GetStringValue(records["token"]) userToken := utils.GetStringValue(postData["token"])
userLogin := utils.GetStringValue(records["login"]) userLogin := utils.GetStringValue(postData["login"])
userEmail := utils.GetStringValue(records["email"]) userEmail := utils.GetStringValue(postData["email"])
userPhone := utils.GetStringValue(records["phone"]) userPhone := utils.GetStringValue(postData["phone"])
userCustomIdx := utils.GetStringValue(records["custom"]) userCustomIdx := utils.GetStringValue(postData["custom"])
var userBson bson.M var userBson map[string]interface{}
if len(userLogin) > 0 { if len(userLogin) > 0 {
userBson, err = e.db.lookupUserRecordByIndex("login", userLogin, e.conf) userBson, err = e.db.lookupUserRecordByIndex("login", userLogin, e.conf)
} else if len(userEmail) > 0 { } else if len(userEmail) > 0 {
@@ -67,10 +66,10 @@ func (e mainEnv) createSession(w http.ResponseWriter, r *http.Request, ps httpro
userTOKEN := "" userTOKEN := ""
if userBson != nil { if userBson != nil {
event = audit.CreateAuditEvent("create session", session, "session", session) event = audit.CreateAuditEvent("create session", session, "session", session)
userTOKEN = userBson["token"].(string) userTOKEN = utils.GetUuidString(userBson["token"])
event.Record = userTOKEN event.Record = userTOKEN
} }
jsonData, err := json.Marshal(records) jsonData, err := json.Marshal(postData)
if err != nil { if err != nil {
utils.ReturnError(w, r, "internal error", 405, err, event) utils.ReturnError(w, r, "internal error", 405, err, event)
return return
@@ -109,26 +108,23 @@ func (e mainEnv) newUserSession(w http.ResponseWriter, r *http.Request, ps httpr
event := audit.CreateAuditEvent("create user session by "+mode, identity, mode, identity) event := audit.CreateAuditEvent("create user session by "+mode, identity, mode, identity)
defer func() { SaveAuditEvent(event, e.db, e.conf) }() defer func() { SaveAuditEvent(event, e.db, e.conf) }()
userTOKEN := e.loadUserToken(w, r, mode, identity, event) userTOKEN, _, _ := e.getUserToken(w, r, mode, identity, event, true)
if userTOKEN == "" { if userTOKEN == "" {
return return
} }
if e.EnforceAuth(w, r, event) == "" { postData, err := utils.GetJSONPostMap(r)
return
}
records, err := utils.GetJSONPostMap(r)
if err != nil { if err != nil {
utils.ReturnError(w, r, "failed to decode request body", 405, err, event) utils.ReturnError(w, r, "failed to decode request body", 405, err, event)
return return
} }
if len(records) == 0 { if len(postData) == 0 {
utils.ReturnError(w, r, "empty body", 405, nil, event) utils.ReturnError(w, r, "empty body", 405, nil, event)
return return
} }
expirationStr := utils.GetStringValue(records["expiration"]) expirationStr := utils.GetStringValue(postData["expiration"])
expiration := utils.SetExpiration(e.conf.Policy.MaxSessionRetentionPeriod, expirationStr) expiration := utils.SetExpiration(e.conf.Policy.MaxSessionRetentionPeriod, expirationStr)
log.Printf("Record expiration: %s", expiration) log.Printf("Record expiration: %s", expiration)
jsonData, err := json.Marshal(records) jsonData, err := json.Marshal(postData)
if err != nil { if err != nil {
utils.ReturnError(w, r, "internal error", 405, err, event) utils.ReturnError(w, r, "internal error", 405, err, event)
return return
@@ -154,13 +150,11 @@ func (e mainEnv) getUserSessions(w http.ResponseWriter, r *http.Request, ps http
event := audit.CreateAuditEvent("get all user sessions", identity, mode, identity) event := audit.CreateAuditEvent("get all user sessions", identity, mode, identity)
defer func() { SaveAuditEvent(event, e.db, e.conf) }() defer func() { SaveAuditEvent(event, e.db, e.conf) }()
userTOKEN := e.loadUserToken(w, r, mode, identity, event) userTOKEN, _, _ := e.getUserToken(w, r, mode, identity, event, true)
if userTOKEN == "" { if userTOKEN == "" {
return return
} }
if e.EnforceAuth(w, r, event) == "" {
return
}
e.db.store.DeleteExpired(storage.TblName.Sessions, "token", userTOKEN) e.db.store.DeleteExpired(storage.TblName.Sessions, "token", userTOKEN)
args := r.URL.Query() args := r.URL.Query()
var offset int32 var offset int32

View File

@@ -70,7 +70,7 @@ func (dbobj dbcon) getSession(sessionUUID string) (int32, []byte, string, error)
return 0, nil, "", errors.New("session expired") return 0, nil, "", errors.New("session expired")
} }
when := record["when"].(int32) when := record["when"].(int32)
userTOKEN := record["token"].(string) userTOKEN := utils.GetUuidString(record["token"])
encData0 := record["data"].(string) encData0 := record["data"].(string)
recordKey0 := record["key"].(string) recordKey0 := record["key"].(string)
recordKey, err := base64.StdEncoding.DecodeString(recordKey0) recordKey, err := base64.StdEncoding.DecodeString(recordKey0)

View File

@@ -56,7 +56,7 @@ func TestCreateQuickSession(t *testing.T) {
} }
sessionTOKEN := raw["session"].(string) sessionTOKEN := raw["session"].(string)
time.Sleep(5 * time.Second) time.Sleep(5 * time.Second)
log.Printf("After delay--------") log.Printf("After delay")
raw, _ = helpGetSession(sessionTOKEN) raw, _ = helpGetSession(sessionTOKEN)
log.Printf("Got: %v", raw) log.Printf("Got: %v", raw)
if _, ok := raw["status"]; !ok || raw["status"].(string) == "ok" { if _, ok := raw["status"]; !ok || raw["status"].(string) == "ok" {
@@ -74,6 +74,7 @@ func TestCreateSessionRecord(t *testing.T) {
t.Fatalf("failed to create user") t.Fatalf("failed to create user")
} }
userTOKEN := raw["token"].(string) userTOKEN := raw["token"].(string)
log.Printf("Created user token %s", userTOKEN)
data := `{"expiration":"1m","cookie":"abcdefg","login":"alex"}` data := `{"expiration":"1m","cookie":"abcdefg","login":"alex"}`
sid, _ := uuid.GenerateUUID() sid, _ := uuid.GenerateUUID()
raw, _ = helpCreateSession(sid, data) raw, _ = helpCreateSession(sid, data)

View File

@@ -20,39 +20,28 @@ func (e mainEnv) newSharedRecord(w http.ResponseWriter, r *http.Request, ps http
event := audit.CreateAuditEvent("create shareable record by "+mode, identity, "token", identity) event := audit.CreateAuditEvent("create shareable record by "+mode, identity, "token", identity)
defer func() { SaveAuditEvent(event, e.db, e.conf) }() defer func() { SaveAuditEvent(event, e.db, e.conf) }()
userTOKEN := e.loadUserToken(w, r, mode, identity, event) userTOKEN, _, _ := e.getUserToken(w, r, mode, identity, event, true)
if userTOKEN == "" { if userTOKEN == "" {
return return
} }
if e.EnforceAuth(w, r, event) == "" { postData, err := utils.GetJSONPostMap(r)
return
}
records, err := utils.GetJSONPostMap(r)
if err != nil { if err != nil {
utils.ReturnError(w, r, "failed to decode request body", 405, err, event) utils.ReturnError(w, r, "failed to decode request body", 405, err, event)
return return
} }
fields := "" fields := utils.GetStringValue(postData["fields"])
session := "" session := utils.GetStringValue(postData["session"])
partner := "" partner := utils.GetStringValue(postData["partner"])
appName := "" appName := utils.GetStringValue(postData["app"])
expiration := e.conf.Policy.MaxShareableRecordRetentionPeriod expiration := e.conf.Policy.MaxShareableRecordRetentionPeriod
if value, ok := records["fields"]; ok {
if reflect.TypeOf(value) == reflect.TypeOf("string") { if len(appName) > 0 {
fields = value.(string) appName = strings.ToLower(appName)
if utils.CheckValidApp(appName) == false {
utils.ReturnError(w, r, "unknown app name", 405, nil, event)
} }
} }
if value, ok := records["session"]; ok { if value, ok := postData["expiration"]; ok {
if reflect.TypeOf(value) == reflect.TypeOf("string") {
session = value.(string)
}
}
if value, ok := records["partner"]; ok {
if reflect.TypeOf(value) == reflect.TypeOf("string") {
partner = value.(string)
}
}
if value, ok := records["expiration"]; ok {
if reflect.TypeOf(value) == reflect.TypeOf("string") { if reflect.TypeOf(value) == reflect.TypeOf("string") {
expiration = utils.SetExpiration(e.conf.Policy.MaxShareableRecordRetentionPeriod, value.(string)) expiration = utils.SetExpiration(e.conf.Policy.MaxShareableRecordRetentionPeriod, value.(string))
} else { } else {
@@ -60,17 +49,6 @@ func (e mainEnv) newSharedRecord(w http.ResponseWriter, r *http.Request, ps http
return return
} }
} }
if value, ok := records["app"]; ok {
if reflect.TypeOf(value) == reflect.TypeOf("string") {
appName = strings.ToLower(value.(string))
if len(appName) > 0 && utils.CheckValidApp(appName) == false {
utils.ReturnError(w, r, "unknown app name", 405, nil, event)
}
} else {
// type is different
utils.ReturnError(w, r, "failed to parse app field", 405, nil, event)
}
}
if len(expiration) == 0 { if len(expiration) == 0 {
// using default expiration time for record // using default expiration time for record
expiration = "1m" expiration = "1m"
@@ -106,10 +84,17 @@ func (e mainEnv) getRecord(w http.ResponseWriter, r *http.Request, ps httprouter
if len(recordInfo.token) > 0 { if len(recordInfo.token) > 0 {
event.Record = recordInfo.token event.Record = recordInfo.token
event.App = recordInfo.appName event.App = recordInfo.appName
log.Printf("field to display: %s, user token: %s\n", recordInfo.fields, recordInfo.token) log.Printf("fields to display: %s, user token: %s\n", recordInfo.fields, recordInfo.token)
if len(recordInfo.appName) > 0 { if len(recordInfo.appName) > 0 {
resultJSON, err = e.db.getUserApp(recordInfo.token, recordInfo.appName, e.conf) if len(recordInfo.token) > 0 {
userBSON, err := e.db.lookupUserRecord(recordInfo.token)
if err != nil {
utils.ReturnError(w, r, "internal error", 405, err, event)
return
}
resultJSON, err = e.db.getUserApp(recordInfo.token, userBSON, recordInfo.appName, e.conf)
}
} else if len(recordInfo.session) > 0 { } else if len(recordInfo.session) > 0 {
_, resultJSON, _, err = e.db.getSession(recordInfo.session) _, resultJSON, _, err = e.db.getSession(recordInfo.session)
} else { } else {
@@ -123,7 +108,7 @@ func (e mainEnv) getRecord(w http.ResponseWriter, r *http.Request, ps httprouter
utils.ReturnError(w, r, "not found", 405, err, event) utils.ReturnError(w, r, "not found", 405, err, event)
return return
} }
log.Printf("Full json: %s\n", resultJSON) //log.Printf("Full json: %s\n", resultJSON)
if len(recordInfo.fields) > 0 { if len(recordInfo.fields) > 0 {
raw := make(map[string]interface{}) raw := make(map[string]interface{})
//var newJSON json //var newJSON json

View File

@@ -31,12 +31,6 @@ func (dbobj dbcon) saveSharedRecord(userTOKEN string, fields string, expiration
if err != nil { if err != nil {
return "", err return "", err
} }
// check if user record exists
record, err := dbobj.lookupUserRecord(userTOKEN)
if record == nil || err != nil {
// not found
return "", errors.New("not found")
}
recordUUID, err := uuid.GenerateUUID() recordUUID, err := uuid.GenerateUUID()
if err != nil { if err != nil {
return "", err return "", err
@@ -81,7 +75,7 @@ func (dbobj dbcon) getSharedRecord(recordUUID string) (checkRecordResult, error)
if now > record["endtime"].(int32) { if now > record["endtime"].(int32) {
return result, errors.New("xtoken expired") return result, errors.New("xtoken expired")
} }
result.token = record["token"].(string) result.token = utils.GetUuidString(record["token"])
if value, ok := record["fields"]; ok { if value, ok := record["fields"]; ok {
result.fields = value.(string) result.fields = value.(string)
} }
@@ -91,6 +85,5 @@ func (dbobj dbcon) getSharedRecord(recordUUID string) (checkRecordResult, error)
if value, ok := record["app"]; ok { if value, ok := record["app"]; ok {
result.appName = value.(string) result.appName = value.(string)
} }
return result, nil return result, nil
} }

View File

@@ -18,13 +18,11 @@ func (e mainEnv) userappNew(w http.ResponseWriter, r *http.Request, ps httproute
event := audit.CreateAuditAppEvent("create user app record by "+mode, identity, appName, mode, identity) event := audit.CreateAuditAppEvent("create user app record by "+mode, identity, appName, mode, identity)
defer func() { SaveAuditEvent(event, e.db, e.conf) }() defer func() { SaveAuditEvent(event, e.db, e.conf) }()
userTOKEN := e.loadUserToken(w, r, mode, identity, event) userTOKEN, userBSON, _ := e.getUserToken(w, r, mode, identity, event, true)
if userTOKEN == "" { if userTOKEN == "" {
return return
} }
if e.EnforceAuth(w, r, event) == "" {
return
}
if utils.CheckValidApp(appName) == false { if utils.CheckValidApp(appName) == false {
utils.ReturnError(w, r, "bad appname", 405, nil, event) utils.ReturnError(w, r, "bad appname", 405, nil, event)
return return
@@ -33,22 +31,21 @@ func (e mainEnv) userappNew(w http.ResponseWriter, r *http.Request, ps httproute
utils.ReturnError(w, r, "db limitation", 405, nil, event) utils.ReturnError(w, r, "db limitation", 405, nil, event)
return return
} }
postData, err := utils.GetJSONPostMap(r)
data, err := utils.GetJSONPostMap(r)
if err != nil { if err != nil {
utils.ReturnError(w, r, "failed to decode request body", 405, err, event) utils.ReturnError(w, r, "failed to decode request body", 405, err, event)
return return
} }
if len(data) == 0 { if len(postData) == 0 {
utils.ReturnError(w, r, "empty body", 405, nil, event) utils.ReturnError(w, r, "empty body", 405, nil, event)
return return
} }
jsonData, err := json.Marshal(data) jsonData, err := json.Marshal(postData)
if err != nil { if err != nil {
utils.ReturnError(w, r, "internal error", 405, err, event) utils.ReturnError(w, r, "internal error", 405, err, event)
return return
} }
_, err = e.db.createAppRecord(jsonData, userTOKEN, appName, event, e.conf) _, err = e.db.createAppRecord(jsonData, userTOKEN, userBSON, appName, event, e.conf)
if err != nil { if err != nil {
utils.ReturnError(w, r, "internal error", 405, err, event) utils.ReturnError(w, r, "internal error", 405, err, event)
return return
@@ -63,14 +60,13 @@ func (e mainEnv) userappChange(w http.ResponseWriter, r *http.Request, ps httpro
mode := ps.ByName("mode") mode := ps.ByName("mode")
event := audit.CreateAuditAppEvent("change user app record by "+mode, identity, appName, mode, identity) event := audit.CreateAuditAppEvent("change user app record by "+mode, identity, appName, mode, identity)
defer func() { SaveAuditEvent(event, e.db, e.conf) }() defer func() { SaveAuditEvent(event, e.db, e.conf) }()
userTOKEN := e.loadUserToken(w, r, mode, identity, event)
userTOKEN, userBSON, _ := e.getUserToken(w, r, mode, identity, event, true)
if userTOKEN == "" { if userTOKEN == "" {
return return
} }
authResult := e.EnforceAuth(w, r, event) authResult := e.EnforceAuth(w, r, event)
if authResult == "" {
return
}
if utils.CheckValidApp(appName) == false { if utils.CheckValidApp(appName) == false {
utils.ReturnError(w, r, "bad appname", 405, nil, event) utils.ReturnError(w, r, "bad appname", 405, nil, event)
return return
@@ -85,17 +81,17 @@ func (e mainEnv) userappChange(w http.ResponseWriter, r *http.Request, ps httpro
return return
} }
// make sure userapp exists // make sure userapp exists
resultJSON, err := e.db.getUserApp(userTOKEN, appName, e.conf) // resultJSON, err := e.db.getUserApp(userTOKEN, userBSON, appName, e.conf)
if err != nil { // if err != nil {
utils.ReturnError(w, r, "internal error", 405, err, event) // utils.ReturnError(w, r, "internal error", 405, err, event)
return // return
} // }
if resultJSON == nil { // if resultJSON == nil {
utils.ReturnError(w, r, "not found", 405, nil, event) // utils.ReturnError(w, r, "not found", 405, nil, event)
return // return
} // }
if authResult != "login" { if authResult != "login" {
_, err = e.db.updateAppRecord(jsonData, userTOKEN, appName, event, e.conf) _, err = e.db.updateAppRecord(jsonData, userTOKEN, userBSON, appName, event, e.conf)
if err != nil { if err != nil {
utils.ReturnError(w, r, "internal error", 405, err, event) utils.ReturnError(w, r, "internal error", 405, err, event)
return return
@@ -106,7 +102,7 @@ func (e mainEnv) userappChange(w http.ResponseWriter, r *http.Request, ps httpro
if e.conf.SelfService.AppRecordChange != nil { if e.conf.SelfService.AppRecordChange != nil {
for _, name := range e.conf.SelfService.AppRecordChange { for _, name := range e.conf.SelfService.AppRecordChange {
if utils.StringPatternMatch(strings.ToLower(name), appName) { if utils.StringPatternMatch(strings.ToLower(name), appName) {
_, err = e.db.updateAppRecord(jsonData, userTOKEN, appName, event, e.conf) _, err = e.db.updateAppRecord(jsonData, userTOKEN, userBSON, appName, event, e.conf)
if err != nil { if err != nil {
utils.ReturnError(w, r, "internal error", 405, err, event) utils.ReturnError(w, r, "internal error", 405, err, event)
return return
@@ -116,7 +112,7 @@ func (e mainEnv) userappChange(w http.ResponseWriter, r *http.Request, ps httpro
} }
} }
} }
rtoken, rstatus, err := e.db.saveUserRequest("change-app-data", userTOKEN, appName, "", jsonData, e.conf) rtoken, rstatus, err := e.db.saveUserRequest("change-app-data", userTOKEN, userBSON, appName, "", jsonData, e.conf)
if err != nil { if err != nil {
utils.ReturnError(w, r, "internal error", 405, err, event) utils.ReturnError(w, r, "internal error", 405, err, event)
return return
@@ -131,13 +127,12 @@ func (e mainEnv) userappList(w http.ResponseWriter, r *http.Request, ps httprout
mode := ps.ByName("mode") mode := ps.ByName("mode")
event := audit.CreateAuditEvent("get user app list by "+mode, identity, mode, identity) event := audit.CreateAuditEvent("get user app list by "+mode, identity, mode, identity)
defer func() { SaveAuditEvent(event, e.db, e.conf) }() defer func() { SaveAuditEvent(event, e.db, e.conf) }()
userTOKEN := e.loadUserToken(w, r, mode, identity, event)
userTOKEN, _, _ := e.getUserToken(w, r, mode, identity, event, true)
if userTOKEN == "" { if userTOKEN == "" {
return return
} }
if e.EnforceAuth(w, r, event) == "" {
return
}
result, err := e.db.listUserApps(userTOKEN, e.conf) result, err := e.db.listUserApps(userTOKEN, e.conf)
if err != nil { if err != nil {
utils.ReturnError(w, r, "internal error", 405, err, event) utils.ReturnError(w, r, "internal error", 405, err, event)
@@ -154,18 +149,16 @@ func (e mainEnv) userappGet(w http.ResponseWriter, r *http.Request, ps httproute
mode := ps.ByName("mode") mode := ps.ByName("mode")
event := audit.CreateAuditAppEvent("get user app record by "+mode, identity, appName, mode, identity) event := audit.CreateAuditAppEvent("get user app record by "+mode, identity, appName, mode, identity)
defer func() { SaveAuditEvent(event, e.db, e.conf) }() defer func() { SaveAuditEvent(event, e.db, e.conf) }()
userTOKEN := e.loadUserToken(w, r, mode, identity, event)
userTOKEN, userBSON, _ := e.getUserToken(w, r, mode, identity, event, true)
if userTOKEN == "" { if userTOKEN == "" {
return return
} }
if e.EnforceAuth(w, r, event) == "" {
return
}
if utils.CheckValidApp(appName) == false { if utils.CheckValidApp(appName) == false {
utils.ReturnError(w, r, "bad appname", 405, nil, event) utils.ReturnError(w, r, "bad appname", 405, nil, event)
return return
} }
resultJSON, err := e.db.getUserApp(userTOKEN, appName, e.conf) resultJSON, err := e.db.getUserApp(userTOKEN, userBSON, appName, e.conf)
if err != nil { if err != nil {
utils.ReturnError(w, r, "internal error", 405, err, event) utils.ReturnError(w, r, "internal error", 405, err, event)
return return
@@ -186,18 +179,16 @@ func (e mainEnv) userappDelete(w http.ResponseWriter, r *http.Request, ps httpro
mode := ps.ByName("mode") mode := ps.ByName("mode")
event := audit.CreateAuditAppEvent("delete user app record by "+mode, identity, appName, mode, identity) event := audit.CreateAuditAppEvent("delete user app record by "+mode, identity, appName, mode, identity)
defer func() { SaveAuditEvent(event, e.db, e.conf) }() defer func() { SaveAuditEvent(event, e.db, e.conf) }()
userTOKEN := e.loadUserToken(w, r, mode, identity, event)
userTOKEN, _, _ := e.getUserToken(w, r, mode, identity, event, true)
if userTOKEN == "" { if userTOKEN == "" {
return return
} }
if e.EnforceAuth(w, r, event) == "" {
return
}
if utils.CheckValidApp(appName) == false { if utils.CheckValidApp(appName) == false {
utils.ReturnError(w, r, "bad appname", 405, nil, event) utils.ReturnError(w, r, "bad appname", 405, nil, event)
return return
} }
e.db.deleteUserApp(userTOKEN, appName, e.conf) e.db.deleteUserApp(userTOKEN, appName, e.conf)
finalJSON := fmt.Sprintf(`{"status":"ok","token":"%s"}`, userTOKEN) finalJSON := fmt.Sprintf(`{"status":"ok","token":"%s"}`, userTOKEN)

View File

@@ -14,7 +14,7 @@ import (
"go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/bson"
) )
func (dbobj dbcon) getUserApp(userTOKEN string, appName string, conf Config) ([]byte, error) { func (dbobj dbcon) getUserApp(userTOKEN string, userBSON map[string]interface{}, appName string, conf Config) ([]byte, error) {
appNameFull := "app_" + appName appNameFull := "app_" + appName
var record bson.M var record bson.M
var err error var err error
@@ -30,7 +30,7 @@ func (dbobj dbcon) getUserApp(userTOKEN string, appName string, conf Config) ([]
return nil, nil return nil, nil
} }
encData0 := record["data"].(string) encData0 := record["data"].(string)
return dbobj.userDecrypt(userTOKEN, encData0) return dbobj.userDecrypt(userBSON, encData0)
} }
func (dbobj dbcon) deleteUserApp(userTOKEN string, appName string, conf Config) { func (dbobj dbcon) deleteUserApp(userTOKEN string, appName string, conf Config) {
@@ -55,10 +55,10 @@ func (dbobj dbcon) deleteUserApps(userTOKEN string, conf Config) {
} }
} }
func (dbobj dbcon) createAppRecord(jsonData []byte, userTOKEN string, appName string, event *audit.AuditEvent, conf Config) (string, error) { func (dbobj dbcon) createAppRecord(jsonData []byte, userTOKEN string, userBSON map[string]interface{}, appName string, event *audit.AuditEvent, conf Config) (string, error) {
appNameFull := "app_" + appName appNameFull := "app_" + appName
//log.Printf("Going to create app record: %s\n", appName) //log.Printf("Going to create app record: %s\n", appName)
encodedStr, err := dbobj.userEncrypt(userTOKEN, jsonData) encodedStr, err := dbobj.userEncrypt(userBSON, jsonData)
if err != nil { if err != nil {
return userTOKEN, err return userTOKEN, err
} }
@@ -104,16 +104,11 @@ func (dbobj dbcon) createAppRecord(jsonData []byte, userTOKEN string, appName st
return userTOKEN, err return userTOKEN, err
} }
func (dbobj dbcon) updateAppRecord(jsonDataPatch []byte, userTOKEN string, appName string, event *audit.AuditEvent, conf Config) (string, error) { func (dbobj dbcon) updateAppRecord(jsonDataPatch []byte, userTOKEN string, userBSON map[string]interface{}, appName string, event *audit.AuditEvent, conf Config) (string, error) {
//_, err = collection.InsertOne(context.TODO(), bson.M{"name": "The Go Language2", "genre": "Coding", "authorId": "4"}) //_, err = collection.InsertOne(context.TODO(), bson.M{"name": "The Go Language2", "genre": "Coding", "authorId": "4"})
appNameFull := "app_" + appName appNameFull := "app_" + appName
userBson, err := dbobj.lookupUserRecord(userTOKEN)
if userBson == nil || err != nil {
// not found
return userTOKEN, err
}
// get user key // get user key
userKey := userBson["key"].(string) userKey := userBSON["key"].(string)
recordKey, err := base64.StdEncoding.DecodeString(userKey) recordKey, err := base64.StdEncoding.DecodeString(userKey)
if err != nil { if err != nil {
return userTOKEN, err return userTOKEN, err
@@ -196,11 +191,6 @@ func (dbobj dbcon) updateAppRecord(jsonDataPatch []byte, userTOKEN string, appNa
// go over app collections and check if we have user record inside // go over app collections and check if we have user record inside
func (dbobj dbcon) listUserApps(userTOKEN string, conf Config) ([]byte, error) { func (dbobj dbcon) listUserApps(userTOKEN string, conf Config) ([]byte, error) {
//_, err = collection.InsertOne(context.TODO(), bson.M{"name": "The Go Language2", "genre": "Coding", "authorId": "4"}) //_, err = collection.InsertOne(context.TODO(), bson.M{"name": "The Go Language2", "genre": "Coding", "authorId": "4"})
record, err := dbobj.lookupUserRecord(userTOKEN)
if record == nil || err != nil {
// not found
return nil, err
}
var result []string var result []string
if conf.Generic.UseSeparateAppTables == true { if conf.Generic.UseSeparateAppTables == true {
allCollections, err := dbobj.store.GetAllTables() allCollections, err := dbobj.store.GetAllTables()

View File

@@ -10,7 +10,6 @@ import (
"github.com/securitybunker/databunker/src/audit" "github.com/securitybunker/databunker/src/audit"
"github.com/securitybunker/databunker/src/storage" "github.com/securitybunker/databunker/src/storage"
"github.com/securitybunker/databunker/src/utils" "github.com/securitybunker/databunker/src/utils"
"go.mongodb.org/mongo-driver/bson"
) )
func (e mainEnv) userCreate(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { func (e mainEnv) userCreate(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
@@ -19,7 +18,7 @@ func (e mainEnv) userCreate(w http.ResponseWriter, r *http.Request, ps httproute
if e.conf.Generic.CreateUserWithoutAccessToken == false { if e.conf.Generic.CreateUserWithoutAccessToken == false {
// anonymous user can not create user record, check token // anonymous user can not create user record, check token
if e.EnforceAuth(w, r, event) == "" { if e.EnforceAdmin(w, r, event) == "" {
log.Println("Failed to create user, access denied, try to configure Create_user_without_access_token") log.Println("Failed to create user, access denied, try to configure Create_user_without_access_token")
return return
} }
@@ -124,41 +123,23 @@ func (e mainEnv) userCreate(w http.ResponseWriter, r *http.Request, ps httproute
} }
func (e mainEnv) userGet(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { func (e mainEnv) userGet(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
var err error
var resultJSON []byte
identity := ps.ByName("identity") identity := ps.ByName("identity")
mode := ps.ByName("mode") mode := ps.ByName("mode")
event := audit.CreateAuditEvent("get user record by "+mode, identity, mode, identity) event := audit.CreateAuditEvent("get user record by "+mode, identity, mode, identity)
defer func() { SaveAuditEvent(event, e.db, e.conf) }() defer func() { SaveAuditEvent(event, e.db, e.conf) }()
if utils.ValidateMode(mode) == false { userTOKEN, userBSON, _ := e.getUserToken(w, r, mode, identity, event, true)
utils.ReturnError(w, r, "bad mode", 405, nil, event) if userTOKEN == "" {
return
}
userTOKEN := ""
authResult := ""
if mode == "token" {
if utils.EnforceUUID(w, identity, event) == false {
return
}
resultJSON, err = e.db.getUserJSON(identity)
userTOKEN = identity
} else {
resultJSON, userTOKEN, err = e.db.getUserJSONByIndex(identity, mode, e.conf)
event.Record = userTOKEN
}
if err != nil {
utils.ReturnError(w, r, "internal error", 405, err, event)
return
}
authResult = e.EnforceAuth(w, r, event)
if authResult == "" {
return return
} }
resultJSON, _ := e.db.userProfileDecrypt(userBSON)
if resultJSON == nil { if resultJSON == nil {
utils.ReturnError(w, r, "record not found", 405, nil, event) resultJSON = []byte("{}")
return
} }
// if resultJSON == nil {
// utils.ReturnError(w, r, "record not found", 405, nil, event)
// return
// }
finalJSON := fmt.Sprintf(`{"status":"ok","token":"%s","data":%s}`, userTOKEN, resultJSON) finalJSON := fmt.Sprintf(`{"status":"ok","token":"%s","data":%s}`, userTOKEN, resultJSON)
//fmt.Printf("record: %s\n", finalJSON) //fmt.Printf("record: %s\n", finalJSON)
//fmt.Fprintf(w, "<html><head><title>title</title></head>") //fmt.Fprintf(w, "<html><head><title>title</title></head>")
@@ -173,48 +154,33 @@ func (e mainEnv) userChange(w http.ResponseWriter, r *http.Request, ps httproute
event := audit.CreateAuditEvent("change user record by "+mode, identity, mode, identity) event := audit.CreateAuditEvent("change user record by "+mode, identity, mode, identity)
defer func() { SaveAuditEvent(event, e.db, e.conf) }() defer func() { SaveAuditEvent(event, e.db, e.conf) }()
if utils.ValidateMode(mode) == false { userTOKEN, userBSON, _ := e.getUserToken(w, r, mode, identity, event, true)
utils.ReturnError(w, r, "bad index", 405, nil, event) if userTOKEN == "" {
return
}
jsonData, err := utils.GetJSONPostData(r)
if err != nil {
utils.ReturnError(w, r, "failed to decode request body", 405, err, event)
return
}
if jsonData == nil {
utils.ReturnError(w, r, "empty request body", 405, nil, event)
return
}
userTOKEN := ""
var userJSON []byte
var userBSON bson.M
if mode == "token" {
if utils.EnforceUUID(w, identity, event) == false {
return
}
userTOKEN = identity
userJSON, userBSON, err = e.db.getUser(identity)
} else {
userJSON, userTOKEN, userBSON, err = e.db.getUserByIndex(identity, mode, e.conf)
event.Record = userTOKEN
}
if err != nil {
utils.ReturnError(w, r, "internal error", 405, err, event)
return return
} }
userJSON, _ := e.db.userProfileDecrypt(userBSON)
if userJSON == nil { if userJSON == nil {
utils.ReturnError(w, r, "user record not found", 405, nil, event) utils.ReturnError(w, r, "user record not found", 405, nil, event)
return return
} }
postData, err := utils.GetJSONPostData(r)
if err != nil {
utils.ReturnError(w, r, "failed to decode request body", 405, err, event)
return
}
if postData == nil {
utils.ReturnError(w, r, "empty request body", 405, nil, event)
return
}
authResult := e.EnforceAuth(w, r, event) authResult := e.EnforceAuth(w, r, event)
if authResult == "" { if authResult == "" {
return return
} }
adminRecordChanged := false adminRecordChanged := false
if UserSchemaEnabled() { if UserSchemaEnabled() {
adminRecordChanged, err = e.db.validateUserRecordChange(userJSON, jsonData, userTOKEN, authResult) adminRecordChanged, err = e.db.validateUserRecordChange(userJSON, postData, userTOKEN, authResult)
if err != nil { if err != nil {
utils.ReturnError(w, r, "schema validation error: "+err.Error(), 405, err, event) utils.ReturnError(w, r, "schema validation error: "+err.Error(), 405, err, event)
return return
@@ -223,7 +189,7 @@ func (e mainEnv) userChange(w http.ResponseWriter, r *http.Request, ps httproute
if authResult == "login" { if authResult == "login" {
event.Title = "user change-profile request" event.Title = "user change-profile request"
if e.conf.SelfService.UserRecordChange == false || adminRecordChanged == true { if e.conf.SelfService.UserRecordChange == false || adminRecordChanged == true {
rtoken, rstatus, err := e.db.saveUserRequest("change-profile", userTOKEN, "", "", jsonData, e.conf) rtoken, rstatus, err := e.db.saveUserRequest("change-profile", userTOKEN, userBSON, "", "", postData, e.conf)
if err != nil { if err != nil {
utils.ReturnError(w, r, "internal error", 405, err, event) utils.ReturnError(w, r, "internal error", 405, err, event)
return return
@@ -234,7 +200,7 @@ func (e mainEnv) userChange(w http.ResponseWriter, r *http.Request, ps httproute
return return
} }
} }
oldJSON, newJSON, lookupErr, err := e.db.updateUserRecord(jsonData, userTOKEN, userBSON, event, e.conf) oldJSON, newJSON, lookupErr, err := e.db.updateUserRecord(postData, userTOKEN, userBSON, event, e.conf)
if lookupErr { if lookupErr {
utils.ReturnError(w, r, "record not found", 405, errors.New("record not found"), event) utils.ReturnError(w, r, "record not found", 405, errors.New("record not found"), event)
return return
@@ -255,37 +221,28 @@ func (e mainEnv) userDelete(w http.ResponseWriter, r *http.Request, ps httproute
event := audit.CreateAuditEvent("delete user record by "+mode, identity, mode, identity) event := audit.CreateAuditEvent("delete user record by "+mode, identity, mode, identity)
defer func() { SaveAuditEvent(event, e.db, e.conf) }() defer func() { SaveAuditEvent(event, e.db, e.conf) }()
if utils.ValidateMode(mode) == false { strictCheck := true
utils.ReturnError(w, r, "bad mode", 405, nil, event) if mode == "email" {
strictCheck = false
}
userTOKEN, userBSON, err := e.getUserToken(w, r, mode, identity, event, strictCheck)
if strictCheck == true && userTOKEN == "" {
return return
} }
var err error
var userBSON bson.M
var userJSON []byte
userTOKEN := identity
if mode == "token" {
if utils.EnforceUUID(w, identity, event) == false {
return
}
userJSON, userBSON, err = e.db.getUser(identity)
} else {
userJSON, userTOKEN, userBSON, err = e.db.getUserByIndex(identity, mode, e.conf)
event.Record = userTOKEN
}
if err != nil { if err != nil {
utils.ReturnError(w, r, "internal error", 405, nil, event)
return return
} }
authResult := e.EnforceAuth(w, r, event) authResult := e.EnforceAuth(w, r, event)
if authResult == "" { if authResult == "" {
return return
} }
if userJSON == nil { if len(userTOKEN) == 0 {
if authResult == "root" && mode == "email" { if authResult == "root" && mode == "email" {
e.globalUserDelete(identity) e.globalUserDelete(identity)
w.Header().Set("Content-Type", "application/json; charset=utf-8") w.Header().Set("Content-Type", "application/json; charset=utf-8")
w.WriteHeader(200) w.WriteHeader(200)
fmt.Fprintf(w, `{"status":"ok","result":"done"}`) fmt.Fprintf(w, `{"status":"ok","result":"done"}`)
return
} }
utils.ReturnError(w, r, "record not found", 405, nil, event) utils.ReturnError(w, r, "record not found", 405, nil, event)
return return
@@ -294,7 +251,7 @@ func (e mainEnv) userDelete(w http.ResponseWriter, r *http.Request, ps httproute
if authResult == "login" { if authResult == "login" {
event.Title = "user forget-me request" event.Title = "user forget-me request"
if e.conf.SelfService.ForgetMe == false { if e.conf.SelfService.ForgetMe == false {
rtoken, rstatus, err := e.db.saveUserRequest("forget-me", userTOKEN, "", "", nil, e.conf) rtoken, rstatus, err := e.db.saveUserRequest("forget-me", userTOKEN, userBSON, "", "", nil, e.conf)
if err != nil { if err != nil {
utils.ReturnError(w, r, "internal error", 405, err, event) utils.ReturnError(w, r, "internal error", 405, err, event)
return return
@@ -305,9 +262,19 @@ func (e mainEnv) userDelete(w http.ResponseWriter, r *http.Request, ps httproute
return return
} }
} }
email := utils.GetStringValue(userBSON["email"]) // decrypt user!
if len(email) > 0 { userJSON, err := e.db.userProfileDecrypt(userBSON)
e.globalUserDelete(email) if err != nil {
utils.ReturnError(w, r, "internal error", 405, err, event)
return
}
if userJSON == nil {
userJSON = []byte("{}")
} else {
email := utils.GetStringValue(userBSON["email"])
if len(email) > 0 {
e.globalUserDelete(email)
}
} }
//fmt.Printf("deleting user %s\n", userTOKEN) //fmt.Printf("deleting user %s\n", userTOKEN)
_, err = e.db.deleteUserRecord(userJSON, userTOKEN, e.conf) _, err = e.db.deleteUserRecord(userJSON, userTOKEN, e.conf)
@@ -347,7 +314,7 @@ func (e mainEnv) userPrelogin(w http.ResponseWriter, r *http.Request, ps httprou
return return
} }
if userBson != nil { if userBson != nil {
userTOKEN := userBson["token"].(string) userTOKEN := utils.GetUuidString(userBson["token"])
event.Record = userTOKEN event.Record = userTOKEN
if identity == "4444" || identity == "test@securitybunker.io" { if identity == "4444" || identity == "test@securitybunker.io" {
// check if it is demo account. // check if it is demo account.
@@ -398,7 +365,7 @@ func (e mainEnv) userLogin(w http.ResponseWriter, r *http.Request, ps httprouter
return return
} }
userTOKEN := userBson["token"].(string) userTOKEN := utils.GetUuidString(userBson["token"])
event.Record = userTOKEN event.Record = userTOKEN
tmpCode := int32(0) tmpCode := int32(0)
if _, ok := userBson["tempcode"]; ok { if _, ok := userBson["tempcode"]; ok {
@@ -407,7 +374,7 @@ func (e mainEnv) userLogin(w http.ResponseWriter, r *http.Request, ps httprouter
if tmp == tmpCode { if tmp == tmpCode {
// user ented correct key // user ented correct key
// generate temp user access code // generate temp user access code
xtoken, hashedToken, err := e.db.generateUserLoginXtoken(userTOKEN) xtoken, hashedToken, err := e.db.genUserLoginXtoken(userTOKEN)
//fmt.Printf("generate user access token: %s\n", xtoken) //fmt.Printf("generate user access token: %s\n", xtoken)
if err != nil { if err != nil {
utils.ReturnError(w, r, "internal error", 405, err, event) utils.ReturnError(w, r, "internal error", 405, err, event)

View File

@@ -18,7 +18,6 @@ import (
) )
func (dbobj dbcon) createUserRecord(parsedData utils.UserJSONStruct, event *audit.AuditEvent) (string, error) { func (dbobj dbcon) createUserRecord(parsedData utils.UserJSONStruct, event *audit.AuditEvent) (string, error) {
var userTOKEN string
//var bdoc interface{} //var bdoc interface{}
bdoc := bson.M{} bdoc := bson.M{}
userTOKEN, err := uuid.GenerateUUID() userTOKEN, err := uuid.GenerateUUID()
@@ -297,11 +296,14 @@ func (dbobj dbcon) updateUserRecordDo(jsonDataPatch []byte, userTOKEN string, ol
return decrypted, newJSON, false, nil return decrypted, newJSON, false, nil
} }
func (dbobj dbcon) lookupUserRecord(userTOKEN string) (bson.M, error) { func (dbobj dbcon) lookupUserRecord(userTOKEN string) (map[string]interface{}, error) {
if len(userTOKEN) == 0 {
return nil, nil
}
return dbobj.store.GetRecord(storage.TblName.Users, "token", userTOKEN) return dbobj.store.GetRecord(storage.TblName.Users, "token", userTOKEN)
} }
func (dbobj dbcon) lookupUserRecordByIndex(indexName string, indexValue string, conf Config) (bson.M, error) { func (dbobj dbcon) lookupUserRecordByIndex(indexName string, indexValue string, conf Config) (map[string]interface{}, error) {
if indexName == "email" { if indexName == "email" {
indexValue = utils.NormalizeEmail(indexValue) indexValue = utils.NormalizeEmail(indexValue)
} else if indexName == "phone" { } else if indexName == "phone" {
@@ -319,65 +321,29 @@ func (dbobj dbcon) lookupUserRecordByIndex(indexName string, indexValue string,
} }
func (dbobj dbcon) getUserJSON(userTOKEN string) ([]byte, error) { func (dbobj dbcon) getUserJSON(userTOKEN string) ([]byte, error) {
userBson, err := dbobj.lookupUserRecord(userTOKEN) userBSON, err := dbobj.lookupUserRecord(userTOKEN)
if userBson == nil || err != nil { if userBSON == nil || err != nil {
// not found // not found
return nil, err return nil, err
} }
if _, ok := userBson["key"]; !ok { decrypted, err := dbobj.userProfileDecrypt(userBSON)
if decrypted == nil {
return []byte("{}"), nil return []byte("{}"), nil
} }
userKey := userBson["key"].(string)
userKeyBinary, err := base64.StdEncoding.DecodeString(userKey)
if err != nil {
return nil, err
}
var decrypted []byte
if _, ok := userBson["data"]; ok {
encData0 := userBson["data"].(string)
if len(encData0) > 0 {
encData, err := base64.StdEncoding.DecodeString(encData0)
if err != nil {
return nil, err
}
decrypted, err = utils.Decrypt(dbobj.masterKey, userKeyBinary, encData)
if err != nil {
return nil, err
}
}
}
return decrypted, err return decrypted, err
} }
func (dbobj dbcon) getUser(userTOKEN string) ([]byte, bson.M, error) { func (dbobj dbcon) getUser(userTOKEN string) ([]byte, map[string]interface{}, error) {
userBson, err := dbobj.lookupUserRecord(userTOKEN) userBSON, err := dbobj.lookupUserRecord(userTOKEN)
if userBson == nil || err != nil { if userBSON == nil || err != nil {
// not found // not found
return nil, nil, err return nil, nil, err
} }
if _, ok := userBson["key"]; !ok { decrypted, err := dbobj.userProfileDecrypt(userBSON)
return []byte("{}"), userBson, nil if decrypted == nil {
return []byte("{}"), userBSON, err
} }
userKey := userBson["key"].(string) return decrypted, userBSON, err
userKeyBinary, err := base64.StdEncoding.DecodeString(userKey)
if err != nil {
return nil, nil, err
}
var decrypted []byte
if _, ok := userBson["data"]; ok {
encData0 := userBson["data"].(string)
if len(encData0) > 0 {
encData, err := base64.StdEncoding.DecodeString(encData0)
if err != nil {
return nil, nil, err
}
decrypted, err = utils.Decrypt(dbobj.masterKey, userKeyBinary, encData)
if err != nil {
return nil, nil, err
}
}
}
return decrypted, userBson, err
} }
func (dbobj dbcon) getUsers(offset int32, limit int32) ([]byte, int64, error) { func (dbobj dbcon) getUsers(offset int32, limit int32) ([]byte, int64, error) {
@@ -394,37 +360,20 @@ func (dbobj dbcon) getUsers(offset int32, limit int32) ([]byte, int64, error) {
return nil, 0, err return nil, 0, err
} }
for _, element := range records { for _, element := range records {
rec := make(map[string]interface{}) decrypted, err := dbobj.userProfileDecrypt(element)
userKey := element["key"].(string) if err == nil {
userKeyBinary, err := base64.StdEncoding.DecodeString(userKey) rec := make(map[string]interface{})
if err != nil { userTOKEN := element["token"].(string)
return nil, 0, err rec["private"] = decrypted
}
userTOKEN := element["token"].(string) expstatus := utils.GetStringValue(element["expstatus"])
encData0 := element["data"].(string) if len(expstatus) > 0 {
if len(encData0) > 0 { rec["endtime"] = element["endtime"]
encData, err := base64.StdEncoding.DecodeString(encData0) rec["expstatus"] = expstatus
if err != nil {
return nil, 0, err
} }
decrypted, err := utils.Decrypt(dbobj.masterKey, userKeyBinary, encData) rec["token"] = userTOKEN
if err != nil { results = append(results, rec)
return nil, 0, err
}
var raw2 map[string]interface{}
err = json.Unmarshal(decrypted, &raw2)
if err != nil {
return nil, 0, err
}
rec["private"] = raw2
} }
expstatus := utils.GetStringValue(element["expstatus"])
if len(expstatus) > 0 {
rec["endtime"] = element["endtime"]
rec["expstatus"] = expstatus
}
rec["token"] = userTOKEN
results = append(results, rec)
} }
resultJSON, err := json.Marshal(results) resultJSON, err := json.Marshal(results)
if err != nil { if err != nil {
@@ -457,62 +406,28 @@ func (dbobj dbcon) dumpUserPII(email string, conf Config) (string, error) {
} }
func (dbobj dbcon) getUserJSONByIndex(indexValue string, indexName string, conf Config) ([]byte, string, error) { func (dbobj dbcon) getUserJSONByIndex(indexValue string, indexName string, conf Config) ([]byte, string, error) {
userBson, err := dbobj.lookupUserRecordByIndex(indexName, indexValue, conf) userBSON, err := dbobj.lookupUserRecordByIndex(indexName, indexValue, conf)
if userBson == nil || err != nil { if userBSON == nil || err != nil {
return nil, "", err return nil, "", err
} }
userKey := userBson["key"].(string) userTOKEN := utils.GetUuidString(userBSON["token"])
userKeyBinary, err := base64.StdEncoding.DecodeString(userKey) decrypted, err := dbobj.userProfileDecrypt(userBSON)
if err != nil { return decrypted, userTOKEN, err
return nil, "", err
}
var decrypted []byte
if _, ok := userBson["data"]; ok {
encData0 := userBson["data"].(string)
if len(encData0) > 0 {
encData, err := base64.StdEncoding.DecodeString(encData0)
if err != nil {
return nil, "", err
}
decrypted, err = utils.Decrypt(dbobj.masterKey, userKeyBinary, encData)
if err != nil {
return nil, "", err
}
}
}
return decrypted, userBson["token"].(string), err
} }
func (dbobj dbcon) getUserByIndex(indexValue string, indexName string, conf Config) ([]byte, string, bson.M, error) { func (dbobj dbcon) getUserByIndex(indexValue string, indexName string, conf Config) ([]byte, string, map[string]interface{}, error) {
userBson, err := dbobj.lookupUserRecordByIndex(indexName, indexValue, conf) userBSON, err := dbobj.lookupUserRecordByIndex(indexName, indexValue, conf)
if userBson == nil || err != nil { if userBSON == nil || err != nil {
return nil, "", nil, err return nil, "", nil, err
} }
userKey := userBson["key"].(string) userTOKEN := utils.GetUuidString(userBSON["token"])
userKeyBinary, err := base64.StdEncoding.DecodeString(userKey) decrypted, err := dbobj.userProfileDecrypt(userBSON)
if err != nil { return decrypted, userTOKEN, userBSON, err
return nil, "", nil, err
}
var decrypted []byte
if _, ok := userBson["data"]; ok {
encData0 := userBson["data"].(string)
if len(encData0) > 0 {
encData, err := base64.StdEncoding.DecodeString(encData0)
if err != nil {
return nil, "", nil, err
}
decrypted, err = utils.Decrypt(dbobj.masterKey, userKeyBinary, encData)
if err != nil {
return nil, "", nil, err
}
}
}
return decrypted, userBson["token"].(string), userBson, err
} }
func (dbobj dbcon) deleteUserRecord(userJSON []byte, userTOKEN string, conf Config) (bool, error) { func (dbobj dbcon) deleteUserRecord(userJSON []byte, userTOKEN string, conf Config) (bool, error) {
dbobj.deleteUserApps(userTOKEN, conf) dbobj.deleteUserApps(userTOKEN, conf)
//delete in audit // TODO: delete in audit?
dbobj.store.DeleteRecord(storage.TblName.Audit, "record", userTOKEN) dbobj.store.DeleteRecord(storage.TblName.Audit, "record", userTOKEN)
dbobj.store.DeleteRecord(storage.TblName.Sessions, "token", userTOKEN) dbobj.store.DeleteRecord(storage.TblName.Sessions, "token", userTOKEN)
@@ -600,16 +515,12 @@ func (dbobj dbcon) wipeRecord(userTOKEN string) (bool, error) {
} }
*/ */
func (dbobj dbcon) userEncrypt(userTOKEN string, data []byte) (string, error) { func (dbobj dbcon) userEncrypt(userBSON map[string]interface{}, data []byte) (string, error) {
userBson, err := dbobj.lookupUserRecord(userTOKEN) userKey, ok := userBSON["key"].(string)
if userBson == nil || err != nil { if !ok {
return "", errors.New("not found")
}
if _, ok := userBson["key"]; !ok {
// user might be deleted already // user might be deleted already
return "", errors.New("not found") return "", errors.New("not found")
} }
userKey := userBson["key"].(string)
userKeyBinary, err := base64.StdEncoding.DecodeString(userKey) userKeyBinary, err := base64.StdEncoding.DecodeString(userKey)
if err != nil { if err != nil {
return "", err return "", err
@@ -622,16 +533,41 @@ func (dbobj dbcon) userEncrypt(userTOKEN string, data []byte) (string, error) {
return encodedStr, nil return encodedStr, nil
} }
func (dbobj dbcon) userDecrypt(userTOKEN, src string) ([]byte, error) { func (dbobj dbcon) userProfileDecrypt(userBSON map[string]interface{}) ([]byte, error) {
userBson, err := dbobj.lookupUserRecord(userTOKEN) userKey, ok := userBSON["key"].(string)
if userBson == nil || err != nil { if !ok {
return nil, errors.New("not found") // user might be deleted already
} return nil, errors.New("not found")
if _, ok := userBson["key"]; !ok { }
userKeyBinary, err := base64.StdEncoding.DecodeString(userKey)
if err != nil {
return nil, err
}
data, ok := userBSON["data"].(string)
if !ok {
// user might be deleted already
return nil, errors.New("not found")
}
if len(data) == 0 {
return nil, errors.New("not found")
}
encData, err := base64.StdEncoding.DecodeString(data)
if err != nil {
return nil, err
}
if len(encData) == 0 {
return nil, errors.New("not found")
}
decrypted, err := utils.Decrypt(dbobj.masterKey, userKeyBinary, encData)
return decrypted, err
}
func (dbobj dbcon) userDecrypt(userBSON map[string]interface{}, src string) ([]byte, error) {
userKey, ok := userBSON["key"].(string)
if !ok {
// user might be deleted already // user might be deleted already
return nil, errors.New("not found") return nil, errors.New("not found")
} }
userKey := userBson["key"].(string)
userKeyBinary, err := base64.StdEncoding.DecodeString(userKey) userKeyBinary, err := base64.StdEncoding.DecodeString(userKey)
if err != nil { if err != nil {
return nil, err return nil, err
@@ -644,16 +580,8 @@ func (dbobj dbcon) userDecrypt(userTOKEN, src string) ([]byte, error) {
return decrypted, err return decrypted, err
} }
func (dbobj dbcon) userDecrypt2(userTOKEN, src string, src2 string) ([]byte, []byte, error) { func (dbobj dbcon) userDecrypt2(userBSON map[string]interface{}, src string, src2 string) ([]byte, []byte, error) {
userBson, err := dbobj.lookupUserRecord(userTOKEN) userKey := userBSON["key"].(string)
if userBson == nil || err != nil {
return nil, nil, errors.New("not found")
}
if _, ok := userBson["key"]; !ok {
// user might be deleted already
return nil, nil, errors.New("not found")
}
userKey := userBson["key"].(string)
userKeyBinary, err := base64.StdEncoding.DecodeString(userKey) userKeyBinary, err := base64.StdEncoding.DecodeString(userKey)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err

View File

@@ -118,7 +118,10 @@ func TestCreateUpdateUser(t *testing.T) {
t.Fatalf("Failed to get audit event/s\n") t.Fatalf("Failed to get audit event/s\n")
} }
records := raw["rows"].([]interface{}) records := raw["rows"].([]interface{})
if raw["total"].(float64) != 6 { for num, r := range records {
log.Printf("audit record %d %v", num, r)
}
if raw["total"].(float64) != 8 {
t.Fatalf("Wrong number of audit event/s\n") t.Fatalf("Wrong number of audit event/s\n")
} }
if len(records) != 1 { if len(records) != 1 {

View File

@@ -50,13 +50,12 @@ func (dbobj dbcon) createRootXtoken(customRootXtoken string) (string, error) {
return rootToken, nil return rootToken, nil
} }
func (dbobj dbcon) generateUserLoginXtoken(userTOKEN string) (string, string, error) { func (dbobj dbcon) genUserLoginXtoken(userTOKEN string) (string, string, error) {
// check if user record exists // record, err := dbobj.lookupUserRecord(userTOKEN)
record, err := dbobj.lookupUserRecord(userTOKEN) // if record == nil || err != nil {
if record == nil || err != nil { // // not found
// not found // return "", "", errors.New("not found")
return "", "", errors.New("not found") // }
}
tokenUUID, err := uuid.GenerateUUID() tokenUUID, err := uuid.GenerateUUID()
if err != nil { if err != nil {
return "", "", err return "", "", err

View File

@@ -101,7 +101,7 @@ func TestUserLoginDelete(t *testing.T) {
} }
raw, _ = helpWithdrawAgreement("token", userTOKEN, "contract1") raw, _ = helpWithdrawAgreement("token", userTOKEN, "contract1")
if _, ok := raw["status"]; !ok || raw["status"].(string) != "ok" { if _, ok := raw["status"]; !ok || raw["status"].(string) != "ok" {
t.Fatalf("Failed to accept on consent") t.Fatalf("Failed to withdraw on consent")
} }
raw, _ = helpChangeUser("token", userTOKEN, `{"login":null}`) raw, _ = helpChangeUser("token", userTOKEN, `{"login":null}`)
if _, ok := raw["status"]; !ok || raw["status"].(string) != "ok" { if _, ok := raw["status"]; !ok || raw["status"].(string) != "ok" {