From 40cfa5480c3bfbf1fdc79d85d7958d7f3968e45f Mon Sep 17 00:00:00 2001 From: stremovsky Date: Sat, 14 Dec 2019 18:04:21 +0200 Subject: [PATCH] validate brief and check if consent can be used with email --- src/consent_api.go | 76 +++++++++++++++++++++++++++++++++++++++++----- src/consent_db.go | 4 --- src/utils.go | 8 +++++ 3 files changed, 76 insertions(+), 12 deletions(-) diff --git a/src/consent_api.go b/src/consent_api.go index 2e8f8f9..c9d4215 100644 --- a/src/consent_api.go +++ b/src/consent_api.go @@ -9,13 +9,18 @@ import ( ) func (e mainEnv) consentAccept(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { - var err error address := ps.ByName("address") brief := ps.ByName("brief") mode := ps.ByName("mode") event := audit("consent accept by "+mode, address) defer func() { event.submit(e.db) }() + brief = normalizeBrief(brief) + if isValidBrief(brief) == false { + returnError(w, r, "bad brief format", 405, nil, event) + return + } + defer func() { w.Header().Set("Content-Type", "application/json; charset=utf-8") w.WriteHeader(200) @@ -70,10 +75,30 @@ func (e mainEnv) consentCancel(w http.ResponseWriter, r *http.Request, ps httpro mode := ps.ByName("mode") event := audit("consent cancel by "+mode, address) defer func() { event.submit(e.db) }() - userTOKEN := address - if enforceUUID(w, userTOKEN, event) == false { + userTOKEN := "" + + brief = normalizeBrief(brief) + if isValidBrief(brief) == false { + returnError(w, r, "bad brief format", 405, nil, event) return } + if mode == "token" { + if enforceUUID(w, address, event) == false { + return + } + userBson, _ := e.db.lookupUserRecord(address) + if userBson == nil { + // if token not found, exit from here + return + } + userTOKEN = address + } else { + // TODO: decode url in code! + userBson, _ := e.db.lookupUserRecordByIndex(mode, address, e.conf) + if userBson != nil { + userTOKEN = userBson["token"].(string) + } + } // make sure that user is logged in here, unless he wants to cancel emails if e.enforceAuth(w, r, event) == false { return @@ -89,9 +114,23 @@ func (e mainEnv) consentAllUserRecords(w http.ResponseWriter, r *http.Request, p mode := ps.ByName("mode") event := audit("consent list of events by "+mode, address) defer func() { event.submit(e.db) }() - userTOKEN := address - if enforceUUID(w, userTOKEN, event) == false { - return + userTOKEN := "" + if mode == "token" { + if enforceUUID(w, address, event) == false { + return + } + userBson, _ := e.db.lookupUserRecord(address) + if userBson == nil { + // if token not found, exit from here + return + } + userTOKEN = address + } else { + // TODO: decode url in code! + userBson, _ := e.db.lookupUserRecordByIndex(mode, address, e.conf) + if userBson != nil { + userTOKEN = userBson["token"].(string) + } } // make sure that user is logged in here, unless he wants to cancel emails if e.enforceAuth(w, r, event) == false { @@ -118,10 +157,31 @@ func (e mainEnv) consentUserRecord(w http.ResponseWriter, r *http.Request, ps ht mode := ps.ByName("mode") event := audit("consent event by "+mode, address) defer func() { event.submit(e.db) }() - userTOKEN := address - if enforceUUID(w, userTOKEN, event) == false { + + brief = normalizeBrief(brief) + if isValidBrief(brief) == false { + returnError(w, r, "bad brief format", 405, nil, event) return } + userTOKEN := "" + if mode == "token" { + if enforceUUID(w, address, event) == false { + return + } + userBson, _ := e.db.lookupUserRecord(address) + if userBson == nil { + // if token not found, exit from here + return + } + userTOKEN = address + } else { + // TODO: decode url in code! + userBson, _ := e.db.lookupUserRecordByIndex(mode, address, e.conf) + if userBson != nil { + userTOKEN = userBson["token"].(string) + } + } + // make sure that user is logged in here, unless he wants to cancel emails if e.enforceAuth(w, r, event) == false { return diff --git a/src/consent_db.go b/src/consent_db.go index 2d0f7f5..35d0dc2 100644 --- a/src/consent_db.go +++ b/src/consent_db.go @@ -22,10 +22,6 @@ type consentEvent struct { func (dbobj dbcon) createConsentRecord(userTOKEN string, mode string, usercode string, brief string, message string, status string) { now := int32(time.Now().Unix()) - // brief can not be too long, may be hash it ? - if len(brief) > 64 { - return - } if len(userTOKEN) > 0 { // first check if this consent exists, then update raw, err := dbobj.getRecord2(TblName.Consent, "token", userTOKEN, "brief", brief) diff --git a/src/utils.go b/src/utils.go index 6df4caa..c5d5ced 100644 --- a/src/utils.go +++ b/src/utils.go @@ -22,10 +22,15 @@ import ( var ( regexUUID = regexp.MustCompile("^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$") + regexBrief = regexp.MustCompile("^[a-z0-9\\-]{1,64}$") regexAppName = regexp.MustCompile("^[a-z][a-z0-9]{1,20}$") regexExpiration = regexp.MustCompile("^([0-9]+)([mhds])$") ) +func normalizeBrief(brief string) string { + return strings.ToLower(brief) +} + func normalizeEmail(email0 string) string { email, _ := url.QueryUnescape(email0) email = strings.ToLower(email) @@ -142,6 +147,9 @@ func isValidUUID(uuidCode string) bool { func isValidApp(app string) bool { return regexAppName.MatchString(app) } +func isValidBrief(brief string) bool { + return regexBrief.MatchString(brief) +} func returnError(w http.ResponseWriter, r *http.Request, message string, code int, err error, event *auditEvent) { fmt.Printf("%d %s %s\n", code, r.Method, r.URL.Path)