all consent api was split into 3 object to make it more GDPR friendly

This commit is contained in:
Yuli
2020-07-01 12:13:16 +03:00
parent 1f973ea878
commit 00b7bddec8
12 changed files with 910 additions and 311 deletions

View File

@@ -7,14 +7,14 @@ import (
"strings" "strings"
"github.com/julienschmidt/httprouter" "github.com/julienschmidt/httprouter"
"go.mongodb.org/mongo-driver/bson" //"go.mongodb.org/mongo-driver/bson"
) )
func (e mainEnv) consentAccept(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { func (e mainEnv) agreementAccept(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
address := ps.ByName("address") address := ps.ByName("address")
brief := ps.ByName("brief") brief := ps.ByName("brief")
mode := ps.ByName("mode") mode := ps.ByName("mode")
event := audit("consent accept for "+brief, address, mode, address) event := audit("agreement accept for "+brief, address, mode, address)
defer func() { event.submit(e.db) }() defer func() { event.submit(e.db) }()
if validateMode(mode) == false { if validateMode(mode) == false {
@@ -27,6 +27,15 @@ func (e mainEnv) consentAccept(w http.ResponseWriter, r *http.Request, ps httpro
returnError(w, r, "bad brief format", 405, nil, event) returnError(w, r, "bad brief format", 405, nil, event)
return return
} }
exists, err := e.db.checkLegalBasis(brief)
if err != nil {
returnError(w, r, "internal error", 405, nil, event)
return
}
if exists == false {
returnError(w, r, "not found", 405, nil, event)
return
}
userTOKEN := "" userTOKEN := ""
if mode == "token" { if mode == "token" {
@@ -69,32 +78,14 @@ func (e mainEnv) consentAccept(w http.ResponseWriter, r *http.Request, ps httpro
}() }()
status := "yes" status := "yes"
message := "" agreementmethod := ""
freetext := ""
lawfulbasis := ""
consentmethod := ""
referencecode := "" referencecode := ""
lastmodifiedby := "" lastmodifiedby := ""
starttime := int32(0) starttime := int32(0)
expiration := int32(0) expiration := int32(0)
if value, ok := records["message"]; ok { if value, ok := records["agreementmethod"]; ok {
if reflect.TypeOf(value) == reflect.TypeOf("string") { if reflect.TypeOf(value) == reflect.TypeOf("string") {
message = value.(string) agreementmethod = value.(string)
}
}
if value, ok := records["freetext"]; ok {
if reflect.TypeOf(value) == reflect.TypeOf("string") {
freetext = value.(string)
}
}
if value, ok := records["lawfulbasis"]; ok {
if reflect.TypeOf(value) == reflect.TypeOf("string") {
lawfulbasis = value.(string)
}
}
if value, ok := records["consentmethod"]; ok {
if reflect.TypeOf(value) == reflect.TypeOf("string") {
consentmethod = value.(string)
} }
} }
if value, ok := records["referencecode"]; ok { if value, ok := records["referencecode"]; ok {
@@ -134,8 +125,9 @@ func (e mainEnv) consentAccept(w http.ResponseWriter, r *http.Request, ps httpro
case "phone": case "phone":
address = normalizePhone(address, e.conf.Sms.DefaultCountry) address = normalizePhone(address, e.conf.Sms.DefaultCountry)
} }
newStatus, _ := e.db.createConsentRecord(userTOKEN, mode, address, brief, message, status, lawfulbasis, consentmethod, e.db.acceptAgreement(userTOKEN, mode, address, brief, status, agreementmethod,
referencecode, freetext, lastmodifiedby, starttime, expiration) referencecode, lastmodifiedby, starttime, expiration)
/*
notifyURL := e.conf.Notification.NotificationURL notifyURL := e.conf.Notification.NotificationURL
if newStatus == true && len(notifyURL) > 0 { if newStatus == true && len(notifyURL) > 0 {
// change notificate on new record or if status change // change notificate on new record or if status change
@@ -145,6 +137,7 @@ func (e mainEnv) consentAccept(w http.ResponseWriter, r *http.Request, ps httpro
notifyConsentChange(notifyURL, brief, status, mode, address) notifyConsentChange(notifyURL, brief, status, mode, address)
} }
} }
*/
} }
func (e mainEnv) consentWithdraw(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { func (e mainEnv) consentWithdraw(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
@@ -164,6 +157,15 @@ func (e mainEnv) consentWithdraw(w http.ResponseWriter, r *http.Request, ps http
returnError(w, r, "bad brief format", 405, nil, event) returnError(w, r, "bad brief format", 405, nil, event)
return return
} }
exists, err := e.db.checkLegalBasis(brief)
if err != nil {
returnError(w, r, "internal error", 405, nil, event)
return
}
if exists == false {
returnError(w, r, "not found", 405, nil, event)
return
}
userTOKEN := "" userTOKEN := ""
authResult := "" authResult := ""
@@ -242,7 +244,7 @@ func (e mainEnv) consentWithdraw(w http.ResponseWriter, r *http.Request, ps http
case "phone": case "phone":
address = normalizePhone(address, e.conf.Sms.DefaultCountry) address = normalizePhone(address, e.conf.Sms.DefaultCountry)
} }
e.db.withdrawConsentRecord(userTOKEN, brief, mode, address, lastmodifiedby) e.db.withdrawAgreement(userTOKEN, brief, mode, address, lastmodifiedby)
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)
w.Write([]byte(`{"status":"ok"}`)) w.Write([]byte(`{"status":"ok"}`))
@@ -255,6 +257,7 @@ func (e mainEnv) consentWithdraw(w http.ResponseWriter, r *http.Request, ps http
} }
/*
func (e mainEnv) consentAllUserRecords(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { func (e mainEnv) consentAllUserRecords(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
address := ps.ByName("address") address := ps.ByName("address")
mode := ps.ByName("mode") mode := ps.ByName("mode")
@@ -370,7 +373,9 @@ func (e mainEnv) consentUserRecord(w http.ResponseWriter, r *http.Request, ps ht
str := fmt.Sprintf(`{"status":"ok","data":%s}`, resultJSON) str := fmt.Sprintf(`{"status":"ok","data":%s}`, resultJSON)
w.Write([]byte(str)) w.Write([]byte(str))
} }
*/
/*
func (e mainEnv) consentFilterRecords(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { func (e mainEnv) consentFilterRecords(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
brief := ps.ByName("brief") brief := ps.ByName("brief")
event := audit("consent get all for "+brief, brief, "brief", brief) event := audit("consent get all for "+brief, brief, "brief", brief)
@@ -416,3 +421,4 @@ func (e mainEnv) consentBriefs(w http.ResponseWriter, r *http.Request, ps httpro
str := fmt.Sprintf(`{"status":"ok","total":%d,"briefs":%s}`, numRecords, resultJSON) str := fmt.Sprintf(`{"status":"ok","total":%d,"briefs":%s}`, numRecords, resultJSON)
w.Write([]byte(str)) w.Write([]byte(str))
} }
*/

174
src/agreements_db.go Normal file
View File

@@ -0,0 +1,174 @@
package main
import (
"encoding/json"
//"errors"
"fmt"
"time"
"github.com/paranoidguy/databunker/src/storage"
"go.mongodb.org/mongo-driver/bson"
)
type agreement struct {
Creationtime int32 `json:"creationtime" structs:"creationtime"`
Starttime int32 `json:"starttime" structs:"starttime"`
Endtime int32 `json:"endtime" structs:"endtime"`
When int32 `json:"when,omitempty" structs:"when"`
Who string `json:"who,omitempty" structs:"who"`
Mode string `json:"mode,omitempty" structs:"mode"`
Token string `json:"token" structs:"token"`
Brief string `json:"brief,omitempty" structs:"brief"`
Status string `json:"status,omitempty" structs:"status"`
Referencecode string `json:"referencecode,omitempty" structs:"referencecode,omitempty"`
Lastmodifiedby string `json:"lastmodifiedby,omitempty" structs:"lastmodifiedby,omitempty"`
Agreementmethod string `json:"agreementmethod,omitempty" structs:"agreementmethod"`
}
func (dbobj dbcon) acceptAgreement(userTOKEN string, mode string, usercode string, brief string,
status string, agreementmethod string, referencecode string, lastmodifiedby string,
starttime int32, endtime int32) (bool, error) {
now := int32(time.Now().Unix())
bdoc := bson.M{}
bdoc["when"] = now
bdoc["status"] = status
bdoc["endtime"] = endtime
bdoc["lastmodifiedby"] = lastmodifiedby
if len(referencecode) > 0 {
bdoc["referencecode"] = referencecode
}
if len(userTOKEN) > 0 {
// first check if this agreement exists, then update
raw, err := dbobj.store.GetRecord2(storage.TblName.Agreements, "token", userTOKEN, "brief", brief)
if err != nil {
fmt.Printf("error to find:%s", err)
return false, err
}
if raw != nil {
dbobj.store.UpdateRecord2(storage.TblName.Agreements, "token", userTOKEN, "brief", brief, &bdoc, nil)
if status != raw["status"].(string) {
// status changed
return true, nil
}
return false, nil
}
} else {
raw, err := dbobj.store.GetRecord2(storage.TblName.Agreements, "who", usercode, "brief", brief)
if err != nil {
fmt.Printf("error to find:%s", err)
return false, err
}
if raw != nil {
dbobj.store.UpdateRecord2(storage.TblName.Agreements, "who", usercode, "brief", brief, &bdoc, nil)
if status != raw["status"].(string) {
// status changed
return true, nil
}
return false, err
}
}
bdoc["brief"] = brief
bdoc["mode"] = mode
bdoc["who"] = usercode
bdoc["token"] = userTOKEN
if len(agreementmethod) > 0 {
bdoc["agreementmethod"] = agreementmethod
} else {
bdoc["agreementmethod"] = "api"
}
// in any case - insert record
_, err := dbobj.store.CreateRecord(storage.TblName.Agreements, &bdoc)
if err != nil {
fmt.Printf("error to insert record: %s\n", err)
return false, err
}
return true, nil
}
// link consent record to userToken
func (dbobj dbcon) linkAgreementRecords(userTOKEN string, mode string, usercode string) error {
bdoc := bson.M{}
bdoc["token"] = userTOKEN
_, err := dbobj.store.UpdateRecord2(storage.TblName.Agreements, "token", "", "who", usercode, &bdoc, nil)
return err
}
func (dbobj dbcon) withdrawAgreement(userTOKEN string, brief string, mode string, usercode string, lastmodifiedby string) error {
now := int32(time.Now().Unix())
// update date, status
bdoc := bson.M{}
bdoc["when"] = now
bdoc["mode"] = mode
bdoc["who"] = usercode
bdoc["endtime"] = 0
bdoc["status"] = "no"
bdoc["lastmodifiedby"] = lastmodifiedby
if len(userTOKEN) > 0 {
fmt.Printf("%s %s\n", userTOKEN, brief)
dbobj.store.UpdateRecord2(storage.TblName.Agreements, "token", userTOKEN, "brief", brief, &bdoc, nil)
} else {
dbobj.store.UpdateRecord2(storage.TblName.Agreements, "who", usercode, "brief", brief, &bdoc, nil)
}
return nil
}
// link consent to user?
/*
func (dbobj dbcon) listConsentRecords(userTOKEN string) ([]byte, int, error) {
records, err := dbobj.store.GetList(storage.TblName.Agreements, "token", userTOKEN, 0, 0, "")
if err != nil {
return nil, 0, err
}
count := len(records)
if count == 0 {
return []byte("[]"), 0, err
}
resultJSON, err := json.Marshal(records)
if err != nil {
return nil, 0, err
}
//fmt.Printf("Found multiple documents (array of pointers): %+v\n", results)
return resultJSON, count, nil
}
*/
func (dbobj dbcon) viewAgreementRecord(userTOKEN string, brief string) ([]byte, error) {
record, err := dbobj.store.GetRecord2(storage.TblName.Agreements, "token", userTOKEN, "brief", brief)
if record == nil || err != nil {
return nil, err
}
resultJSON, err := json.Marshal(record)
if err != nil {
return nil, err
}
//fmt.Printf("Found multiple documents (array of pointers): %+v\n", results)
return resultJSON, nil
}
func (dbobj dbcon) expireAgreementRecords(notifyURL string) error {
records, err := dbobj.store.GetExpiring(storage.TblName.Agreements, "status", "yes")
if err != nil {
return err
}
for _, rec := range records {
now := int32(time.Now().Unix())
// update date, status
bdoc := bson.M{}
bdoc["when"] = now
bdoc["status"] = "expired"
userTOKEN := rec["token"].(string)
brief := rec["brief"].(string)
fmt.Printf("This Agreements record is expired: %s - %s\n", userTOKEN, brief)
if len(userTOKEN) > 0 {
fmt.Printf("%s %s\n", userTOKEN, brief)
dbobj.store.UpdateRecord2(storage.TblName.Agreements, "token", userTOKEN, "brief", brief, &bdoc, nil)
notifyConsentChange(notifyURL, brief, "expired", "token", userTOKEN)
} else {
usercode := rec["who"].(string)
dbobj.store.UpdateRecord2(storage.TblName.Agreements, "who", usercode, "brief", brief, &bdoc, nil)
notifyConsentChange(notifyURL, brief, "expired", rec["mode"].(string), usercode)
}
}
return nil
}

View File

@@ -209,12 +209,22 @@ func (e mainEnv) setupRouter() *httprouter.Router {
router.GET("/v1/requests/:mode/:address", e.getCustomUserRequests) router.GET("/v1/requests/:mode/:address", e.getCustomUserRequests)
router.GET("/v1/requests", e.getUserRequests) router.GET("/v1/requests", e.getUserRequests)
router.GET("/v1/consent/:mode/:address", e.consentAllUserRecords) router.GET("/v1/pactivity", e.pactivityList)
router.GET("/v1/consent/:mode/:address/:brief", e.consentUserRecord) router.POST("/v1/pactivity/:activity", e.pactivityCreate)
router.GET("/v1/consents/:brief", e.consentFilterRecords) router.DELETE("/v1/pactivity/:activity", e.pactivityDelete)
router.GET("/v1/consents", e.consentBriefs) router.POST("/v1/pactivity/:activity/:brief", e.pactivityLink)
router.POST("/v1/consent/:mode/:address/:brief", e.consentAccept) router.DELETE("/v1/pactivity/:activity/:brief", e.pactivityUnlink)
router.DELETE("/v1/consent/:mode/:address/:brief", e.consentWithdraw)
router.GET("/v1/lbasis", e.listLegalBasisRecords)
router.POST("/v1/lbasis/:brief", e.createLegalBasis)
router.DELETE("/v1/lbasis/:brief", e.deleteLegalBasis)
//router.GET("/v1/agreement/:mode/:address", e.pactivityUserReport)
router.POST("/v1/agreement/:brief/:mode/:address", e.agreementAccept)
router.DELETE("/v1/agreement/:brief/:mode/:address", e.consentWithdraw)
//router.GET("/v1/consent/:mode/:address", e.consentAllUserRecords)
//router.GET("/v1/consent/:mode/:address/:brief", e.consentUserRecord)
router.POST("/v1/userapp/token/:token/:appname", e.userappNew) router.POST("/v1/userapp/token/:token/:appname", e.userappNew)
router.GET("/v1/userapp/token/:token/:appname", e.userappGet) router.GET("/v1/userapp/token/:token/:appname", e.userappGet)
@@ -305,7 +315,7 @@ func (e mainEnv) dbCleanupDo() {
e.db.store.DeleteExpired0(storage.TblName.Audit, exp) e.db.store.DeleteExpired0(storage.TblName.Audit, exp)
} }
notifyURL := e.conf.Notification.NotificationURL notifyURL := e.conf.Notification.NotificationURL
e.db.expireConsentRecords(notifyURL) e.db.expireAgreementRecords(notifyURL)
} }
func (e mainEnv) dbCleanup() { func (e mainEnv) dbCleanup() {

View File

@@ -1,252 +0,0 @@
package main
import (
"encoding/json"
"errors"
"fmt"
"time"
"github.com/fatih/structs"
"github.com/paranoidguy/databunker/src/storage"
"go.mongodb.org/mongo-driver/bson"
)
type consentEvent struct {
Creationtime int32 `json:"creationtime" structs:"creationtime"`
Starttime int32 `json:"starttime" structs:"starttime"`
Endtime int32 `json:"endtime" structs:"endtime"`
When int32 `json:"when,omitempty" structs:"when"`
Who string `json:"who,omitempty" structs:"who"`
Mode string `json:"mode,omitempty" structs:"mode"`
Token string `json:"token" structs:"token"`
Brief string `json:"brief,omitempty" structs:"brief"`
Status string `json:"status,omitempty" structs:"status"`
Message string `json:"message,omitempty" structs:"message,omitempty"`
Freetext string `json:"freetext,omitempty" structs:"freetext,omitempty"`
Lawfulbasis string `json:"lawfulbasis,omitempty" structs:"lawfulbasis"`
Consentmethod string `json:"consentmethod,omitempty" structs:"consentmethod"`
Referencecode string `json:"referencecode,omitempty" structs:"referencecode,omitempty"`
Lastmodifiedby string `json:"lastmodifiedby,omitempty" structs:"lastmodifiedby,omitempty"`
}
func (dbobj dbcon) createConsentRecord(userTOKEN string, mode string, usercode string,
brief string, message string, status string, lawfulbasis string, consentmethod string,
referencecode string, freetext string, lastmodifiedby string, starttime int32, endtime int32) (bool, error) {
now := int32(time.Now().Unix())
bdoc := bson.M{}
bdoc["when"] = now
bdoc["status"] = status
bdoc["endtime"] = endtime
if len(lawfulbasis) > 0 {
// in case of update, consent, use new value
bdoc["lawfulbasis"] = lawfulbasis
}
if len(consentmethod) > 0 {
bdoc["consentmethod"] = consentmethod
}
if len(referencecode) > 0 {
bdoc["referencecode"] = referencecode
}
if len(freetext) > 0 {
bdoc["freetext"] = freetext
}
bdoc["lastmodifiedby"] = lastmodifiedby
if len(userTOKEN) > 0 {
// first check if this consent exists, then update
raw, err := dbobj.store.GetRecord2(storage.TblName.Consent, "token", userTOKEN, "brief", brief)
if err != nil {
fmt.Printf("error to find:%s", err)
return false, err
}
if raw != nil {
dbobj.store.UpdateRecord2(storage.TblName.Consent, "token", userTOKEN, "brief", brief, &bdoc, nil)
if status != raw["status"].(string) {
// status changed
return true, nil
}
return false, nil
}
} else {
raw, err := dbobj.store.GetRecord2(storage.TblName.Consent, "who", usercode, "brief", brief)
if err != nil {
fmt.Printf("error to find:%s", err)
return false, err
}
if raw != nil {
dbobj.store.UpdateRecord2(storage.TblName.Consent, "who", usercode, "brief", brief, &bdoc, nil)
if status != raw["status"].(string) {
// status changed
return true, nil
}
return false, err
}
}
if len(consentmethod) == 0 {
consentmethod = "api"
}
if len(lawfulbasis) == 0 {
lawfulbasis = "consent"
}
ev := consentEvent{
Creationtime: now,
Endtime: endtime,
When: now,
Who: usercode,
Token: userTOKEN,
Mode: mode,
Brief: brief,
Message: message,
Status: status,
Freetext: freetext,
Lawfulbasis: lawfulbasis,
Consentmethod: consentmethod,
Referencecode: referencecode,
Lastmodifiedby: lastmodifiedby,
}
// in any case - insert record
_, err := dbobj.store.CreateRecord(storage.TblName.Consent, structs.Map(ev))
if err != nil {
fmt.Printf("error to insert record: %s\n", err)
return false, err
}
return true, nil
}
// link consent record to userToken
func (dbobj dbcon) linkConsentRecords(userTOKEN string, mode string, usercode string) error {
bdoc := bson.M{}
bdoc["token"] = userTOKEN
_, err := dbobj.store.UpdateRecord2(storage.TblName.Consent, "token", "", "who", usercode, &bdoc, nil)
return err
}
func (dbobj dbcon) withdrawConsentRecord(userTOKEN string, brief string, mode string, usercode string, lastmodifiedby string) error {
// brief can not be too long, may be hash it ?
if len(brief) > 64 {
return errors.New("Brief value is too long")
}
now := int32(time.Now().Unix())
// update date, status
bdoc := bson.M{}
bdoc["when"] = now
bdoc["mode"] = mode
bdoc["who"] = usercode
bdoc["endtime"] = 0
bdoc["status"] = "no"
bdoc["lastmodifiedby"] = lastmodifiedby
if len(userTOKEN) > 0 {
fmt.Printf("%s %s\n", userTOKEN, brief)
dbobj.store.UpdateRecord2(storage.TblName.Consent, "token", userTOKEN, "brief", brief, &bdoc, nil)
} else {
dbobj.store.UpdateRecord2(storage.TblName.Consent, "who", usercode, "brief", brief, &bdoc, nil)
}
return nil
}
// link consent to user?
func (dbobj dbcon) listConsentRecords(userTOKEN string) ([]byte, int, error) {
records, err := dbobj.store.GetList(storage.TblName.Consent, "token", userTOKEN, 0, 0, "")
if err != nil {
return nil, 0, err
}
count := len(records)
if count == 0 {
return []byte("[]"), 0, err
}
resultJSON, err := json.Marshal(records)
if err != nil {
return nil, 0, err
}
//fmt.Printf("Found multiple documents (array of pointers): %+v\n", results)
return resultJSON, count, nil
}
func (dbobj dbcon) viewConsentRecord(userTOKEN string, brief string) ([]byte, error) {
record, err := dbobj.store.GetRecord2(storage.TblName.Consent, "token", userTOKEN, "brief", brief)
if record == nil || err != nil {
return nil, err
}
resultJSON, err := json.Marshal(record)
if err != nil {
return nil, err
}
//fmt.Printf("Found multiple documents (array of pointers): %+v\n", results)
return resultJSON, nil
}
func (dbobj dbcon) filterConsentRecords(brief string, offset int32, limit int32) ([]byte, int64, error) {
//var results []*auditEvent
count, err := dbobj.store.CountRecords(storage.TblName.Consent, "brief", brief)
if err != nil {
return nil, 0, err
}
if count == 0 {
return []byte("[]"), 0, err
}
records, err := dbobj.store.GetList(storage.TblName.Consent, "brief", brief, offset, limit, "")
if err != nil {
return nil, 0, err
}
// we need to return only list of tokens
var result []string
for _, rec := range records {
result = append(result, rec["token"].(string))
}
resultJSON, err := json.Marshal(result)
if err != nil {
return nil, 0, err
}
//fmt.Printf("Found multiple documents (array of pointers): %+v\n", results)
return resultJSON, count, nil
}
func (dbobj dbcon) getConsentBriefs() ([]byte, int64, error) {
records, err := dbobj.store.GetUniqueList(storage.TblName.Consent, "brief")
if err != nil {
return nil, 0, err
}
count := int64(len(records))
if count == 0 {
return []byte("[]"), 0, err
}
// we need to return only list of briefs
var result []string
for _, rec := range records {
result = append(result, rec["brief"].(string))
}
resultJSON, err := json.Marshal(result)
if err != nil {
return nil, 0, err
}
//fmt.Printf("Found multiple documents (array of pointers): %+v\n", results)
return resultJSON, count, nil
}
func (dbobj dbcon) expireConsentRecords(notifyURL string) error {
records, err := dbobj.store.GetExpiring(storage.TblName.Consent, "status", "yes")
if err != nil {
return err
}
for _, rec := range records {
now := int32(time.Now().Unix())
// update date, status
bdoc := bson.M{}
bdoc["when"] = now
bdoc["status"] = "expired"
userTOKEN := rec["token"].(string)
brief := rec["brief"].(string)
fmt.Printf("This consent record is expired: %s - %s\n", userTOKEN, brief)
if len(userTOKEN) > 0 {
fmt.Printf("%s %s\n", userTOKEN, brief)
dbobj.store.UpdateRecord2(storage.TblName.Consent, "token", userTOKEN, "brief", brief, &bdoc, nil)
notifyConsentChange(notifyURL, brief, "expired", "token", userTOKEN)
} else {
usercode := rec["who"].(string)
dbobj.store.UpdateRecord2(storage.TblName.Consent, "who", usercode, "brief", brief, &bdoc, nil)
notifyConsentChange(notifyURL, brief, "expired", rec["mode"].(string), usercode)
}
}
return nil
}

124
src/lbasis_api.go Normal file
View File

@@ -0,0 +1,124 @@
package main
import (
"fmt"
"net/http"
"reflect"
"github.com/julienschmidt/httprouter"
//"go.mongodb.org/mongo-driver/bson"
)
func (e mainEnv) createLegalBasis(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
brief := ps.ByName("brief")
authResult := e.enforceAdmin(w, r)
if authResult == "" {
return
}
brief = normalizeBrief(brief)
if isValidBrief(brief) == false {
returnError(w, r, "bad brief format", 405, nil, nil)
return
}
records, err := getJSONPostData(r)
if err != nil {
returnError(w, r, "failed to decode request body", 405, err, nil)
return
}
module := ""
fulldesc := ""
shortdesc := ""
basistype := ""
requiredmsg := ""
usercontrol := false
requiredflag := false
if value, ok := records["module"]; ok {
if reflect.TypeOf(value) == reflect.TypeOf("string") {
module = value.(string)
}
}
if value, ok := records["fulldesc"]; ok {
if reflect.TypeOf(value) == reflect.TypeOf("string") {
fulldesc = value.(string)
}
}
if value, ok := records["shortdesc"]; ok {
if reflect.TypeOf(value) == reflect.TypeOf("string") {
shortdesc = value.(string)
}
}
if value, ok := records["basistype"]; ok {
if reflect.TypeOf(value) == reflect.TypeOf("string") {
basistype = value.(string)
}
}
basistype = normalizeBasisType(basistype)
if value, ok := records["requiredmsg"]; ok {
if reflect.TypeOf(value) == reflect.TypeOf("string") {
requiredmsg = value.(string)
}
}
if value, ok := records["usercontrol"]; ok {
if reflect.TypeOf(value).Kind() == reflect.Bool {
usercontrol = value.(bool)
}
}
if value, ok := records["requiredflag"]; ok {
if reflect.TypeOf(value).Kind() == reflect.Bool {
requiredflag = value.(bool)
}
}
e.db.createLegalBasis(brief, module, shortdesc, fulldesc, basistype, requiredmsg, usercontrol, requiredflag)
/*
notifyURL := e.conf.Notification.NotificationURL
if newStatus == true && len(notifyURL) > 0 {
// change notificate on new record or if status change
if len(userTOKEN) > 0 {
notifyConsentChange(notifyURL, brief, status, "token", userTOKEN)
} else {
notifyConsentChange(notifyURL, brief, status, mode, address)
}
}
*/
w.Header().Set("Content-Type", "application/json; charset=utf-8")
w.WriteHeader(200)
w.Write([]byte(`{"status":"ok"}`))
}
func (e mainEnv) deleteLegalBasis(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
brief := ps.ByName("brief")
authResult := e.enforceAdmin(w, r)
if authResult == "" {
return
}
brief = normalizeBrief(brief)
if isValidBrief(brief) == false {
returnError(w, r, "bad brief format", 405, nil, nil)
return
}
e.db.deleteLegalBasis(brief);
w.Header().Set("Content-Type", "application/json; charset=utf-8")
w.WriteHeader(200)
w.Write([]byte(`{"status":"ok"}`))
}
func (e mainEnv) listLegalBasisRecords(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
authResult := e.enforceAdmin(w, r)
if authResult == "" {
return
}
resultJSON, numRecords, err := e.db.getLegalBasisRecords()
if err != nil {
returnError(w, r, "internal error", 405, err, nil)
return
}
fmt.Printf("Total count of rows: %d\n", numRecords)
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Content-Type", "application/json; charset=utf-8")
w.WriteHeader(200)
str := fmt.Sprintf(`{"status":"ok","total":%d,"rows":%s}`, numRecords, resultJSON)
w.Write([]byte(str))
}

118
src/lbasis_db.go Normal file
View File

@@ -0,0 +1,118 @@
package main
import (
"encoding/json"
"fmt"
"time"
"github.com/paranoidguy/databunker/src/storage"
"go.mongodb.org/mongo-driver/bson"
)
type legalBasis struct {
Brief string `json:"brief" structs:"brief"`
Status string `json:"status" structs:"status"`
Module string `json:"module,omitempty" structs:"module,omitempty"`
Shortdesc string `json:"shortdesc,omitempty" structs:"shortdesc,omitempty"`
Fulldesc string `json:"fulldesc,omitempty" structs:"fulldesc,omitempty"`
Basistype string `json:"basistype,omitempty" structs:"basistype"`
Requiredmsg string `json:"requiredmsg,omitempty" structs:"requiredmsg,omitempty"`
Usercontrol bool `json:"usercontrol" structs:"usercontrol"`
Requiredflag bool `json:"requiredflag" structs:"requiredflag"`
Creationtime int32 `json:"creationtime" structs:"creationtime"`
}
func (dbobj dbcon) createLegalBasis(brief string, module string, shortdesc string, fulldesc string, basistype string, requiredmsg string,
usercontrol bool, requiredflag bool) (bool, error) {
now := int32(time.Now().Unix())
bdoc := bson.M{}
bdoc["basistype"] = basistype
if len(module) > 0 {
bdoc["module"] = module
}
if len(shortdesc) > 0 {
bdoc["shortdesc"] = shortdesc
}
if len(fulldesc) > 0 {
bdoc["fulldesc"] = fulldesc
}
if len(requiredmsg) > 0 {
bdoc["requiredmsg"] = requiredmsg
}
bdoc["status"] = "active";
bdoc["usercontrol"] = usercontrol
bdoc["requiredflag"] = requiredflag
raw, err := dbobj.store.GetRecord(storage.TblName.Legalbasis, "brief", brief)
if err != nil {
fmt.Printf("error to find:%s", err)
return false, err
}
if raw != nil {
if basistype != raw["basistype"].(string) {
// check if this legitbasis is used to change it's structure
} else {
dbobj.store.UpdateRecord(storage.TblName.Legalbasis, "brief", brief, &bdoc)
return true, nil
}
return false, err
}
bdoc["brief"] = brief
bdoc["creationtime"] = now
_, err = dbobj.store.CreateRecord(storage.TblName.Legalbasis, &bdoc)
if err != nil {
fmt.Printf("error to insert record: %s\n", err)
return false, err
}
return true, nil
}
func (dbobj dbcon) deleteLegalBasis(brief string) (bool, error) {
// look up for user with this legal basis
count, err := dbobj.store.CountRecords(storage.TblName.Agreements, "brief", brief)
if err != nil {
return false, err
}
if count == 0 {
// we can safely remove this record
dbobj.store.DeleteRecord(storage.TblName.Legalbasis, "brief", brief)
return true, nil
}
// change status to revoked for users
bdoc := bson.M{}
now := int32(time.Now().Unix())
bdoc["when"] = now
bdoc["status"] = "revoked"
dbobj.store.UpdateRecord2(storage.TblName.Agreements, "brief", brief, "status", "yes", &bdoc, nil)
bdoc2 := bson.M{}
bdoc2["status"] = "deleted"
dbobj.store.UpdateRecord(storage.TblName.Legalbasis, "brief", brief, &bdoc2)
return true, nil
}
func (dbobj dbcon) getLegalBasisRecords() ([]byte, int, error) {
records, err := dbobj.store.GetList0(storage.TblName.Legalbasis, 0, 0, "")
if err != nil {
return nil, 0, err
}
count := len(records)
if count == 0 {
return []byte("[]"), 0, err
}
resultJSON, err := json.Marshal(records)
if err != nil {
return nil, 0, err
}
//fmt.Printf("Found multiple documents (array of pointers): %+v\n", results)
return resultJSON, count, nil
}
func (dbobj dbcon) checkLegalBasis(brief string) (bool, error) {
count, err := dbobj.store.CountRecords(storage.TblName.Legalbasis, "brief", brief)
if err != nil {
return false, err
}
if count == 0 {
return false, nil
}
return true, nil
}

161
src/pactivities_api.go Normal file
View File

@@ -0,0 +1,161 @@
package main
import (
"fmt"
"net/http"
"reflect"
"github.com/julienschmidt/httprouter"
//"go.mongodb.org/mongo-driver/bson"
)
func (e mainEnv) pactivityCreate(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
activity := ps.ByName("activity")
authResult := e.enforceAdmin(w, r)
if authResult == "" {
return
}
activity = normalizeBrief(activity)
if isValidBrief(activity) == false {
returnError(w, r, "bad activity format", 405, nil, nil)
return
}
records, err := getJSONPostData(r)
if err != nil {
returnError(w, r, "failed to decode request body", 405, err, nil)
return
}
defer func() {
w.Header().Set("Content-Type", "application/json; charset=utf-8")
w.WriteHeader(200)
w.Write([]byte(`{"status":"ok"}`))
}()
title := ""
script := ""
fulldesc := ""
legalbasis := ""
applicableto := ""
if value, ok := records["title"]; ok {
if reflect.TypeOf(value) == reflect.TypeOf("string") {
title = value.(string)
}
}
if len(title) == 0 {
title = activity
}
if value, ok := records["script"]; ok {
if reflect.TypeOf(value) == reflect.TypeOf("string") {
script = value.(string)
}
}
if value, ok := records["fulldesc"]; ok {
if reflect.TypeOf(value) == reflect.TypeOf("string") {
fulldesc = value.(string)
}
}
if value, ok := records["applicableto"]; ok {
if reflect.TypeOf(value) == reflect.TypeOf("string") {
applicableto = value.(string)
}
}
e.db.createProcessingActivity(activity, title, script, fulldesc, legalbasis, applicableto)
}
func (e mainEnv) pactivityDelete(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
activity := ps.ByName("activity")
authResult := e.enforceAdmin(w, r)
if authResult == "" {
return
}
activity = normalizeBrief(activity)
if isValidBrief(activity) == false {
returnError(w, r, "bad activity format", 405, nil, nil)
return
}
e.db.deleteProcessingActivity(activity)
w.Header().Set("Content-Type", "application/json; charset=utf-8")
w.WriteHeader(200)
w.Write([]byte(`{"status":"ok"}`))
}
func (e mainEnv) pactivityLink(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
activity := ps.ByName("activity")
brief := ps.ByName("brief")
authResult := e.enforceAdmin(w, r)
if authResult == "" {
return
}
activity = normalizeBrief(activity)
if isValidBrief(activity) == false {
returnError(w, r, "bad activity format", 405, nil, nil)
return
}
brief = normalizeBrief(brief)
if isValidBrief(brief) == false {
returnError(w, r, "bad brief format", 405, nil, nil)
return
}
exists, err := e.db.checkLegalBasis(brief)
if err != nil {
returnError(w, r, "internal error", 405, nil, nil)
return
}
if exists == false {
returnError(w, r, "not found", 405, nil, nil)
return
}
_, err = e.db.linkProcessingActivity(activity, brief)
if err != nil {
returnError(w, r, "internal error", 405, err, nil)
return
}
w.Header().Set("Content-Type", "application/json; charset=utf-8")
w.WriteHeader(200)
w.Write([]byte(`{"status":"ok"}`))
}
func (e mainEnv) pactivityUnlink(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
activity := ps.ByName("activity")
brief := ps.ByName("brief")
authResult := e.enforceAdmin(w, r)
if authResult == "" {
return
}
activity = normalizeBrief(activity)
if isValidBrief(activity) == false {
returnError(w, r, "bad activity format", 405, nil, nil)
return
}
brief = normalizeBrief(brief)
if isValidBrief(brief) == false {
returnError(w, r, "bad brief format", 405, nil, nil)
return
}
_, err := e.db.unlinkProcessingActivity(activity, brief)
if err != nil {
returnError(w, r, "internal error", 405, err, nil)
return
}
w.Header().Set("Content-Type", "application/json; charset=utf-8")
w.WriteHeader(200)
w.Write([]byte(`{"status":"ok"}`))
}
func (e mainEnv) pactivityList(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
authResult := e.enforceAdmin(w, r)
if authResult == "" {
return
}
resultJSON, numRecords, err := e.db.listProcessingActivities()
if err != nil {
returnError(w, r, "internal error", 405, err, nil)
return
}
fmt.Printf("Total count of rows: %d\n", numRecords)
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Content-Type", "application/json; charset=utf-8")
w.WriteHeader(200)
str := fmt.Sprintf(`{"status":"ok","total":%d,"rows":%s}`, numRecords, resultJSON)
w.Write([]byte(str))
}

170
src/pactivities_db.go Normal file
View File

@@ -0,0 +1,170 @@
package main
import (
"encoding/json"
"errors"
"fmt"
"reflect"
"strings"
"time"
"github.com/paranoidguy/databunker/src/storage"
"go.mongodb.org/mongo-driver/bson"
)
type processingActivity struct {
Activity string `json:"activity" structs:"activity"`
Title string `json:"title" structs:"title"`
Script string `json:"script,omitempty" structs:"script,omitempty"`
Fulldesc string `json:"fulldesc,omitempty" structs:"fulldesc,omitempty"`
Legalbasis string `json:"legalbasis,omitempty" structs:"legalbasis,omitempty"`
Applicableto string `json:"applicableto,omitempty" structs:"applicableto,omitempty"`
Creationtime int32 `json:"creationtime" structs:"creationtime"`
}
func (dbobj dbcon) createProcessingActivity(activity string, title string, script string, fulldesc string, legalbasis string, applicableto string) (bool, error) {
now := int32(time.Now().Unix())
bdoc := bson.M{}
bdoc["creationtime"] = now
if len(activity) > 0 {
bdoc["activity"] = activity
}
if len(title) > 0 {
bdoc["title"] = title
}
if len(script) > 0 {
bdoc["script"] = script
}
if len(fulldesc) > 0 {
bdoc["fulldesc"] = fulldesc
}
if len(legalbasis) > 0 {
bdoc["legalbasis"] = legalbasis
}
if len(applicableto) > 0 {
bdoc["applicableto"] = applicableto
}
raw, err := dbobj.store.GetRecord(storage.TblName.Processingactivities, "activity", activity)
if err != nil {
fmt.Printf("error to find:%s", err)
return false, err
}
if raw != nil {
_, err = dbobj.store.UpdateRecord(storage.TblName.Processingactivities, "activity", activity, &bdoc)
return false, err
}
_, err = dbobj.store.CreateRecord(storage.TblName.Processingactivities, &bdoc)
if err != nil {
fmt.Printf("error to insert record: %s\n", err)
return false, err
}
return true, nil
}
func (dbobj dbcon) deleteProcessingActivity(activity string) (bool, error) {
dbobj.store.DeleteRecord(storage.TblName.Processingactivities, "activity", activity)
return true, nil
}
func (dbobj dbcon) linkProcessingActivity(activity string, brief string) (bool, error) {
raw, err := dbobj.store.GetRecord(storage.TblName.Processingactivities, "activity", activity)
if err != nil {
fmt.Printf("error to find:%s", err)
return false, err
}
if raw == nil {
return false, errors.New("not found")
}
legalbasis := ""
if value, ok := raw["legalbasis"]; ok {
if reflect.TypeOf(value) == reflect.TypeOf("string") {
legalbasis = value.(string)
}
}
briefs := strings.Split(legalbasis, ",")
if contains(briefs, brief) == true {
// nothing to do here
return false, nil
}
if len(legalbasis) > 0 {
legalbasis = legalbasis + "," + brief
} else {
legalbasis = brief
}
bdoc := bson.M{}
bdoc["legalbasis"] = legalbasis
_, err = dbobj.store.UpdateRecord(storage.TblName.Processingactivities, "activity", activity, &bdoc)
return true, err
}
func (dbobj dbcon) unlinkProcessingActivity(activity string, brief string) (bool, error) {
raw, err := dbobj.store.GetRecord(storage.TblName.Processingactivities, "activity", activity)
if err != nil {
fmt.Printf("error to find:%s", err)
return false, err
}
if raw == nil {
return false, errors.New("not found")
}
legalbasis := ""
if val, ok := raw["legalbasis"]; ok {
if reflect.TypeOf(val) == reflect.TypeOf("string") {
legalbasis = val.(string)
}
}
briefs := strings.Split(legalbasis, ",")
if contains(briefs, brief) == false {
// nothing to do here
return false, nil
}
legalbasis = ""
for _, value := range briefs {
if value != brief {
if len(legalbasis) > 0 {
legalbasis = legalbasis + "," + value
} else {
legalbasis = value
}
}
}
bdoc := bson.M{}
bdoc["legalbasis"] = legalbasis
_, err = dbobj.store.UpdateRecord(storage.TblName.Processingactivities, "activity", activity, &bdoc)
return true, err
}
func (dbobj dbcon) listProcessingActivities() ([]byte, int, error) {
set := make(map[string]interface{})
records0, err := dbobj.store.GetList0(storage.TblName.Legalbasis, 0, 0, "")
for _, val := range records0 {
set[val["brief"].(string)] = val
}
records, err := dbobj.store.GetList0(storage.TblName.Processingactivities, 0, 0, "")
if err != nil {
return nil, 0, err
}
count := len(records)
if count == 0 {
return []byte("[]"), 0, err
}
var results []interface{}
for _, record := range records {
briefs := strings.Split(record["legalbasis"].(string), ",")
var results0 []interface{}
if len(briefs) > 0 {
for _, brief := range briefs {
if value, ok := set[brief]; ok {
results0 = append(results0, value)
}
}
}
record["briefs"] = results0
results = append(results, record)
}
resultJSON, err := json.Marshal(results)
if err != nil {
return nil, 0, err
}
//fmt.Printf("Found multiple documents (array of pointers): %+v\n", results)
return resultJSON, count, nil
}

View File

@@ -142,7 +142,7 @@ func (e mainEnv) getUserRequest(w http.ResponseWriter, r *http.Request, ps httpr
if len(appName) > 0 { if len(appName) > 0 {
resultJSON, err = e.db.getUserApp(userTOKEN, appName) resultJSON, err = e.db.getUserApp(userTOKEN, appName)
} else if len(brief) > 0 { } else if len(brief) > 0 {
resultJSON, err = e.db.viewConsentRecord(userTOKEN, brief) resultJSON, err = e.db.viewAgreementRecord(userTOKEN, brief)
} else { } else {
resultJSON, err = e.db.getUser(userTOKEN) resultJSON, err = e.db.getUser(userTOKEN)
} }
@@ -251,11 +251,11 @@ func (e mainEnv) approveUserRequest(w http.ResponseWriter, r *http.Request, ps h
returnError(w, r, "internal error", 405, err, event) returnError(w, r, "internal error", 405, err, event)
return return
} }
} else if action == "consent-withdraw" { } else if action == "agreement-withdraw" {
brief := requestInfo["brief"].(string) brief := requestInfo["brief"].(string)
mode := "token" mode := "token"
lastmodifiedby := "admin" lastmodifiedby := "admin"
e.db.withdrawConsentRecord(userTOKEN, brief, mode, userTOKEN, lastmodifiedby) e.db.withdrawAgreement(userTOKEN, brief, mode, userTOKEN, lastmodifiedby)
} }
e.db.updateRequestStatus(request, "approved", "") e.db.updateRequestStatus(request, "approved", "")
w.Header().Set("Content-Type", "application/json; charset=utf-8") w.Header().Set("Content-Type", "application/json; charset=utf-8")

View File

@@ -30,10 +30,12 @@ type listTbls struct {
Users Tbl Users Tbl
Audit Tbl Audit Tbl
Xtokens Tbl Xtokens Tbl
Consent Tbl
Sessions Tbl Sessions Tbl
Requests Tbl Requests Tbl
Legalbasis Tbl
Agreements Tbl
Sharedrecords Tbl Sharedrecords Tbl
Processingactivities Tbl
} }
// TblName is enum of tables // TblName is enum of tables
@@ -41,10 +43,12 @@ var TblName = &listTbls{
Users: 0, Users: 0,
Audit: 1, Audit: 1,
Xtokens: 2, Xtokens: 2,
Consent: 3, Sessions: 3,
Sessions: 4, Requests: 4,
Requests: 5, Legalbasis: 5,
Sharedrecords: 6, Agreements: 6,
Sharedrecords: 7,
Processingactivities: 8,
} }
// DBStorage struct is used to store database object // DBStorage struct is used to store database object
@@ -161,10 +165,12 @@ func InitDB(filepath *string) (DBStorage, error){
initUsers(dbobj.db) initUsers(dbobj.db)
initXTokens(dbobj.db) initXTokens(dbobj.db)
initAudit(dbobj.db) initAudit(dbobj.db)
initConsent(dbobj.db)
initSessions(dbobj.db) initSessions(dbobj.db)
initRequests(dbobj.db) initRequests(dbobj.db)
initSharedRecords(dbobj.db) initSharedRecords(dbobj.db)
initProcessingactivities(dbobj.db)
initLegalbasis(dbobj.db)
initAgreements(dbobj.db)
return dbobj, nil return dbobj, nil
} }
@@ -303,16 +309,20 @@ func getTable(t Tbl) string {
return "users" return "users"
case TblName.Audit: case TblName.Audit:
return "audit" return "audit"
case TblName.Consent:
return "consent"
case TblName.Xtokens: case TblName.Xtokens:
return "xtokens" return "xtokens"
case TblName.Sessions: case TblName.Sessions:
return "sessions" return "sessions"
case TblName.Requests: case TblName.Requests:
return "requests" return "requests"
case TblName.Legalbasis:
return "legalbasis"
case TblName.Agreements:
return "agreements"
case TblName.Sharedrecords: case TblName.Sharedrecords:
return "sharedrecords" return "sharedrecords"
case TblName.Processingactivities:
return "processingactivities"
} }
return "users" return "users"
} }
@@ -530,6 +540,8 @@ func (dbobj DBStorage) getRecordInTableDo(q string, values []interface{}) (bson.
recBson[colName] = int32(columns[i].(int64)) recBson[colName] = int32(columns[i].(int64))
case int32: case int32:
recBson[colName] = int32(columns[i].(int32)) recBson[colName] = int32(columns[i].(int32))
case bool:
recBson[colName] = columns[i].(bool)
case nil: case nil:
//fmt.Printf("is nil, not interesting\n") //fmt.Printf("is nil, not interesting\n")
default: default:
@@ -728,6 +740,28 @@ func (dbobj DBStorage) GetUniqueList(t Tbl, keyName string) ([]bson.M, error) {
return dbobj.getListDo(q, values) return dbobj.getListDo(q, values)
} }
// GetList is used to return list of rows. It can be used to return values using pager.
func (dbobj DBStorage) GetList0(t Tbl, start int32, limit int32, orderField string) ([]bson.M, error) {
table := getTable(t)
if limit > 100 {
limit = 100
}
q := "select * from " + table
if len(orderField) > 0 {
q = q + " ORDER BY " + escapeName(orderField) + " DESC"
}
if start > 0 {
q = q + " LIMIT " + strconv.FormatInt(int64(limit), 10) +
" OFFSET " + strconv.FormatInt(int64(start), 10)
} else if limit > 0 {
q = q + " LIMIT " + strconv.FormatInt(int64(limit), 10)
}
fmt.Printf("q: %s\n", q)
values := make([]interface{}, 0)
return dbobj.getListDo(q, values)
}
// GetList is used to return list of rows. It can be used to return values using pager. // GetList is used to return list of rows. It can be used to return values using pager.
func (dbobj DBStorage) GetList(t Tbl, keyName string, keyValue string, start int32, limit int32, orderField string) ([]bson.M, error) { func (dbobj DBStorage) GetList(t Tbl, keyName string, keyValue string, start int32, limit int32, orderField string) ([]bson.M, error) {
table := getTable(t) table := getTable(t)
@@ -806,6 +840,8 @@ func (dbobj DBStorage) getListDo(q string, values []interface{}) ([]bson.M, erro
recBson[colName] = string(columns[i].([]uint8)) recBson[colName] = string(columns[i].([]uint8))
case int64: case int64:
recBson[colName] = int32(columns[i].(int64)) recBson[colName] = int32(columns[i].(int64))
case bool:
recBson[colName] = columns[i].(bool)
case nil: case nil:
//fmt.Printf("is nil, not interesting\n") //fmt.Printf("is nil, not interesting\n")
default: default:
@@ -970,24 +1006,51 @@ func initRequests(db *sql.DB) error {
return execQueries(db, queries) return execQueries(db, queries)
} }
func initConsent(db *sql.DB) error { func initProcessingactivities(db *sql.DB) error {
queries := []string{`CREATE TABLE IF NOT EXISTS consent ( queries := []string{`CREATE TABLE IF NOT EXISTS processingactivities (
activity STRING,
title STRING,
script STRING,
fulldesc STRING,
legalbasis STRING,
applicableto STRING,
creationtime int);`,
`CREATE INDEX processingactivities_activity ON processingactivities (activity);`}
return execQueries(db, queries)
}
func initLegalbasis(db *sql.DB) error {
queries := []string{`CREATE TABLE IF NOT EXISTS legalbasis (
brief STRING,
status STRING,
module STRING,
shortdesc STRING,
fulldesc STRING,
basistype STRING,
requiredmsg STRING,
usercontrol BOOLEAN,
requiredflag BOOLEAN,
creationtime int);`,
`CREATE INDEX legalbasis_brief ON legalbasis (brief);`}
return execQueries(db, queries)
}
func initAgreements(db *sql.DB) error {
queries := []string{`CREATE TABLE IF NOT EXISTS agreements (
who STRING, who STRING,
mode STRING, mode STRING,
token STRING, token STRING,
brief STRING, brief STRING,
status STRING, status STRING,
message STRING,
freetext STRING,
lawfulbasis STRING,
consentmethod STRING,
referencecode STRING, referencecode STRING,
lastmodifiedby STRING, lastmodifiedby STRING,
agreementmethod STRING,
creationtime int, creationtime int,
starttime int, starttime int,
endtime int, endtime int,
` + "`when` int);", ` + "`when` int);",
`CREATE INDEX consent_token ON consent (token);`} `CREATE INDEX agreements_token ON agreements (token);`,
`CREATE INDEX agreements_brief ON agreements (brief);`}
return execQueries(db, queries) return execQueries(db, queries)
} }

View File

@@ -74,24 +74,24 @@ func (e mainEnv) userNew(w http.ResponseWriter, r *http.Request, ps httprouter.P
return return
} }
if len(parsedData.emailIdx) > 0 { if len(parsedData.emailIdx) > 0 {
e.db.linkConsentRecords(userTOKEN, "email", parsedData.emailIdx) e.db.linkAgreementRecords(userTOKEN, "email", parsedData.emailIdx)
} }
if len(parsedData.phoneIdx) > 0 { if len(parsedData.phoneIdx) > 0 {
e.db.linkConsentRecords(userTOKEN, "phone", parsedData.phoneIdx) e.db.linkAgreementRecords(userTOKEN, "phone", parsedData.phoneIdx)
} }
if len(parsedData.emailIdx) > 0 && len(parsedData.phoneIdx) > 0 { if len(parsedData.emailIdx) > 0 && len(parsedData.phoneIdx) > 0 {
// delete duplicate consent records for user // delete duplicate consent records for user
records, _ := e.db.store.GetList(storage.TblName.Consent, "who", parsedData.emailIdx, 0, 0, "") records, _ := e.db.store.GetList(storage.TblName.Agreements, "who", parsedData.emailIdx, 0, 0, "")
var briefCodes []string var briefCodes []string
for _, val := range records { for _, val := range records {
//fmt.Printf("adding brief code: %s\n", val["brief"].(string)) //fmt.Printf("adding brief code: %s\n", val["brief"].(string))
briefCodes = append(briefCodes, val["brief"].(string)) briefCodes = append(briefCodes, val["brief"].(string))
} }
records, _ = e.db.store.GetList(storage.TblName.Consent, "who", parsedData.phoneIdx, 0, 0, "") records, _ = e.db.store.GetList(storage.TblName.Agreements, "who", parsedData.phoneIdx, 0, 0, "")
for _, val := range records { for _, val := range records {
//fmt.Printf("XXX checking brief code for duplicates: %s\n", val["brief"].(string)) //fmt.Printf("XXX checking brief code for duplicates: %s\n", val["brief"].(string))
if contains(briefCodes, val["brief"].(string)) == true { if contains(briefCodes, val["brief"].(string)) == true {
e.db.store.DeleteRecord2(storage.TblName.Consent, "token", userTOKEN, "who", parsedData.phoneIdx) e.db.store.DeleteRecord2(storage.TblName.Agreements, "token", userTOKEN, "who", parsedData.phoneIdx)
} }
} }
} }

View File

@@ -29,6 +29,7 @@ var (
regexExpiration = regexp.MustCompile("^([0-9]+)([mhds])?$") regexExpiration = regexp.MustCompile("^([0-9]+)([mhds])?$")
regexHex = regexp.MustCompile("^[a-zA-F0-9]+$") regexHex = regexp.MustCompile("^[a-zA-F0-9]+$")
consentYesStatuses = []string{"y", "yes", "accept", "agree", "approve", "given", "true", "good"} consentYesStatuses = []string{"y", "yes", "accept", "agree", "approve", "given", "true", "good"}
basisTypes = []string{"consent", "contract", "legitimate-interest", "vital-interest", "legal-requirement", "public-interest"}
) )
// Consideration why collection of meta data patch was postpone: // Consideration why collection of meta data patch was postpone:
@@ -69,6 +70,14 @@ func normalizeConsentStatus(status string) string {
return "no" return "no"
} }
func normalizeBasisType(status string) string {
status = strings.ToLower(status)
if contains(basisTypes, status) {
return status
}
return "consent"
}
func normalizeBrief(brief string) string { func normalizeBrief(brief string) string {
return strings.ToLower(brief) return strings.ToLower(brief)
} }
@@ -347,6 +356,22 @@ func (e mainEnv) enforceAuth(w http.ResponseWriter, r *http.Request, event *audi
return "" return ""
} }
func (e mainEnv) enforceAdmin(w http.ResponseWriter, r *http.Request) string {
if token, ok := r.Header["X-Bunker-Token"]; ok {
authResult, err := e.db.checkUserAuthXToken(token[0])
//fmt.Printf("error in auth? error %s - %s\n", err, token[0])
if err == nil {
if len(authResult.ttype) > 0 && authResult.ttype != "login" {
return authResult.ttype
}
}
}
fmt.Printf("403 Access denied\n")
w.WriteHeader(http.StatusForbidden)
w.Write([]byte("Access denied"))
return ""
}
func enforceUUID(w http.ResponseWriter, uuidCode string, event *auditEvent) bool { func enforceUUID(w http.ResponseWriter, uuidCode string, event *auditEvent) bool {
if isValidUUID(uuidCode) == false { if isValidUUID(uuidCode) == false {
fmt.Printf("405 bad uuid in : %s\n", uuidCode) fmt.Printf("405 bad uuid in : %s\n", uuidCode)