mirror of
				https://github.com/optim-enterprises-bv/databunker.git
				synced 2025-10-30 17:37:50 +00:00 
			
		
		
		
	refactor code - adding new utils module
This commit is contained in:
		| @@ -7,6 +7,7 @@ import ( | ||||
| 	"reflect" | ||||
|  | ||||
| 	"github.com/julienschmidt/httprouter" | ||||
| 	"github.com/securitybunker/databunker/src/utils" | ||||
| 	//"go.mongodb.org/mongo-driver/bson" | ||||
| ) | ||||
|  | ||||
| @@ -17,42 +18,42 @@ func (e mainEnv) agreementAccept(w http.ResponseWriter, r *http.Request, ps http | ||||
| 	event := audit("accept agreement by "+brief, identity, mode, identity) | ||||
| 	defer func() { event.submit(e.db, e.conf) }() | ||||
|  | ||||
| 	if validateMode(mode) == false { | ||||
| 		returnError(w, r, "bad mode", 405, nil, event) | ||||
| 	if utils.ValidateMode(mode) == false { | ||||
| 		ReturnError(w, r, "bad mode", 405, nil, event) | ||||
| 		return | ||||
| 	} | ||||
| 	brief = normalizeBrief(brief) | ||||
| 	if isValidBrief(brief) == false { | ||||
| 		returnError(w, r, "bad brief format", 405, nil, event) | ||||
| 	brief = utils.NormalizeBrief(brief) | ||||
| 	if utils.CheckValidBrief(brief) == false { | ||||
| 		ReturnError(w, r, "bad brief format", 405, nil, event) | ||||
| 		return | ||||
| 	} | ||||
| 	exists, err := e.db.checkLegalBasis(brief) | ||||
| 	if err != nil { | ||||
| 		returnError(w, r, "internal error", 405, err, event) | ||||
| 		ReturnError(w, r, "internal error", 405, err, event) | ||||
| 		return | ||||
| 	} | ||||
| 	if exists == false { | ||||
| 		returnError(w, r, "not found", 404, nil, event) | ||||
| 		ReturnError(w, r, "not found", 404, nil, event) | ||||
| 		return | ||||
| 	} | ||||
| 	userTOKEN := "" | ||||
| 	if mode == "token" { | ||||
| 		if enforceUUID(w, identity, event) == false { | ||||
| 		if EnforceUUID(w, identity, event) == false { | ||||
| 			return | ||||
| 		} | ||||
| 		userBson, err := e.db.lookupUserRecord(identity) | ||||
| 		if err != nil || userBson == nil { | ||||
| 			returnError(w, r, "internal error", 405, err, event) | ||||
| 			ReturnError(w, r, "internal error", 405, err, event) | ||||
| 			return | ||||
| 		} | ||||
| 		if e.enforceAuth(w, r, event) == "" { | ||||
| 		if e.EnforceAuth(w, r, event) == "" { | ||||
| 			return | ||||
| 		} | ||||
| 		userTOKEN = identity | ||||
| 	} else { | ||||
| 		userBson, err := e.db.lookupUserRecordByIndex(mode, identity, e.conf) | ||||
| 		if err != nil { | ||||
| 			returnError(w, r, "internal error", 405, err, event) | ||||
| 			ReturnError(w, r, "internal error", 405, err, event) | ||||
| 			return | ||||
| 		} | ||||
| 		if userBson != nil { | ||||
| @@ -60,33 +61,33 @@ func (e mainEnv) agreementAccept(w http.ResponseWriter, r *http.Request, ps http | ||||
| 			event.Record = userTOKEN | ||||
| 		} else { | ||||
| 			if mode == "login" { | ||||
| 				returnError(w, r, "internal error", 405, nil, event) | ||||
| 				ReturnError(w, r, "internal error", 405, nil, event) | ||||
| 				return | ||||
| 			} | ||||
| 			// else user not found - we allow to save consent for unlinked users! | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	records, err := getJSONPostMap(r) | ||||
| 	records, err := utils.GetJSONPostMap(r) | ||||
| 	if err != nil { | ||||
| 		returnError(w, r, "failed to decode request body", 405, err, event) | ||||
| 		ReturnError(w, r, "failed to decode request body", 405, err, event) | ||||
| 		return | ||||
| 	} | ||||
| 	starttime := int32(0) | ||||
| 	expiration := int32(0) | ||||
| 	referencecode := getStringValue(records["referencecode"]) | ||||
| 	lastmodifiedby := getStringValue(records["lastmodifiedby"]) | ||||
| 	agreementmethod := getStringValue(records["agreementmethod"]) | ||||
| 	status := getStringValue(records["status"]) | ||||
| 	referencecode := utils.GetStringValue(records["referencecode"]) | ||||
| 	lastmodifiedby := utils.GetStringValue(records["lastmodifiedby"]) | ||||
| 	agreementmethod := utils.GetStringValue(records["agreementmethod"]) | ||||
| 	status := utils.GetStringValue(records["status"]) | ||||
| 	if len(status) == 0 { | ||||
| 		status = "yes" | ||||
| 	} else { | ||||
| 		status = normalizeConsentStatus(status) | ||||
| 		status = utils.NormalizeConsentStatus(status) | ||||
| 	} | ||||
| 	if value, ok := records["expiration"]; ok { | ||||
| 		switch records["expiration"].(type) { | ||||
| 		case string: | ||||
| 			expiration, _ = parseExpiration(value.(string)) | ||||
| 			expiration, _ = utils.ParseExpiration(value.(string)) | ||||
| 		case float64: | ||||
| 			expiration = int32(value.(float64)) | ||||
| 		} | ||||
| @@ -94,16 +95,16 @@ func (e mainEnv) agreementAccept(w http.ResponseWriter, r *http.Request, ps http | ||||
| 	if value, ok := records["starttime"]; ok { | ||||
| 		switch records["starttime"].(type) { | ||||
| 		case string: | ||||
| 			starttime, _ = parseExpiration(value.(string)) | ||||
| 			starttime, _ = utils.ParseExpiration(value.(string)) | ||||
| 		case float64: | ||||
| 			starttime = int32(value.(float64)) | ||||
| 		} | ||||
| 	} | ||||
| 	switch mode { | ||||
| 	case "email": | ||||
| 		identity = normalizeEmail(identity) | ||||
| 		identity = utils.NormalizeEmail(identity) | ||||
| 	case "phone": | ||||
| 		identity = normalizePhone(identity, e.conf.Sms.DefaultCountry) | ||||
| 		identity = utils.NormalizePhone(identity, e.conf.Sms.DefaultCountry) | ||||
| 	} | ||||
| 	log.Printf("Processing agreement, status: %s\n", status) | ||||
| 	e.db.acceptAgreement(userTOKEN, mode, identity, brief, status, agreementmethod, | ||||
| @@ -131,37 +132,37 @@ func (e mainEnv) agreementWithdraw(w http.ResponseWriter, r *http.Request, ps ht | ||||
| 	event := audit("withdraw agreement by "+brief, identity, mode, identity) | ||||
| 	defer func() { event.submit(e.db, e.conf) }() | ||||
|  | ||||
| 	if validateMode(mode) == false { | ||||
| 		returnError(w, r, "bad mode", 405, nil, event) | ||||
| 	if utils.ValidateMode(mode) == false { | ||||
| 		ReturnError(w, r, "bad mode", 405, nil, event) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	brief = normalizeBrief(brief) | ||||
| 	if isValidBrief(brief) == false { | ||||
| 		returnError(w, r, "bad brief format", 405, nil, event) | ||||
| 	brief = utils.NormalizeBrief(brief) | ||||
| 	if utils.CheckValidBrief(brief) == false { | ||||
| 		ReturnError(w, r, "bad brief format", 405, nil, event) | ||||
| 		return | ||||
| 	} | ||||
| 	lbasis, err := e.db.getLegalBasis(brief) | ||||
| 	if err != nil { | ||||
| 		returnError(w, r, "internal error", 405, err, event) | ||||
| 		ReturnError(w, r, "internal error", 405, err, event) | ||||
| 		return | ||||
| 	} | ||||
| 	if lbasis == nil { | ||||
| 		returnError(w, r, "not  found", 405, nil, event) | ||||
| 		ReturnError(w, r, "not  found", 405, nil, event) | ||||
| 		return | ||||
| 	} | ||||
| 	userTOKEN := "" | ||||
| 	authResult := "" | ||||
| 	if mode == "token" { | ||||
| 		if enforceUUID(w, identity, event) == false { | ||||
| 		if EnforceUUID(w, identity, event) == false { | ||||
| 			return | ||||
| 		} | ||||
| 		userBson, _ := e.db.lookupUserRecord(identity) | ||||
| 		if userBson == nil { | ||||
| 			returnError(w, r, "internal error", 405, nil, event) | ||||
| 			ReturnError(w, r, "internal error", 405, nil, event) | ||||
| 			return | ||||
| 		} | ||||
| 		authResult = e.enforceAuth(w, r, event) | ||||
| 		authResult = e.EnforceAuth(w, r, event) | ||||
| 		if authResult == "" { | ||||
| 			return | ||||
| 		} | ||||
| @@ -174,18 +175,18 @@ func (e mainEnv) agreementWithdraw(w http.ResponseWriter, r *http.Request, ps ht | ||||
| 			event.Record = userTOKEN | ||||
| 		} else { | ||||
| 			if mode == "login" { | ||||
| 				returnError(w, r, "internal error", 405, nil, event) | ||||
| 				ReturnError(w, r, "internal error", 405, nil, event) | ||||
| 				return | ||||
| 			} | ||||
| 			// else user not found - we allow to save consent for unlinked users! | ||||
| 		} | ||||
| 	} | ||||
| 	records, err := getJSONPostMap(r) | ||||
| 	records, err := utils.GetJSONPostMap(r) | ||||
| 	if err != nil { | ||||
| 		returnError(w, r, "failed to decode request body", 405, err, event) | ||||
| 		ReturnError(w, r, "failed to decode request body", 405, err, event) | ||||
| 		return | ||||
| 	} | ||||
| 	lastmodifiedby := getStringValue(records["lastmodifiedby"]) | ||||
| 	lastmodifiedby := utils.GetStringValue(records["lastmodifiedby"]) | ||||
| 	selfService := false | ||||
| 	if value, ok := lbasis["usercontrol"]; ok { | ||||
| 		if reflect.TypeOf(value).Kind() == reflect.Bool { | ||||
| @@ -200,7 +201,7 @@ func (e mainEnv) agreementWithdraw(w http.ResponseWriter, r *http.Request, ps ht | ||||
| 	if selfService == false { | ||||
| 		// user can change consent only for briefs defined in self-service | ||||
| 		if len(authResult) == 0 { | ||||
| 			if e.enforceAdmin(w, r, event) == "" { | ||||
| 			if e.EnforceAdmin(w, r, event) == "" { | ||||
| 				return | ||||
| 			} | ||||
| 		} | ||||
| @@ -209,7 +210,7 @@ func (e mainEnv) agreementWithdraw(w http.ResponseWriter, r *http.Request, ps ht | ||||
| 	if authResult == "login" && selfService == false { | ||||
| 		rtoken, rstatus, err := e.db.saveUserRequest("agreement-withdraw", userTOKEN, "", brief, nil, e.conf) | ||||
| 		if err != nil { | ||||
| 			returnError(w, r, "internal error", 405, err, event) | ||||
| 			ReturnError(w, r, "internal error", 405, err, event) | ||||
| 			return | ||||
| 		} | ||||
| 		w.Header().Set("Content-Type", "application/json; charset=utf-8") | ||||
| @@ -219,9 +220,9 @@ func (e mainEnv) agreementWithdraw(w http.ResponseWriter, r *http.Request, ps ht | ||||
| 	} | ||||
| 	switch mode { | ||||
| 	case "email": | ||||
| 		identity = normalizeEmail(identity) | ||||
| 		identity = utils.NormalizeEmail(identity) | ||||
| 	case "phone": | ||||
| 		identity = normalizePhone(identity, e.conf.Sms.DefaultCountry) | ||||
| 		identity = utils.NormalizePhone(identity, e.conf.Sms.DefaultCountry) | ||||
| 	} | ||||
| 	e.db.withdrawAgreement(userTOKEN, brief, mode, identity, lastmodifiedby) | ||||
| 	w.Header().Set("Content-Type", "application/json; charset=utf-8") | ||||
| @@ -237,21 +238,21 @@ 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) { | ||||
| 	brief := ps.ByName("brief") | ||||
| 	if e.enforceAdmin(w, r, nil) == "" { | ||||
| 	if e.EnforceAdmin(w, r, nil) == "" { | ||||
| 		return | ||||
| 	} | ||||
| 	brief = normalizeBrief(brief) | ||||
| 	if isValidBrief(brief) == false { | ||||
| 		returnError(w, r, "bad brief format", 405, nil, nil) | ||||
| 	brief = utils.NormalizeBrief(brief) | ||||
| 	if utils.CheckValidBrief(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) | ||||
| 		ReturnError(w, r, "internal error", 405, nil, nil) | ||||
| 		return | ||||
| 	} | ||||
| 	if exists == false { | ||||
| 		returnError(w, r, "not found", 405, nil, nil) | ||||
| 		ReturnError(w, r, "not found", 405, nil, nil) | ||||
| 		return | ||||
| 	} | ||||
| 	e.db.revokeLegalBasis(brief) | ||||
| @@ -266,22 +267,22 @@ func (e mainEnv) getUserAgreements(w http.ResponseWriter, r *http.Request, ps ht | ||||
| 	event := audit("privacy agreements for "+mode, identity, mode, identity) | ||||
| 	defer func() { event.submit(e.db, e.conf) }() | ||||
|  | ||||
| 	if validateMode(mode) == false { | ||||
| 		returnError(w, r, "bad mode", 405, nil, event) | ||||
| 	if utils.ValidateMode(mode) == false { | ||||
| 		ReturnError(w, r, "bad mode", 405, nil, event) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	userTOKEN := "" | ||||
| 	if mode == "token" { | ||||
| 		if enforceUUID(w, identity, event) == false { | ||||
| 		if EnforceUUID(w, identity, event) == false { | ||||
| 			return | ||||
| 		} | ||||
| 		userBson, _ := e.db.lookupUserRecord(identity) | ||||
| 		if userBson == nil { | ||||
| 			returnError(w, r, "internal error", 405, nil, event) | ||||
| 			ReturnError(w, r, "internal error", 405, nil, event) | ||||
| 			return | ||||
| 		} | ||||
| 		if e.enforceAuth(w, r, event) == "" { | ||||
| 		if e.EnforceAuth(w, r, event) == "" { | ||||
| 			return | ||||
| 		} | ||||
| 		userTOKEN = identity | ||||
| @@ -291,12 +292,12 @@ func (e mainEnv) getUserAgreements(w http.ResponseWriter, r *http.Request, ps ht | ||||
| 		if userBson != nil { | ||||
| 			userTOKEN = userBson["token"].(string) | ||||
| 			event.Record = userTOKEN | ||||
| 			if e.enforceAuth(w, r, event) == "" { | ||||
| 			if e.EnforceAuth(w, r, event) == "" { | ||||
| 				return | ||||
| 			} | ||||
| 		} else { | ||||
| 			if mode == "login" { | ||||
| 				returnError(w, r, "internal error", 405, nil, event) | ||||
| 				ReturnError(w, r, "internal error", 405, nil, event) | ||||
| 				return | ||||
| 			} | ||||
| 			// else user not found - we allow to save consent for unlinked users! | ||||
| @@ -304,7 +305,7 @@ func (e mainEnv) getUserAgreements(w http.ResponseWriter, r *http.Request, ps ht | ||||
| 		} | ||||
| 	} | ||||
| 	// make sure that user is logged in here, unless he wants to cancel emails | ||||
| 	if e.enforceAuth(w, r, event) == "" { | ||||
| 	if e.EnforceAuth(w, r, event) == "" { | ||||
| 		return | ||||
| 	} | ||||
| 	var resultJSON []byte | ||||
| @@ -316,7 +317,7 @@ func (e mainEnv) getUserAgreements(w http.ResponseWriter, r *http.Request, ps ht | ||||
| 		resultJSON, numRecords, err = e.db.listAgreementRecordsByIdentity(identity) | ||||
| 	} | ||||
| 	if err != nil { | ||||
| 		returnError(w, r, "internal error", 405, err, event) | ||||
| 		ReturnError(w, r, "internal error", 405, err, event) | ||||
| 		return | ||||
| 	} | ||||
| 	w.Header().Set("Content-Type", "application/json; charset=utf-8") | ||||
| @@ -332,35 +333,35 @@ func (e mainEnv) getUserAgreement(w http.ResponseWriter, r *http.Request, ps htt | ||||
| 	event := audit("privacy agreements for "+mode, identity, mode, identity) | ||||
| 	defer func() { event.submit(e.db, e.conf) }() | ||||
|  | ||||
| 	if validateMode(mode) == false { | ||||
| 		returnError(w, r, "bad mode", 405, nil, event) | ||||
| 	if utils.ValidateMode(mode) == false { | ||||
| 		ReturnError(w, r, "bad mode", 405, nil, event) | ||||
| 		return | ||||
| 	} | ||||
| 	brief = normalizeBrief(brief) | ||||
| 	if isValidBrief(brief) == false { | ||||
| 		returnError(w, r, "bad brief format", 405, nil, event) | ||||
| 	brief = utils.NormalizeBrief(brief) | ||||
| 	if utils.CheckValidBrief(brief) == false { | ||||
| 		ReturnError(w, r, "bad brief format", 405, nil, event) | ||||
| 		return | ||||
| 	} | ||||
| 	exists, err := e.db.checkLegalBasis(brief) | ||||
| 	if err != nil { | ||||
| 		returnError(w, r, "internal error", 405, err, event) | ||||
| 		ReturnError(w, r, "internal error", 405, err, event) | ||||
| 		return | ||||
| 	} | ||||
| 	if exists == false { | ||||
| 		returnError(w, r, "not found", 404, nil, event) | ||||
| 		ReturnError(w, r, "not found", 404, nil, event) | ||||
| 		return | ||||
| 	} | ||||
| 	userTOKEN := "" | ||||
| 	if mode == "token" { | ||||
| 		if enforceUUID(w, identity, event) == false { | ||||
| 		if EnforceUUID(w, identity, event) == false { | ||||
| 			return | ||||
| 		} | ||||
| 		userBson, _ := e.db.lookupUserRecord(identity) | ||||
| 		if userBson == nil { | ||||
| 			returnError(w, r, "internal error", 405, nil, event) | ||||
| 			ReturnError(w, r, "internal error", 405, nil, event) | ||||
| 			return | ||||
| 		} | ||||
| 		if e.enforceAuth(w, r, event) == "" { | ||||
| 		if e.EnforceAuth(w, r, event) == "" { | ||||
| 			return | ||||
| 		} | ||||
| 		userTOKEN = identity | ||||
| @@ -370,29 +371,29 @@ func (e mainEnv) getUserAgreement(w http.ResponseWriter, r *http.Request, ps htt | ||||
| 		if userBson != nil { | ||||
| 			userTOKEN = userBson["token"].(string) | ||||
| 			event.Record = userTOKEN | ||||
| 			if e.enforceAuth(w, r, event) == "" { | ||||
| 			if e.EnforceAuth(w, r, event) == "" { | ||||
| 				return | ||||
| 			} | ||||
| 		} else { | ||||
| 			if mode == "login" { | ||||
| 				returnError(w, r, "internal error", 405, nil, event) | ||||
| 				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) == "" { | ||||
| 	if e.EnforceAuth(w, r, event) == "" { | ||||
| 		return | ||||
| 	} | ||||
| 	var resultJSON []byte | ||||
| 	resultJSON, err = e.db.viewAgreementRecord(userTOKEN, brief) | ||||
| 	if err != nil { | ||||
| 		returnError(w, r, "internal error", 405, err, event) | ||||
| 		ReturnError(w, r, "internal error", 405, err, event) | ||||
| 		return | ||||
| 	} | ||||
| 	if resultJSON == nil { | ||||
| 		returnError(w, r, "not found", 405, err, event) | ||||
| 		ReturnError(w, r, "not found", 405, err, event) | ||||
| 		return | ||||
| 	} | ||||
| 	w.Header().Set("Content-Type", "application/json; charset=utf-8") | ||||
| @@ -409,19 +410,19 @@ func (e mainEnv) consentUserRecord(w http.ResponseWriter, r *http.Request, ps ht | ||||
| 	event := audit("consent record for "+brief, identity, mode, identity) | ||||
| 	defer func() { event.submit(e.db, e.conf) }() | ||||
|  | ||||
| 	if validateMode(mode) == false { | ||||
| 		returnError(w, r, "bad mode", 405, nil, event) | ||||
| 	if utils.ValidateMode(mode) == false { | ||||
| 		ReturnError(w, r, "bad mode", 405, nil, event) | ||||
| 		return | ||||
| 	} | ||||
| 	brief = normalizeBrief(brief) | ||||
| 	if isValidBrief(brief) == false { | ||||
| 		returnError(w, r, "bad brief format", 405, nil, event) | ||||
| 	brief = utils.NormalizeBrief(brief) | ||||
| 	if utils.CheckValidBrief(brief) == false { | ||||
| 		ReturnError(w, r, "bad brief format", 405, nil, event) | ||||
| 		return | ||||
| 	} | ||||
| 	userTOKEN := identity | ||||
| 	var userBson bson.M | ||||
| 	if mode == "token" { | ||||
| 		if enforceUUID(w, identity, event) == false { | ||||
| 		if EnforceUUID(w, identity, event) == false { | ||||
| 			return | ||||
| 		} | ||||
| 		userBson, _ = e.db.lookupUserRecord(identity) | ||||
| @@ -433,20 +434,20 @@ func (e mainEnv) consentUserRecord(w http.ResponseWriter, r *http.Request, ps ht | ||||
| 		} | ||||
| 	} | ||||
| 	if userBson == nil { | ||||
| 		returnError(w, r, "internal error", 405, nil, event) | ||||
| 		ReturnError(w, r, "internal error", 405, nil, event) | ||||
| 		return | ||||
| 	} | ||||
| 	// make sure that user is logged in here, unless he wants to cancel emails | ||||
| 	if e.enforceAuth(w, r, event) == "" { | ||||
| 	if e.EnforceAuth(w, r, event) == "" { | ||||
| 		return | ||||
| 	} | ||||
| 	resultJSON, err := e.db.viewConsentRecord(userTOKEN, brief) | ||||
| 	if err != nil { | ||||
| 		returnError(w, r, "internal error", 405, err, event) | ||||
| 		ReturnError(w, r, "internal error", 405, err, event) | ||||
| 		return | ||||
| 	} | ||||
| 	if resultJSON == nil { | ||||
| 		returnError(w, r, "not found", 405, nil, event) | ||||
| 		ReturnError(w, r, "not found", 405, nil, event) | ||||
| 		return | ||||
| 	} | ||||
| 	w.Header().Set("Content-Type", "application/json; charset=utf-8") | ||||
| @@ -461,7 +462,7 @@ func (e mainEnv) consentFilterRecords(w http.ResponseWriter, r *http.Request, ps | ||||
| 	brief := ps.ByName("brief") | ||||
| 	event := audit("consent get all for "+brief, brief, "brief", brief) | ||||
| 	defer func() { event.submit(e.db, e.conf) }() | ||||
| 	if e.enforceAuth(w, r, event) == "" { | ||||
| 	if e.EnforceAuth(w, r, event) == "" { | ||||
| 		return | ||||
| 	} | ||||
| 	var offset int32 | ||||
| @@ -475,7 +476,7 @@ func (e mainEnv) consentFilterRecords(w http.ResponseWriter, r *http.Request, ps | ||||
| 	} | ||||
| 	resultJSON, numRecords, err := e.db.filterConsentRecords(brief, offset, limit) | ||||
| 	if err != nil { | ||||
| 		returnError(w, r, "internal error", 405, err, event) | ||||
| 		ReturnError(w, r, "internal error", 405, err, event) | ||||
| 		return | ||||
| 	} | ||||
| 	log.Printf("Total count of rows: %d\n", numRecords) | ||||
|   | ||||
							
								
								
									
										116
									
								
								src/audit_api.go
									
									
									
									
									
								
							
							
						
						
									
										116
									
								
								src/audit_api.go
									
									
									
									
									
								
							| @@ -6,30 +6,122 @@ import ( | ||||
| 	"net/http" | ||||
|  | ||||
| 	"github.com/julienschmidt/httprouter" | ||||
| 	"github.com/securitybunker/databunker/src/utils" | ||||
| ) | ||||
|  | ||||
| func ReturnError(w http.ResponseWriter, r *http.Request, message string, code int, err error, event *auditEvent) { | ||||
| 	log.Printf("[%d] %s %s -> Return error\n", code, r.Method, r.URL.Path) | ||||
| 	w.Header().Set("Content-Type", "application/json; charset=utf-8") | ||||
| 	w.WriteHeader(code) | ||||
| 	fmt.Fprintf(w, `{"status":"error","message":%q}`, message) | ||||
| 	if event != nil { | ||||
| 		event.Status = "error" | ||||
| 		event.Msg = message | ||||
| 		if err != nil { | ||||
| 			event.Debug = err.Error() | ||||
| 			log.Printf("Generate error response: %s, Error: %s\n", message, err.Error()) | ||||
| 		} else { | ||||
| 			log.Printf("Generate error response: %s\n", message) | ||||
| 		} | ||||
| 	} | ||||
| 	//http.Error(w, http.StatusText(405), 405) | ||||
| } | ||||
|  | ||||
| func EnforceUUID(w http.ResponseWriter, uuidCode string, event *auditEvent) bool { | ||||
| 	if utils.CheckValidUUID(uuidCode) == false { | ||||
| 		//fmt.Printf("405 bad uuid in : %s\n", uuidCode) | ||||
| 		w.Header().Set("Content-Type", "application/json; charset=utf-8") | ||||
| 		w.WriteHeader(405) | ||||
| 		fmt.Fprintf(w, `{"status":"error","message":"bad uuid"}`) | ||||
| 		if event != nil { | ||||
| 			event.Status = "error" | ||||
| 			event.Msg = "bad uuid" | ||||
| 		} | ||||
| 		return false | ||||
| 	} | ||||
| 	return true | ||||
| } | ||||
|  | ||||
| func (e mainEnv) EnforceAuth(w http.ResponseWriter, r *http.Request, event *auditEvent) string { | ||||
| 	/* | ||||
| 		for key, value := range r.Header { | ||||
| 			fmt.Printf("%s => %s\n", key, value) | ||||
| 		} | ||||
| 	*/ | ||||
| 	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 event != nil { | ||||
| 				event.Identity = authResult.name | ||||
| 				if authResult.ttype == "login" && authResult.token == event.Record { | ||||
| 					return authResult.ttype | ||||
| 				} | ||||
| 			} | ||||
| 			if len(authResult.ttype) > 0 && authResult.ttype != "login" { | ||||
| 				return authResult.ttype | ||||
| 			} | ||||
| 		} | ||||
| 		/* | ||||
| 			if e.db.checkXtoken(token[0]) == true { | ||||
| 				if event != nil { | ||||
| 					event.Identity = "admin" | ||||
| 				} | ||||
| 				return true | ||||
| 			} | ||||
| 		*/ | ||||
| 	} | ||||
| 	log.Printf("403 Access denied\n") | ||||
| 	w.WriteHeader(http.StatusForbidden) | ||||
| 	w.Write([]byte("Access denied")) | ||||
| 	if event != nil { | ||||
| 		event.Status = "error" | ||||
| 		event.Msg = "access denied" | ||||
| 	} | ||||
| 	return "" | ||||
| } | ||||
|  | ||||
| func (e mainEnv) EnforceAdmin(w http.ResponseWriter, r *http.Request, event *auditEvent) 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 event != nil { | ||||
| 				event.Identity = authResult.name | ||||
| 			} | ||||
| 			if len(authResult.ttype) > 0 && authResult.ttype != "login" { | ||||
| 				return authResult.ttype | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	log.Printf("403 Access denied\n") | ||||
| 	w.WriteHeader(http.StatusForbidden) | ||||
| 	w.Write([]byte("Access denied")) | ||||
| 	return "" | ||||
| } | ||||
|  | ||||
| func (e mainEnv) getAuditEvents(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { | ||||
| 	userTOKEN := ps.ByName("token") | ||||
| 	event := audit("view audit events", userTOKEN, "token", userTOKEN) | ||||
| 	defer func() { event.submit(e.db, e.conf) }() | ||||
| 	if enforceUUID(w, userTOKEN, event) == false { | ||||
| 	if EnforceUUID(w, userTOKEN, event) == false { | ||||
| 		return | ||||
| 	} | ||||
| 	if e.enforceAuth(w, r, event) == "" { | ||||
| 	if e.EnforceAuth(w, r, event) == "" { | ||||
| 		return | ||||
| 	} | ||||
| 	var offset int32 | ||||
| 	var limit int32 = 10 | ||||
| 	args := r.URL.Query() | ||||
| 	if value, ok := args["offset"]; ok { | ||||
| 		offset = atoi(value[0]) | ||||
| 		offset = utils.Atoi(value[0]) | ||||
| 	} | ||||
| 	if value, ok := args["limit"]; ok { | ||||
| 		limit = atoi(value[0]) | ||||
| 		limit = utils.Atoi(value[0]) | ||||
| 	} | ||||
| 	resultJSON, counter, err := e.db.getAuditEvents(userTOKEN, offset, limit) | ||||
| 	if err != nil { | ||||
| 		returnError(w, r, "internal error", 405, err, event) | ||||
| 		ReturnError(w, r, "internal error", 405, err, event) | ||||
| 		return | ||||
| 	} | ||||
| 	//fmt.Printf("Total count of events: %d\n", counter) | ||||
| @@ -40,21 +132,21 @@ func (e mainEnv) getAuditEvents(w http.ResponseWriter, r *http.Request, ps httpr | ||||
| } | ||||
|  | ||||
| func (e mainEnv) getAdminAuditEvents(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { | ||||
| 	if e.enforceAdmin(w, r, nil) == "" { | ||||
| 	if e.EnforceAdmin(w, r, nil) == "" { | ||||
| 		return | ||||
| 	} | ||||
| 	var offset int32 | ||||
| 	var limit int32 = 10 | ||||
| 	args := r.URL.Query() | ||||
| 	if value, ok := args["offset"]; ok { | ||||
| 		offset = atoi(value[0]) | ||||
| 		offset = utils.Atoi(value[0]) | ||||
| 	} | ||||
| 	if value, ok := args["limit"]; ok { | ||||
| 		limit = atoi(value[0]) | ||||
| 		limit = utils.Atoi(value[0]) | ||||
| 	} | ||||
| 	resultJSON, counter, err := e.db.getAdminAuditEvents(offset, limit) | ||||
| 	if err != nil { | ||||
| 		returnError(w, r, "internal error", 405, err, nil) | ||||
| 		ReturnError(w, r, "internal error", 405, err, nil) | ||||
| 		return | ||||
| 	} | ||||
| 	//fmt.Printf("Total count of events: %d\n", counter) | ||||
| @@ -69,17 +161,17 @@ func (e mainEnv) getAuditEvent(w http.ResponseWriter, r *http.Request, ps httpro | ||||
| 	event := audit("view audit event", atoken, "token", atoken) | ||||
| 	defer func() { event.submit(e.db, e.conf) }() | ||||
| 	//fmt.Println("error code") | ||||
| 	if enforceUUID(w, atoken, event) == false { | ||||
| 	if EnforceUUID(w, atoken, event) == false { | ||||
| 		return | ||||
| 	} | ||||
| 	userTOKEN, resultJSON, err := e.db.getAuditEvent(atoken) | ||||
| 	log.Printf("extracted user token: %s", userTOKEN) | ||||
| 	if err != nil { | ||||
| 		returnError(w, r, "internal error", 405, err, event) | ||||
| 		ReturnError(w, r, "internal error", 405, err, event) | ||||
| 		return | ||||
| 	} | ||||
| 	event.Record = userTOKEN | ||||
| 	if e.enforceAuth(w, r, event) == "" { | ||||
| 	if e.EnforceAuth(w, r, event) == "" { | ||||
| 		return | ||||
| 	} | ||||
| 	w.Header().Set("Content-Type", "application/json; charset=utf-8") | ||||
|   | ||||
| @@ -9,16 +9,20 @@ import ( | ||||
| 	"log" | ||||
| 	"math/rand" | ||||
| 	"net/http" | ||||
| 	"os" | ||||
| 	"strings" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/gobuffalo/packr" | ||||
| 	"github.com/julienschmidt/httprouter" | ||||
| 	"github.com/kelseyhightower/envconfig" | ||||
| 	"github.com/prometheus/client_golang/prometheus" | ||||
| 	"github.com/prometheus/client_golang/prometheus/promhttp" | ||||
| 	"github.com/securitybunker/databunker/src/autocontext" | ||||
| 	"github.com/securitybunker/databunker/src/storage" | ||||
| 	"github.com/securitybunker/databunker/src/utils" | ||||
| 	"go.mongodb.org/mongo-driver/bson" | ||||
| 	"gopkg.in/yaml.v2" | ||||
| ) | ||||
|  | ||||
| var version string | ||||
| @@ -105,16 +109,6 @@ type mainEnv struct { | ||||
| 	stopChan chan struct{} | ||||
| } | ||||
|  | ||||
| // userJSON used to parse user POST | ||||
| type userJSON struct { | ||||
| 	jsonData  []byte | ||||
| 	loginIdx  string | ||||
| 	emailIdx  string | ||||
| 	phoneIdx  string | ||||
| 	customIdx string | ||||
| 	token     string | ||||
| } | ||||
|  | ||||
| type tokenAuthResult struct { | ||||
| 	ttype string | ||||
| 	name  string | ||||
| @@ -151,7 +145,7 @@ func (e mainEnv) metrics(w http.ResponseWriter, r *http.Request, ps httprouter.P | ||||
|  | ||||
| // backupDB API call. | ||||
| func (e mainEnv) backupDB(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { | ||||
| 	if e.enforceAuth(w, r, nil) == "" { | ||||
| 	if e.EnforceAuth(w, r, nil) == "" { | ||||
| 		return | ||||
| 	} | ||||
| 	w.WriteHeader(200) | ||||
| @@ -169,6 +163,33 @@ func (e mainEnv) checkStatus(w http.ResponseWriter, r *http.Request, ps httprout | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // ReadConfFile() read configuration file. | ||||
| func ReadConfFile(cfg *Config, filepath *string) error { | ||||
| 	confFile := "databunker.yaml" | ||||
| 	if filepath != nil { | ||||
| 		if len(*filepath) > 0 { | ||||
| 			confFile = *filepath | ||||
| 		} | ||||
| 	} | ||||
| 	log.Printf("Loading configuration file: %s\n", confFile) | ||||
| 	f, err := os.Open(confFile) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	decoder := yaml.NewDecoder(f) | ||||
| 	err = decoder.Decode(cfg) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // readEnv() process environment variables. | ||||
| func ReadEnv(cfg *Config) error { | ||||
| 	err := envconfig.Process("", cfg) | ||||
| 	return err | ||||
| } | ||||
|  | ||||
| // setupRouter() setup HTTP Router object. | ||||
| func (e mainEnv) setupRouter() *httprouter.Router { | ||||
| 	box := packr.NewBox("../ui") | ||||
| @@ -335,7 +356,7 @@ func (e mainEnv) setupRouter() *httprouter.Router { | ||||
| // dbCleanup() is used to run cron jobs. | ||||
| func (e mainEnv) dbCleanupDo() { | ||||
| 	log.Printf("db cleanup timeout\n") | ||||
| 	exp, _ := parseExpiration0(e.conf.Policy.MaxAuditRetentionPeriod) | ||||
| 	exp, _ := utils.ParseExpiration0(e.conf.Policy.MaxAuditRetentionPeriod) | ||||
| 	if exp > 0 { | ||||
| 		e.db.store.DeleteExpired0(storage.TblName.Audit, exp) | ||||
| 	} | ||||
| @@ -364,13 +385,13 @@ func (e mainEnv) dbCleanup() { | ||||
| // helper function to load user details by idex name | ||||
| func (e mainEnv) loadUserToken(w http.ResponseWriter, r *http.Request, mode string, identity string, event *auditEvent) string { | ||||
| 	var err error | ||||
| 	if validateMode(mode) == false { | ||||
| 		returnError(w, r, "bad mode", 405, nil, event) | ||||
| 	if utils.ValidateMode(mode) == false { | ||||
| 		ReturnError(w, r, "bad mode", 405, nil, event) | ||||
| 		return "" | ||||
| 	} | ||||
| 	var userBson bson.M | ||||
| 	if mode == "token" { | ||||
| 		if enforceUUID(w, identity, event) == false { | ||||
| 		if EnforceUUID(w, identity, event) == false { | ||||
| 			return "" | ||||
| 		} | ||||
| 		userBson, err = e.db.lookupUserRecord(identity) | ||||
| @@ -378,7 +399,7 @@ func (e mainEnv) loadUserToken(w http.ResponseWriter, r *http.Request, mode stri | ||||
| 		userBson, err = e.db.lookupUserRecordByIndex(mode, identity, e.conf) | ||||
| 	} | ||||
| 	if userBson == nil || err != nil { | ||||
| 		returnError(w, r, "internal error", 405, nil, event) | ||||
| 		ReturnError(w, r, "internal error", 405, nil, event) | ||||
| 		return "" | ||||
| 	} | ||||
| 	event.Record = userBson["token"].(string) | ||||
| @@ -470,6 +491,6 @@ func (e mainEnv) reqMiddleware(handler http.Handler) http.Handler { | ||||
| // main application function | ||||
| func main() { | ||||
| 	rand.Seed(time.Now().UnixNano()) | ||||
| 	lockMemory() | ||||
| 	utils.LockMemory() | ||||
| 	loadService() | ||||
| } | ||||
|   | ||||
| @@ -6,14 +6,16 @@ import ( | ||||
| 	"encoding/hex" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"github.com/afocus/captcha" | ||||
| 	"github.com/gobuffalo/packr" | ||||
| 	"github.com/julienschmidt/httprouter" | ||||
| 	"image/png" | ||||
| 	"log" | ||||
| 	"net/http" | ||||
| 	"regexp" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/afocus/captcha" | ||||
| 	"github.com/gobuffalo/packr" | ||||
| 	"github.com/julienschmidt/httprouter" | ||||
| 	"github.com/securitybunker/databunker/src/utils" | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| @@ -26,19 +28,19 @@ func (e mainEnv) showCaptcha(w http.ResponseWriter, r *http.Request, ps httprout | ||||
| 	code := ps.ByName("code") | ||||
| 	if len(code) == 0 { | ||||
| 		err := errors.New("Bad code") | ||||
| 		returnError(w, r, "bad code", 405, err, nil) | ||||
| 		ReturnError(w, r, "bad code", 405, err, nil) | ||||
| 		return | ||||
| 	} | ||||
| 	s, err := decryptCaptcha(code) | ||||
| 	if err != nil { | ||||
| 		returnError(w, r, err.Error(), 405, err, nil) | ||||
| 		ReturnError(w, r, err.Error(), 405, err, nil) | ||||
| 		return | ||||
| 	} | ||||
| 	log.Printf("Decoded captcha: %s", s) | ||||
| 	//box := packr.NewBox("../ui") | ||||
| 	//comic, err := box.Find("site/fonts/comic.ttf") | ||||
| 	//if err != nil { | ||||
| 	//  returnError(w, r, err.Error(), 405, err, nil) | ||||
| 	//  ReturnError(w, r, err.Error(), 405, err, nil) | ||||
| 	//  return | ||||
| 	//} | ||||
| 	cap := captcha.New() | ||||
| @@ -62,7 +64,7 @@ func initCaptcha(h [16]byte) { | ||||
| } | ||||
|  | ||||
| func generateCaptcha() (string, error) { | ||||
| 	code := randNum(6) | ||||
| 	code := utils.RandNum(6) | ||||
| 	//log.Printf("Generate captcha code: %d", code) | ||||
| 	now := int32(time.Now().Unix()) | ||||
| 	s := fmt.Sprintf("%d:%d", code, now) | ||||
| @@ -112,7 +114,7 @@ func decryptCaptcha(data string) (string, error) { | ||||
| 		return "", errors.New("Failed to parse captcha") | ||||
| 	} | ||||
| 	code := match[1] | ||||
| 	t := atoi(match[2]) | ||||
| 	t := utils.Atoi(match[2]) | ||||
| 	// check if time expired | ||||
| 	now := int32(time.Now().Unix()) | ||||
| 	if now > (t + 120) { | ||||
|   | ||||
| @@ -23,7 +23,7 @@ func (e mainEnv) initContext(r *http.Request) { | ||||
| func (e mainEnv) cookieSettings(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { | ||||
| 	resultJSON, scriptsJSON, _, err := e.db.getLegalBasisCookieConf() | ||||
| 	if err != nil { | ||||
| 		returnError(w, r, "internal error", 405, err, nil) | ||||
| 		ReturnError(w, r, "internal error", 405, err, nil) | ||||
| 		return | ||||
| 	} | ||||
| 	resultUIConfJSON, _ := json.Marshal(e.conf.UI) | ||||
| @@ -34,7 +34,7 @@ func (e mainEnv) cookieSettings(w http.ResponseWriter, r *http.Request, ps httpr | ||||
| } | ||||
|  | ||||
| func (e mainEnv) configurationDump(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { | ||||
| 	if e.enforceAuth(w, r, nil) == "" { | ||||
| 	if e.EnforceAuth(w, r, nil) == "" { | ||||
| 		return | ||||
| 	} | ||||
| 	resultJSON, _ := json.Marshal(e.conf) | ||||
|   | ||||
| @@ -7,6 +7,7 @@ import ( | ||||
| 	uuid "github.com/hashicorp/go-uuid" | ||||
| 	"github.com/julienschmidt/httprouter" | ||||
| 	"github.com/securitybunker/databunker/src/storage" | ||||
| 	"github.com/securitybunker/databunker/src/utils" | ||||
| 	"go.mongodb.org/mongo-driver/bson" | ||||
| ) | ||||
|  | ||||
| @@ -16,7 +17,7 @@ func (e mainEnv) expUsers() error { | ||||
| 		userTOKEN := rec["token"].(string) | ||||
| 		resultJSON, userBSON, _ := e.db.getUser(userTOKEN) | ||||
| 		if resultJSON != nil { | ||||
| 			email := getStringValue(userBSON["email"]) | ||||
| 			email := utils.GetStringValue(userBSON["email"]) | ||||
| 			if len(email) > 0 { | ||||
| 				e.globalUserDelete(email) | ||||
| 			} | ||||
| @@ -33,13 +34,13 @@ func (e mainEnv) expGetStatus(w http.ResponseWriter, r *http.Request, ps httprou | ||||
| 	event := audit("get expiration status by "+mode, identity, mode, identity) | ||||
| 	defer func() { event.submit(e.db, e.conf) }() | ||||
| 	var err error | ||||
| 	if validateMode(mode) == false { | ||||
| 		returnError(w, r, "bad mode", 405, nil, event) | ||||
| 	if utils.ValidateMode(mode) == false { | ||||
| 		ReturnError(w, r, "bad mode", 405, nil, event) | ||||
| 		return | ||||
| 	} | ||||
| 	var userBson bson.M | ||||
| 	if mode == "token" { | ||||
| 		if enforceUUID(w, identity, event) == false { | ||||
| 		if EnforceUUID(w, identity, event) == false { | ||||
| 			return | ||||
| 		} | ||||
| 		userBson, err = e.db.lookupUserRecord(identity) | ||||
| @@ -47,14 +48,14 @@ func (e mainEnv) expGetStatus(w http.ResponseWriter, r *http.Request, ps httprou | ||||
| 		userBson, err = e.db.lookupUserRecordByIndex(mode, identity, e.conf) | ||||
| 	} | ||||
| 	if userBson == nil || err != nil { | ||||
| 		returnError(w, r, "internal error", 405, nil, event) | ||||
| 		ReturnError(w, r, "internal error", 405, nil, event) | ||||
| 		return | ||||
| 	} | ||||
| 	userTOKEN := userBson["token"].(string) | ||||
| 	event.Record = userTOKEN | ||||
| 	expirationDate := getIntValue(userBson["endtime"]) | ||||
| 	expirationStatus := getStringValue(userBson["expstatus"]) | ||||
| 	expirationToken := getStringValue(userBson["exptoken"]) | ||||
| 	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"}`, | ||||
| 		expirationDate, expirationStatus, expirationToken) | ||||
| 	w.Header().Set("Content-Type", "application/json; charset=utf-8") | ||||
| @@ -68,14 +69,14 @@ func (e mainEnv) expCancel(w http.ResponseWriter, r *http.Request, ps httprouter | ||||
| 	mode := ps.ByName("mode") | ||||
| 	event := audit("clear user expiration by "+mode, identity, mode, identity) | ||||
| 	defer func() { event.submit(e.db, e.conf) }() | ||||
| 	if validateMode(mode) == false { | ||||
| 		returnError(w, r, "bad mode", 405, nil, event) | ||||
| 	if utils.ValidateMode(mode) == false { | ||||
| 		ReturnError(w, r, "bad mode", 405, nil, event) | ||||
| 		return | ||||
| 	} | ||||
| 	userTOKEN := identity | ||||
| 	var userBson bson.M | ||||
| 	if mode == "token" { | ||||
| 		if enforceUUID(w, identity, event) == false { | ||||
| 		if EnforceUUID(w, identity, event) == false { | ||||
| 			return | ||||
| 		} | ||||
| 		userBson, err = e.db.lookupUserRecord(identity) | ||||
| @@ -87,13 +88,13 @@ func (e mainEnv) expCancel(w http.ResponseWriter, r *http.Request, ps httprouter | ||||
| 		} | ||||
| 	} | ||||
| 	if userBson == nil || err != nil { | ||||
| 		returnError(w, r, "internal error", 405, nil, event) | ||||
| 		ReturnError(w, r, "internal error", 405, nil, event) | ||||
| 		return | ||||
| 	} | ||||
| 	status := "" | ||||
| 	err = e.db.updateUserExpStatus(userTOKEN, status) | ||||
| 	if err != nil { | ||||
| 		returnError(w, r, "internal error", 405, nil, event) | ||||
| 		ReturnError(w, r, "internal error", 405, nil, event) | ||||
| 		return | ||||
| 	} | ||||
| 	finalJSON := `{"status":"ok"}` | ||||
| @@ -107,12 +108,12 @@ func (e mainEnv) expRetainData(w http.ResponseWriter, r *http.Request, ps httpro | ||||
| 	mode := "exptoken" | ||||
| 	event := audit("retain user data by exptoken", identity, mode, identity) | ||||
| 	defer func() { event.submit(e.db, e.conf) }() | ||||
| 	if enforceUUID(w, identity, event) == false { | ||||
| 	if EnforceUUID(w, identity, event) == false { | ||||
| 		return | ||||
| 	} | ||||
| 	userBson, err := e.db.lookupUserRecordByIndex(mode, identity, e.conf) | ||||
| 	if userBson == nil || err != nil { | ||||
| 		returnError(w, r, "internal error", 405, nil, event) | ||||
| 		ReturnError(w, r, "internal error", 405, nil, event) | ||||
| 		return | ||||
| 	} | ||||
| 	userTOKEN := userBson["token"].(string) | ||||
| @@ -120,7 +121,7 @@ func (e mainEnv) expRetainData(w http.ResponseWriter, r *http.Request, ps httpro | ||||
| 	status := "retain" | ||||
| 	err = e.db.updateUserExpStatus(userTOKEN, status) | ||||
| 	if err != nil { | ||||
| 		returnError(w, r, "internal error", 405, nil, event) | ||||
| 		ReturnError(w, r, "internal error", 405, nil, event) | ||||
| 		return | ||||
| 	} | ||||
| 	w.WriteHeader(200) | ||||
| @@ -132,22 +133,22 @@ func (e mainEnv) expDeleteData(w http.ResponseWriter, r *http.Request, ps httpro | ||||
| 	mode := "exptoken" | ||||
| 	event := audit("delete user data by exptoken", identity, mode, identity) | ||||
| 	defer func() { event.submit(e.db, e.conf) }() | ||||
| 	if enforceUUID(w, identity, event) == false { | ||||
| 	if EnforceUUID(w, identity, event) == false { | ||||
| 		return | ||||
| 	} | ||||
| 	userJSON, userTOKEN, userBSON, err := e.db.getUserByIndex(identity, mode, e.conf) | ||||
| 	if userJSON == nil || err != nil { | ||||
| 		returnError(w, r, "internal error", 405, nil, event) | ||||
| 		ReturnError(w, r, "internal error", 405, nil, event) | ||||
| 		return | ||||
| 	} | ||||
| 	event.Record = userTOKEN | ||||
| 	email := getStringValue(userBSON["email"]) | ||||
| 	email := utils.GetStringValue(userBSON["email"]) | ||||
| 	if len(email) > 0 { | ||||
| 		e.globalUserDelete(email) | ||||
| 	} | ||||
| 	_, err = e.db.deleteUserRecord(userJSON, userTOKEN, e.conf) | ||||
| 	if err != nil { | ||||
| 		returnError(w, r, "internal error", 405, nil, event) | ||||
| 		ReturnError(w, r, "internal error", 405, nil, event) | ||||
| 		return | ||||
| 	} | ||||
| 	e.db.updateUserExpStatus(userTOKEN, "expired") | ||||
| @@ -162,32 +163,32 @@ func (e mainEnv) expStart(w http.ResponseWriter, r *http.Request, ps httprouter. | ||||
| 	event := audit("initiate user record expiration by "+mode, identity, mode, identity) | ||||
| 	defer func() { event.submit(e.db, e.conf) }() | ||||
|  | ||||
| 	if e.enforceAdmin(w, r, event) == "" { | ||||
| 	if e.EnforceAdmin(w, r, event) == "" { | ||||
| 		return | ||||
| 	} | ||||
| 	userTOKEN := e.loadUserToken(w, r, mode, identity, event) | ||||
| 	if userTOKEN == "" { | ||||
| 		return | ||||
| 	} | ||||
| 	records, err := getJSONPostMap(r) | ||||
| 	records, err := utils.GetJSONPostMap(r) | ||||
| 	if err != nil { | ||||
| 		returnError(w, r, "failed to decode request body", 405, err, event) | ||||
| 		ReturnError(w, r, "failed to decode request body", 405, err, event) | ||||
| 		return | ||||
| 	} | ||||
| 	expirationStr := getStringValue(records["expiration"]) | ||||
| 	expiration := setExpiration(e.conf.Policy.MaxUserRetentionPeriod, expirationStr) | ||||
| 	endtime, _ := parseExpiration(expiration) | ||||
| 	status := getStringValue(records["status"]) | ||||
| 	expirationStr := utils.GetStringValue(records["expiration"]) | ||||
| 	expiration := utils.SetExpiration(e.conf.Policy.MaxUserRetentionPeriod, expirationStr) | ||||
| 	endtime, _ := utils.ParseExpiration(expiration) | ||||
| 	status := utils.GetStringValue(records["status"]) | ||||
| 	if len(status) == 0 { | ||||
| 		status = "wait" | ||||
| 	} | ||||
| 	expToken, err := uuid.GenerateUUID() | ||||
| 	if err != nil { | ||||
| 		returnError(w, r, "internal error", 405, err, event) | ||||
| 		ReturnError(w, r, "internal error", 405, err, event) | ||||
| 	} | ||||
| 	err = e.db.initiateUserExpiration(userTOKEN, endtime, status, expToken) | ||||
| 	if err != nil { | ||||
| 		returnError(w, r, "internal error", 405, err, event) | ||||
| 		ReturnError(w, r, "internal error", 405, err, event) | ||||
| 		return | ||||
| 	} | ||||
| 	finalJSON := fmt.Sprintf(`{"status":"ok","exptoken":"%s"}`, expToken) | ||||
|   | ||||
| @@ -6,6 +6,8 @@ toolchain go1.23.3 | ||||
|  | ||||
| replace github.com/securitybunker/databunker/src/storage => ./storage | ||||
|  | ||||
| replace github.com/securitybunker/databunker/src/utils => ./utils | ||||
|  | ||||
| require ( | ||||
| 	github.com/afocus/captcha v0.0.0-20191010092841-4bd1f21c8868 | ||||
| 	github.com/evanphx/json-patch v5.9.0+incompatible | ||||
| @@ -50,13 +52,14 @@ require ( | ||||
| 	github.com/prometheus/procfs v0.15.1 // indirect | ||||
| 	github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect | ||||
| 	github.com/rogpeppe/go-internal v1.13.1 // indirect | ||||
| 	github.com/securitybunker/databunker/src/utils v0.0.0-20241226201542-d0c5d1a19645 // indirect | ||||
| 	github.com/tidwall/match v1.1.1 // indirect | ||||
| 	github.com/tidwall/pretty v1.2.1 // indirect | ||||
| 	github.com/ttacon/builder v0.0.0-20170518171403-c099f663e1c2 // indirect | ||||
| 	golang.org/x/exp v0.0.0-20241217172543-b2144cdd0a67 // indirect | ||||
| 	golang.org/x/image v0.23.0 // indirect | ||||
| 	golang.org/x/mod v0.22.0 // indirect | ||||
| 	google.golang.org/protobuf v1.36.0 // indirect | ||||
| 	google.golang.org/protobuf v1.36.1 // indirect | ||||
| 	modernc.org/gc/v3 v3.0.0-20241213165251-3bc300f6d0c9 // indirect | ||||
| 	modernc.org/libc v1.61.4 // indirect | ||||
| 	modernc.org/mathutil v1.6.0 // indirect | ||||
|   | ||||
| @@ -16,7 +16,7 @@ func init() { | ||||
| 	rootToken = myRootToken | ||||
| 	var cfg Config | ||||
| 	cfile := "../databunker.yaml" | ||||
| 	err = readConfFile(&cfg, &cfile) | ||||
| 	err = ReadConfFile(&cfg, &cfile) | ||||
| 	cfg.SelfService.AppRecordChange = []string{"testapp", "super"} | ||||
| 	if err != nil { | ||||
| 		cfg.SelfService.ForgetMe = false | ||||
|   | ||||
| @@ -7,37 +7,38 @@ import ( | ||||
| 	"reflect" | ||||
|  | ||||
| 	"github.com/julienschmidt/httprouter" | ||||
| 	"github.com/securitybunker/databunker/src/utils" | ||||
| 	//"go.mongodb.org/mongo-driver/bson" | ||||
| ) | ||||
|  | ||||
| func (e mainEnv) createLegalBasis(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { | ||||
| 	brief := ps.ByName("brief") | ||||
| 	if e.enforceAdmin(w, r, nil) == "" { | ||||
| 	if e.EnforceAdmin(w, r, nil) == "" { | ||||
| 		return | ||||
| 	} | ||||
| 	brief = normalizeBrief(brief) | ||||
| 	if isValidBrief(brief) == false { | ||||
| 		returnError(w, r, "bad brief format", 405, nil, nil) | ||||
| 	brief = utils.NormalizeBrief(brief) | ||||
| 	if utils.CheckValidBrief(brief) == false { | ||||
| 		ReturnError(w, r, "bad brief format", 405, nil, nil) | ||||
| 		return | ||||
| 	} | ||||
| 	records, err := getJSONPostMap(r) | ||||
| 	records, err := utils.GetJSONPostMap(r) | ||||
| 	if err != nil { | ||||
| 		returnError(w, r, "failed to decode request body", 405, err, nil) | ||||
| 		ReturnError(w, r, "failed to decode request body", 405, err, nil) | ||||
| 		return | ||||
| 	} | ||||
| 	newbrief := getStringValue(records["brief"]) | ||||
| 	newbrief := utils.GetStringValue(records["brief"]) | ||||
| 	if len(newbrief) > 0 && newbrief != brief { | ||||
| 		if isValidBrief(newbrief) == false { | ||||
| 			returnError(w, r, "bad brief format", 405, nil, nil) | ||||
| 		if utils.CheckValidBrief(newbrief) == false { | ||||
| 			ReturnError(w, r, "bad brief format", 405, nil, nil) | ||||
| 			return | ||||
| 		} | ||||
| 	} | ||||
| 	status := getStringValue(records["status"]) | ||||
| 	module := getStringValue(records["module"]) | ||||
| 	fulldesc := getStringValue(records["fulldesc"]) | ||||
| 	shortdesc := getStringValue(records["shortdesc"]) | ||||
| 	basistype := getStringValue(records["basistype"]) | ||||
| 	requiredmsg := getStringValue(records["requiredmsg"]) | ||||
| 	status := utils.GetStringValue(records["status"]) | ||||
| 	module := utils.GetStringValue(records["module"]) | ||||
| 	fulldesc := utils.GetStringValue(records["fulldesc"]) | ||||
| 	shortdesc := utils.GetStringValue(records["shortdesc"]) | ||||
| 	basistype := utils.GetStringValue(records["basistype"]) | ||||
| 	requiredmsg := utils.GetStringValue(records["requiredmsg"]) | ||||
| 	usercontrol := false | ||||
| 	requiredflag := false | ||||
| 	if status != "disabled" { | ||||
| @@ -82,12 +83,12 @@ func (e mainEnv) createLegalBasis(w http.ResponseWriter, r *http.Request, ps htt | ||||
|  | ||||
| func (e mainEnv) deleteLegalBasis(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { | ||||
| 	brief := ps.ByName("brief") | ||||
| 	if e.enforceAdmin(w, r, nil) == "" { | ||||
| 	if e.EnforceAdmin(w, r, nil) == "" { | ||||
| 		return | ||||
| 	} | ||||
| 	brief = normalizeBrief(brief) | ||||
| 	if isValidBrief(brief) == false { | ||||
| 		returnError(w, r, "bad brief format", 405, nil, nil) | ||||
| 	brief = utils.NormalizeBrief(brief) | ||||
| 	if utils.CheckValidBrief(brief) == false { | ||||
| 		ReturnError(w, r, "bad brief format", 405, nil, nil) | ||||
| 		return | ||||
| 	} | ||||
| 	e.db.unlinkProcessingActivityBrief(brief) | ||||
| @@ -98,12 +99,12 @@ func (e mainEnv) deleteLegalBasis(w http.ResponseWriter, r *http.Request, ps htt | ||||
| } | ||||
|  | ||||
| func (e mainEnv) listLegalBasisRecords(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { | ||||
| 	if e.enforceAdmin(w, r, nil) == "" { | ||||
| 	if e.EnforceAdmin(w, r, nil) == "" { | ||||
| 		return | ||||
| 	} | ||||
| 	resultJSON, numRecords, err := e.db.getLegalBasisRecords() | ||||
| 	if err != nil { | ||||
| 		returnError(w, r, "internal error", 405, err, nil) | ||||
| 		ReturnError(w, r, "internal error", 405, err, nil) | ||||
| 		return | ||||
| 	} | ||||
| 	log.Printf("Total count of rows: %d\n", numRecords) | ||||
|   | ||||
| @@ -7,22 +7,23 @@ import ( | ||||
| 	"reflect" | ||||
|  | ||||
| 	"github.com/julienschmidt/httprouter" | ||||
| 	"github.com/securitybunker/databunker/src/utils" | ||||
| 	//"go.mongodb.org/mongo-driver/bson" | ||||
| ) | ||||
|  | ||||
| func (e mainEnv) pactivityCreate(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { | ||||
| 	activity := ps.ByName("activity") | ||||
| 	if e.enforceAdmin(w, r, nil) == "" { | ||||
| 	if e.EnforceAdmin(w, r, nil) == "" { | ||||
| 		return | ||||
| 	} | ||||
| 	activity = normalizeBrief(activity) | ||||
| 	if isValidBrief(activity) == false { | ||||
| 		returnError(w, r, "bad activity format", 405, nil, nil) | ||||
| 	activity = utils.NormalizeBrief(activity) | ||||
| 	if utils.CheckValidBrief(activity) == false { | ||||
| 		ReturnError(w, r, "bad activity format", 405, nil, nil) | ||||
| 		return | ||||
| 	} | ||||
| 	records, err := getJSONPostMap(r) | ||||
| 	records, err := utils.GetJSONPostMap(r) | ||||
| 	if err != nil { | ||||
| 		returnError(w, r, "failed to decode request body", 405, err, nil) | ||||
| 		ReturnError(w, r, "failed to decode request body", 405, err, nil) | ||||
| 		return | ||||
| 	} | ||||
| 	defer func() { | ||||
| @@ -70,12 +71,12 @@ func (e mainEnv) pactivityCreate(w http.ResponseWriter, r *http.Request, ps http | ||||
|  | ||||
| func (e mainEnv) pactivityDelete(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { | ||||
| 	activity := ps.ByName("activity") | ||||
| 	if e.enforceAdmin(w, r, nil) == "" { | ||||
| 	if e.EnforceAdmin(w, r, nil) == "" { | ||||
| 		return | ||||
| 	} | ||||
| 	activity = normalizeBrief(activity) | ||||
| 	if isValidBrief(activity) == false { | ||||
| 		returnError(w, r, "bad activity format", 405, nil, nil) | ||||
| 	activity = utils.NormalizeBrief(activity) | ||||
| 	if utils.CheckValidBrief(activity) == false { | ||||
| 		ReturnError(w, r, "bad activity format", 405, nil, nil) | ||||
| 		return | ||||
| 	} | ||||
| 	e.db.deleteProcessingActivity(activity) | ||||
| @@ -87,31 +88,31 @@ func (e mainEnv) pactivityDelete(w http.ResponseWriter, r *http.Request, ps http | ||||
| func (e mainEnv) pactivityLink(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { | ||||
| 	activity := ps.ByName("activity") | ||||
| 	brief := ps.ByName("brief") | ||||
| 	if e.enforceAdmin(w, r, nil) == "" { | ||||
| 	if e.EnforceAdmin(w, r, nil) == "" { | ||||
| 		return | ||||
| 	} | ||||
| 	activity = normalizeBrief(activity) | ||||
| 	if isValidBrief(activity) == false { | ||||
| 		returnError(w, r, "bad activity format", 405, nil, nil) | ||||
| 	activity = utils.NormalizeBrief(activity) | ||||
| 	if utils.CheckValidBrief(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) | ||||
| 	brief = utils.NormalizeBrief(brief) | ||||
| 	if utils.CheckValidBrief(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) | ||||
| 		ReturnError(w, r, "internal error", 405, nil, nil) | ||||
| 		return | ||||
| 	} | ||||
| 	if exists == false { | ||||
| 		returnError(w, r, "not found", 405, nil, nil) | ||||
| 		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) | ||||
| 		ReturnError(w, r, "internal error", 405, err, nil) | ||||
| 		return | ||||
| 	} | ||||
| 	w.Header().Set("Content-Type", "application/json; charset=utf-8") | ||||
| @@ -122,22 +123,22 @@ func (e mainEnv) pactivityLink(w http.ResponseWriter, r *http.Request, ps httpro | ||||
| func (e mainEnv) pactivityUnlink(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { | ||||
| 	activity := ps.ByName("activity") | ||||
| 	brief := ps.ByName("brief") | ||||
| 	if e.enforceAdmin(w, r, nil) == "" { | ||||
| 	if e.EnforceAdmin(w, r, nil) == "" { | ||||
| 		return | ||||
| 	} | ||||
| 	activity = normalizeBrief(activity) | ||||
| 	if isValidBrief(activity) == false { | ||||
| 		returnError(w, r, "bad activity format", 405, nil, nil) | ||||
| 	activity = utils.NormalizeBrief(activity) | ||||
| 	if utils.CheckValidBrief(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) | ||||
| 	brief = utils.NormalizeBrief(brief) | ||||
| 	if utils.CheckValidBrief(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) | ||||
| 		ReturnError(w, r, "internal error", 405, err, nil) | ||||
| 		return | ||||
| 	} | ||||
| 	w.Header().Set("Content-Type", "application/json; charset=utf-8") | ||||
| @@ -146,12 +147,12 @@ func (e mainEnv) pactivityUnlink(w http.ResponseWriter, r *http.Request, ps http | ||||
| } | ||||
|  | ||||
| func (e mainEnv) pactivityList(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { | ||||
| 	if e.enforceAdmin(w, r, nil) == "" { | ||||
| 	if e.EnforceAdmin(w, r, nil) == "" { | ||||
| 		return | ||||
| 	} | ||||
| 	resultJSON, numRecords, err := e.db.listProcessingActivities() | ||||
| 	if err != nil { | ||||
| 		returnError(w, r, "internal error", 405, err, nil) | ||||
| 		ReturnError(w, r, "internal error", 405, err, nil) | ||||
| 		return | ||||
| 	} | ||||
| 	log.Printf("Total count of rows: %d\n", numRecords) | ||||
|   | ||||
| @@ -9,6 +9,7 @@ import ( | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/securitybunker/databunker/src/storage" | ||||
| 	"github.com/securitybunker/databunker/src/utils" | ||||
| 	"go.mongodb.org/mongo-driver/bson" | ||||
| ) | ||||
|  | ||||
| @@ -75,7 +76,7 @@ func (dbobj dbcon) linkProcessingActivity(activity string, brief string) (bool, | ||||
| 		} | ||||
| 	} | ||||
| 	briefs := strings.Split(legalbasis, ",") | ||||
| 	if contains(briefs, brief) == true { | ||||
| 	if utils.SliceContains(briefs, brief) == true { | ||||
| 		// nothing to do here | ||||
| 		return false, nil | ||||
| 	} | ||||
| @@ -106,7 +107,7 @@ func (dbobj dbcon) unlinkProcessingActivity(activity string, brief string) (bool | ||||
| 		} | ||||
| 	} | ||||
| 	briefs := strings.Split(legalbasis, ",") | ||||
| 	if contains(briefs, brief) == false { | ||||
| 	if utils.SliceContains(briefs, brief) == false { | ||||
| 		// nothing to do here | ||||
| 		return false, nil | ||||
| 	} | ||||
|   | ||||
| @@ -7,11 +7,12 @@ import ( | ||||
| 	"strings" | ||||
|  | ||||
| 	"github.com/julienschmidt/httprouter" | ||||
| 	"github.com/securitybunker/databunker/src/utils" | ||||
| ) | ||||
|  | ||||
| // 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) { | ||||
| 	if e.enforceAuth(w, r, nil) == "" { | ||||
| 	if e.EnforceAuth(w, r, nil) == "" { | ||||
| 		return | ||||
| 	} | ||||
| 	var offset int32 | ||||
| @@ -19,17 +20,17 @@ func (e mainEnv) getUserRequests(w http.ResponseWriter, r *http.Request, ps http | ||||
| 	status := "open" | ||||
| 	args := r.URL.Query() | ||||
| 	if value, ok := args["offset"]; ok { | ||||
| 		offset = atoi(value[0]) | ||||
| 		offset = utils.Atoi(value[0]) | ||||
| 	} | ||||
| 	if value, ok := args["limit"]; ok { | ||||
| 		limit = atoi(value[0]) | ||||
| 		limit = utils.Atoi(value[0]) | ||||
| 	} | ||||
| 	if value, ok := args["status"]; ok { | ||||
| 		status = value[0] | ||||
| 	} | ||||
| 	resultJSON, counter, err := e.db.getRequests(status, offset, limit) | ||||
| 	if err != nil { | ||||
| 		returnError(w, r, "internal error", 405, err, nil) | ||||
| 		ReturnError(w, r, "internal error", 405, err, nil) | ||||
| 		return | ||||
| 	} | ||||
| 	w.Header().Set("Content-Type", "application/json; charset=utf-8") | ||||
| @@ -45,7 +46,7 @@ func (e mainEnv) getCustomUserRequests(w http.ResponseWriter, r *http.Request, p | ||||
| 	event := audit("get user privacy requests", identity, mode, identity) | ||||
| 	defer func() { event.submit(e.db, e.conf) }() | ||||
|  | ||||
| 	if e.enforceAuth(w, r, event) == "" { | ||||
| 	if e.EnforceAuth(w, r, event) == "" { | ||||
| 		return | ||||
| 	} | ||||
| 	userTOKEN := e.loadUserToken(w, r, mode, identity, event) | ||||
| @@ -56,14 +57,14 @@ func (e mainEnv) getCustomUserRequests(w http.ResponseWriter, r *http.Request, p | ||||
| 	var limit int32 = 10 | ||||
| 	args := r.URL.Query() | ||||
| 	if value, ok := args["offset"]; ok { | ||||
| 		offset = atoi(value[0]) | ||||
| 		offset = utils.Atoi(value[0]) | ||||
| 	} | ||||
| 	if value, ok := args["limit"]; ok { | ||||
| 		limit = atoi(value[0]) | ||||
| 		limit = utils.Atoi(value[0]) | ||||
| 	} | ||||
| 	resultJSON, counter, err := e.db.getUserRequests(userTOKEN, offset, limit) | ||||
| 	if err != nil { | ||||
| 		returnError(w, r, "internal error", 405, err, nil) | ||||
| 		ReturnError(w, r, "internal error", 405, err, nil) | ||||
| 		return | ||||
| 	} | ||||
| 	w.Header().Set("Content-Type", "application/json; charset=utf-8") | ||||
| @@ -77,30 +78,30 @@ func (e mainEnv) getUserRequest(w http.ResponseWriter, r *http.Request, ps httpr | ||||
| 	event := audit("get user request by request token", request, "request", request) | ||||
| 	defer func() { event.submit(e.db, e.conf) }() | ||||
|  | ||||
| 	if enforceUUID(w, request, event) == false { | ||||
| 	if EnforceUUID(w, request, event) == false { | ||||
| 		return | ||||
| 	} | ||||
| 	requestInfo, err := e.db.getRequest(request) | ||||
| 	if err != nil { | ||||
| 		returnError(w, r, "internal error", 405, err, nil) | ||||
| 		ReturnError(w, r, "internal error", 405, err, nil) | ||||
| 		return | ||||
| 	} | ||||
| 	if len(requestInfo) == 0 { | ||||
| 		returnError(w, r, "not found", 405, err, event) | ||||
| 		ReturnError(w, r, "not found", 405, err, event) | ||||
| 		return | ||||
| 	} | ||||
| 	var resultJSON []byte | ||||
| 	action := getStringValue(requestInfo["action"]) | ||||
| 	userTOKEN := getStringValue(requestInfo["token"]) | ||||
| 	action := utils.GetStringValue(requestInfo["action"]) | ||||
| 	userTOKEN := utils.GetStringValue(requestInfo["token"]) | ||||
| 	if len(userTOKEN) != 0 { | ||||
| 		event.Record = userTOKEN | ||||
| 	} | ||||
| 	if e.enforceAdmin(w, r, event) == "" { | ||||
| 	if e.EnforceAdmin(w, r, event) == "" { | ||||
| 		return | ||||
| 	} | ||||
| 	change := getStringValue(requestInfo["change"]) | ||||
| 	appName := getStringValue(requestInfo["app"]) | ||||
| 	brief := getStringValue(requestInfo["brief"]) | ||||
| 	change := utils.GetStringValue(requestInfo["change"]) | ||||
| 	appName := utils.GetStringValue(requestInfo["app"]) | ||||
| 	brief := utils.GetStringValue(requestInfo["brief"]) | ||||
| 	if strings.HasPrefix(action, "plugin") { | ||||
| 		brief = "" | ||||
| 	} | ||||
| @@ -112,11 +113,11 @@ func (e mainEnv) getUserRequest(w http.ResponseWriter, r *http.Request, ps httpr | ||||
| 		resultJSON, err = e.db.getUserJSON(userTOKEN) | ||||
| 	} | ||||
| 	if err != nil { | ||||
| 		returnError(w, r, "internal error", 405, err, event) | ||||
| 		ReturnError(w, r, "internal error", 405, err, event) | ||||
| 		return | ||||
| 	} | ||||
| 	if resultJSON == nil { | ||||
| 		returnError(w, r, "not found", 405, err, event) | ||||
| 		ReturnError(w, r, "not found", 405, err, event) | ||||
| 		return | ||||
| 	} | ||||
| 	//fmt.Printf("Full json: %s\n", resultJSON) | ||||
| @@ -145,49 +146,49 @@ func (e mainEnv) approveUserRequest(w http.ResponseWriter, r *http.Request, ps h | ||||
| 	event := audit("approve user request", request, "request", request) | ||||
| 	defer func() { event.submit(e.db, e.conf) }() | ||||
|  | ||||
| 	if enforceUUID(w, request, event) == false { | ||||
| 	if EnforceUUID(w, request, event) == false { | ||||
| 		return | ||||
| 	} | ||||
| 	authResult := e.enforceAdmin(w, r, event) | ||||
| 	authResult := e.EnforceAdmin(w, r, event) | ||||
| 	if authResult == "" { | ||||
| 		return | ||||
| 	} | ||||
| 	records, err := getJSONPostMap(r) | ||||
| 	records, err := utils.GetJSONPostMap(r) | ||||
| 	if err != nil { | ||||
| 		returnError(w, r, "failed to decode request body", 405, err, event) | ||||
| 		ReturnError(w, r, "failed to decode request body", 405, err, event) | ||||
| 		return | ||||
| 	} | ||||
| 	reason := getStringValue(records["reason"]) | ||||
| 	reason := utils.GetStringValue(records["reason"]) | ||||
| 	requestInfo, err := e.db.getRequest(request) | ||||
| 	if err != nil { | ||||
| 		returnError(w, r, "internal error", 405, err, event) | ||||
| 		ReturnError(w, r, "internal error", 405, err, event) | ||||
| 		return | ||||
| 	} | ||||
| 	if len(requestInfo) == 0 { | ||||
| 		returnError(w, r, "not found", 405, err, event) | ||||
| 		ReturnError(w, r, "not found", 405, err, event) | ||||
| 		return | ||||
| 	} | ||||
| 	userTOKEN := getStringValue(requestInfo["token"]) | ||||
| 	userTOKEN := utils.GetStringValue(requestInfo["token"]) | ||||
| 	if len(userTOKEN) != 0 { | ||||
| 		event.Record = userTOKEN | ||||
| 	} | ||||
| 	action := getStringValue(requestInfo["action"]) | ||||
| 	status := getStringValue(requestInfo["status"]) | ||||
| 	action := utils.GetStringValue(requestInfo["action"]) | ||||
| 	status := utils.GetStringValue(requestInfo["status"]) | ||||
| 	if status != "open" { | ||||
| 		returnError(w, r, "wrong status: "+status, 405, err, event) | ||||
| 		ReturnError(w, r, "wrong status: "+status, 405, err, event) | ||||
| 		return | ||||
| 	} | ||||
| 	userJSON, userBSON, err := e.db.getUser(userTOKEN) | ||||
| 	if err != nil { | ||||
| 		returnError(w, r, "internal error", 405, err, event) | ||||
| 		ReturnError(w, r, "internal error", 405, err, event) | ||||
| 		return | ||||
| 	} | ||||
| 	if userJSON == nil { | ||||
| 		returnError(w, r, "not found", 405, err, event) | ||||
| 		ReturnError(w, r, "not found", 405, err, event) | ||||
| 		return | ||||
| 	} | ||||
| 	if action == "forget-me" { | ||||
| 		email := getStringValue(userBSON["email"]) | ||||
| 		email := utils.GetStringValue(userBSON["email"]) | ||||
| 		if len(email) > 0 { | ||||
| 			e.globalUserDelete(email) | ||||
| 		} | ||||
| @@ -198,7 +199,7 @@ func (e mainEnv) approveUserRequest(w http.ResponseWriter, r *http.Request, ps h | ||||
| 			event.Msg = "failed to delete" | ||||
| 		} | ||||
| 		if err != nil { | ||||
| 			returnError(w, r, "internal error", 405, err, event) | ||||
| 			ReturnError(w, r, "internal error", 405, err, event) | ||||
| 			return | ||||
| 		} | ||||
| 		notifyURL := e.conf.Notification.NotificationURL | ||||
| @@ -206,21 +207,21 @@ func (e mainEnv) approveUserRequest(w http.ResponseWriter, r *http.Request, ps h | ||||
| 	} else if action == "change-profile" { | ||||
| 		oldJSON, newJSON, lookupErr, err := e.db.updateUserRecord(requestInfo["change"].([]uint8), userTOKEN, userBSON, event, e.conf) | ||||
| 		if lookupErr { | ||||
| 			returnError(w, r, "internal error", 405, errors.New("not found"), event) | ||||
| 			ReturnError(w, r, "internal error", 405, errors.New("not found"), event) | ||||
| 			return | ||||
| 		} | ||||
| 		if err != nil { | ||||
| 			returnError(w, r, "internal error", 405, err, event) | ||||
| 			ReturnError(w, r, "internal error", 405, err, event) | ||||
| 			return | ||||
| 		} | ||||
| 		returnUUID(w, userTOKEN) | ||||
| 		utils.ReturnUUID(w, userTOKEN) | ||||
| 		notifyURL := e.conf.Notification.NotificationURL | ||||
| 		notifyProfileChange(notifyURL, oldJSON, newJSON, "token", userTOKEN) | ||||
| 	} else if action == "change-app-data" { | ||||
| 		app := requestInfo["app"].(string) | ||||
| 		_, err = e.db.updateAppRecord(requestInfo["change"].([]uint8), userTOKEN, app, event, e.conf) | ||||
| 		if err != nil { | ||||
| 			returnError(w, r, "internal error", 405, err, event) | ||||
| 			ReturnError(w, r, "internal error", 405, err, event) | ||||
| 			return | ||||
| 		} | ||||
| 	} else if action == "agreement-withdraw" { | ||||
| @@ -243,43 +244,43 @@ func (e mainEnv) cancelUserRequest(w http.ResponseWriter, r *http.Request, ps ht | ||||
| 	event := audit("cancel user request", request, "request", request) | ||||
| 	defer func() { event.submit(e.db, e.conf) }() | ||||
|  | ||||
| 	if enforceUUID(w, request, event) == false { | ||||
| 	if EnforceUUID(w, request, event) == false { | ||||
| 		return | ||||
| 	} | ||||
| 	records, err := getJSONPostMap(r) | ||||
| 	records, err := utils.GetJSONPostMap(r) | ||||
| 	if err != nil { | ||||
| 		returnError(w, r, "failed to decode request body", 405, err, event) | ||||
| 		ReturnError(w, r, "failed to decode request body", 405, err, event) | ||||
| 		return | ||||
| 	} | ||||
| 	reason := getStringValue(records["reason"]) | ||||
| 	reason := utils.GetStringValue(records["reason"]) | ||||
| 	requestInfo, err := e.db.getRequest(request) | ||||
| 	if err != nil { | ||||
| 		returnError(w, r, "internal error", 405, err, event) | ||||
| 		ReturnError(w, r, "internal error", 405, err, event) | ||||
| 		return | ||||
| 	} | ||||
| 	if len(requestInfo) == 0 { | ||||
| 		returnError(w, r, "not found", 405, err, event) | ||||
| 		ReturnError(w, r, "not found", 405, err, event) | ||||
| 		return | ||||
| 	} | ||||
| 	userTOKEN := getStringValue(requestInfo["token"]) | ||||
| 	userTOKEN := utils.GetStringValue(requestInfo["token"]) | ||||
| 	if len(userTOKEN) != 0 { | ||||
| 		event.Record = userTOKEN | ||||
| 	} | ||||
| 	authResult := e.enforceAuth(w, r, event) | ||||
| 	authResult := e.EnforceAuth(w, r, event) | ||||
| 	if authResult == "" { | ||||
| 		return | ||||
| 	} | ||||
| 	if requestInfo["status"].(string) != "open" { | ||||
| 		returnError(w, r, "wrong status: "+requestInfo["status"].(string), 405, err, event) | ||||
| 		ReturnError(w, r, "wrong status: "+requestInfo["status"].(string), 405, err, event) | ||||
| 		return | ||||
| 	} | ||||
| 	resultJSON, err := e.db.getUserJSON(userTOKEN) | ||||
| 	if err != nil { | ||||
| 		returnError(w, r, "internal error", 405, err, event) | ||||
| 		ReturnError(w, r, "internal error", 405, err, event) | ||||
| 		return | ||||
| 	} | ||||
| 	if resultJSON == nil { | ||||
| 		returnError(w, r, "not found", 405, err, event) | ||||
| 		ReturnError(w, r, "not found", 405, err, event) | ||||
| 		return | ||||
| 	} | ||||
| 	if len(reason) == 0 && authResult == "login" { | ||||
|   | ||||
| @@ -15,6 +15,7 @@ import ( | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/securitybunker/databunker/src/storage" | ||||
| 	"github.com/securitybunker/databunker/src/utils" | ||||
| ) | ||||
|  | ||||
| func loadService() { | ||||
| @@ -34,14 +35,14 @@ func loadService() { | ||||
| 	} | ||||
| 	log.Printf("Databunker version: %s\n", version) | ||||
| 	var cfg Config | ||||
| 	readEnv(&cfg) | ||||
| 	readConfFile(&cfg, confPtr) | ||||
| 	ReadEnv(&cfg) | ||||
| 	ReadConfFile(&cfg, confPtr) | ||||
|  | ||||
| 	customRootToken := "" | ||||
| 	if *demoPtr { | ||||
| 		customRootToken = "DEMO" | ||||
| 	} else { | ||||
| 		customRootToken = getArgEnvFileVariable("DATABUNKER_ROOTTOKEN", rootTokenKeyPtr) | ||||
| 		customRootToken = utils.GetArgEnvFileVariable("DATABUNKER_ROOTTOKEN", rootTokenKeyPtr) | ||||
| 	} | ||||
| 	if *initPtr || *demoPtr { | ||||
| 		if storage.DBExists(dbPtr) == true { | ||||
| @@ -63,7 +64,7 @@ func loadService() { | ||||
| 		log.Println(`Run "databunker -init" for the first time to generate keys and init database.`) | ||||
| 		os.Exit(0) | ||||
| 	} | ||||
| 	masterKeyStr := getArgEnvFileVariable("DATABUNKER_MASTERKEY", masterKeyPtr) | ||||
| 	masterKeyStr := utils.GetArgEnvFileVariable("DATABUNKER_MASTERKEY", masterKeyPtr) | ||||
| 	if *startPtr == false { | ||||
| 		log.Println(`'databunker -start' command is missing.`) | ||||
| 		os.Exit(0) | ||||
| @@ -149,7 +150,7 @@ func decodeMasterkey(masterKeyStr string) ([]byte, error) { | ||||
| 	if len(masterKeyStr) != 48 { | ||||
| 		return nil, errors.New("Master key length is wrong") | ||||
| 	} | ||||
| 	if isValidHex(masterKeyStr) == false { | ||||
| 	if utils.CheckValidHex(masterKeyStr) == false { | ||||
| 		return nil, errors.New("Master key is not valid hex string") | ||||
| 	} | ||||
| 	masterKey, err := hex.DecodeString(masterKeyStr) | ||||
| @@ -163,7 +164,7 @@ func setupDB(dbPtr *string, masterKeyPtr *string, customRootToken string) (*dbco | ||||
| 	log.Println("Databunker init") | ||||
| 	var masterKey []byte | ||||
| 	var err error | ||||
| 	masterKeyString := getArgEnvFileVariable("DATABUNKER_MASTERKEY", masterKeyPtr) | ||||
| 	masterKeyString := utils.GetArgEnvFileVariable("DATABUNKER_MASTERKEY", masterKeyPtr) | ||||
| 	if len(masterKeyString) > 0 { | ||||
| 		masterKey, err = decodeMasterkey(masterKeyString) | ||||
| 		if err != nil { | ||||
|   | ||||
| @@ -10,6 +10,7 @@ import ( | ||||
| 	uuid "github.com/hashicorp/go-uuid" | ||||
| 	"github.com/julienschmidt/httprouter" | ||||
| 	"github.com/securitybunker/databunker/src/storage" | ||||
| 	"github.com/securitybunker/databunker/src/utils" | ||||
| 	"go.mongodb.org/mongo-driver/bson" | ||||
| ) | ||||
|  | ||||
| @@ -21,30 +22,30 @@ func (e mainEnv) createSession(w http.ResponseWriter, r *http.Request, ps httpro | ||||
| 			event.submit(e.db, e.conf) | ||||
| 		} | ||||
| 	}() | ||||
| 	if enforceUUID(w, session, event) == false { | ||||
| 		//returnError(w, r, "bad session format", nil, event) | ||||
| 	if EnforceUUID(w, session, event) == false { | ||||
| 		//ReturnError(w, r, "bad session format", nil, event) | ||||
| 		return | ||||
| 	} | ||||
| 	if e.enforceAdmin(w, r, event) == "" { | ||||
| 	if e.EnforceAdmin(w, r, event) == "" { | ||||
| 		return | ||||
| 	} | ||||
| 	records, err := getJSONPostMap(r) | ||||
| 	records, err := utils.GetJSONPostMap(r) | ||||
| 	if err != nil { | ||||
| 		returnError(w, r, "failed to decode request body", 405, err, event) | ||||
| 		ReturnError(w, r, "failed to decode request body", 405, err, event) | ||||
| 		return | ||||
| 	} | ||||
| 	if len(records) == 0 { | ||||
| 		returnError(w, r, "empty body", 405, nil, event) | ||||
| 		ReturnError(w, r, "empty body", 405, nil, event) | ||||
| 		return | ||||
| 	} | ||||
| 	expirationStr := getStringValue(records["expiration"]) | ||||
| 	expiration := setExpiration(e.conf.Policy.MaxSessionRetentionPeriod, expirationStr) | ||||
| 	expirationStr := utils.GetStringValue(records["expiration"]) | ||||
| 	expiration := utils.SetExpiration(e.conf.Policy.MaxSessionRetentionPeriod, expirationStr) | ||||
| 	log.Printf("Record expiration: %s", expiration) | ||||
| 	userToken := getStringValue(records["token"]) | ||||
| 	userLogin := getStringValue(records["login"]) | ||||
| 	userEmail := getStringValue(records["email"]) | ||||
| 	userPhone := getStringValue(records["phone"]) | ||||
| 	userCustomIdx := getStringValue(records["custom"]) | ||||
| 	userToken := utils.GetStringValue(records["token"]) | ||||
| 	userLogin := utils.GetStringValue(records["login"]) | ||||
| 	userEmail := utils.GetStringValue(records["email"]) | ||||
| 	userPhone := utils.GetStringValue(records["phone"]) | ||||
| 	userCustomIdx := utils.GetStringValue(records["custom"]) | ||||
|  | ||||
| 	var userBson bson.M | ||||
| 	if len(userLogin) > 0 { | ||||
| @@ -59,7 +60,7 @@ func (e mainEnv) createSession(w http.ResponseWriter, r *http.Request, ps httpro | ||||
| 		userBson, err = e.db.lookupUserRecord(userToken) | ||||
| 	} | ||||
| 	if err != nil { | ||||
| 		returnError(w, r, "internal error", 405, err, event) | ||||
| 		ReturnError(w, r, "internal error", 405, err, event) | ||||
| 		return | ||||
| 	} | ||||
| 	userTOKEN := "" | ||||
| @@ -70,12 +71,12 @@ func (e mainEnv) createSession(w http.ResponseWriter, r *http.Request, ps httpro | ||||
| 	} | ||||
| 	jsonData, err := json.Marshal(records) | ||||
| 	if err != nil { | ||||
| 		returnError(w, r, "internal error", 405, err, event) | ||||
| 		ReturnError(w, r, "internal error", 405, err, event) | ||||
| 		return | ||||
| 	} | ||||
| 	session, err = e.db.createSessionRecord(session, userTOKEN, expiration, jsonData) | ||||
| 	if err != nil { | ||||
| 		returnError(w, r, "internal error", 405, err, event) | ||||
| 		ReturnError(w, r, "internal error", 405, err, event) | ||||
| 		return | ||||
| 	} | ||||
| 	w.Header().Set("Content-Type", "application/json; charset=utf-8") | ||||
| @@ -87,11 +88,11 @@ func (e mainEnv) deleteSession(w http.ResponseWriter, r *http.Request, ps httpro | ||||
| 	session := ps.ByName("session") | ||||
| 	event := audit("delete session", session, "session", session) | ||||
| 	defer func() { event.submit(e.db, e.conf) }() | ||||
| 	if enforceUUID(w, session, event) == false { | ||||
| 		//returnError(w, r, "bad session format", nil, event) | ||||
| 	if EnforceUUID(w, session, event) == false { | ||||
| 		//ReturnError(w, r, "bad session format", nil, event) | ||||
| 		return | ||||
| 	} | ||||
| 	if e.enforceAdmin(w, r, event) == "" { | ||||
| 	if e.EnforceAdmin(w, r, event) == "" { | ||||
| 		return | ||||
| 	} | ||||
| 	e.db.deleteSession(session) | ||||
| @@ -111,34 +112,34 @@ func (e mainEnv) newUserSession(w http.ResponseWriter, r *http.Request, ps httpr | ||||
| 	if userTOKEN == "" { | ||||
| 		return | ||||
| 	} | ||||
| 	if e.enforceAuth(w, r, event) == "" { | ||||
| 	if e.EnforceAuth(w, r, event) == "" { | ||||
| 		return | ||||
| 	} | ||||
| 	records, err := getJSONPostMap(r) | ||||
| 	records, err := utils.GetJSONPostMap(r) | ||||
| 	if err != nil { | ||||
| 		returnError(w, r, "failed to decode request body", 405, err, event) | ||||
| 		ReturnError(w, r, "failed to decode request body", 405, err, event) | ||||
| 		return | ||||
| 	} | ||||
| 	if len(records) == 0 { | ||||
| 		returnError(w, r, "empty body", 405, nil, event) | ||||
| 		ReturnError(w, r, "empty body", 405, nil, event) | ||||
| 		return | ||||
| 	} | ||||
| 	expirationStr := getStringValue(records["expiration"]) | ||||
| 	expiration := setExpiration(e.conf.Policy.MaxSessionRetentionPeriod, expirationStr) | ||||
| 	expirationStr := utils.GetStringValue(records["expiration"]) | ||||
| 	expiration := utils.SetExpiration(e.conf.Policy.MaxSessionRetentionPeriod, expirationStr) | ||||
| 	log.Printf("Record expiration: %s", expiration) | ||||
| 	jsonData, err := json.Marshal(records) | ||||
| 	if err != nil { | ||||
| 		returnError(w, r, "internal error", 405, err, event) | ||||
| 		ReturnError(w, r, "internal error", 405, err, event) | ||||
| 		return | ||||
| 	} | ||||
| 	sessionUUID, err := uuid.GenerateUUID() | ||||
| 	if err != nil { | ||||
| 		returnError(w, r, "internal error", 405, err, event) | ||||
| 		ReturnError(w, r, "internal error", 405, err, event) | ||||
| 		return | ||||
| 	} | ||||
| 	sessionID, err := e.db.createSessionRecord(sessionUUID, userTOKEN, expiration, jsonData) | ||||
| 	if err != nil { | ||||
| 		returnError(w, r, "internal error", 405, err, event) | ||||
| 		ReturnError(w, r, "internal error", 405, err, event) | ||||
| 		return | ||||
| 	} | ||||
| 	w.Header().Set("Content-Type", "application/json; charset=utf-8") | ||||
| @@ -156,7 +157,7 @@ func (e mainEnv) getUserSessions(w http.ResponseWriter, r *http.Request, ps http | ||||
| 	if userTOKEN == "" { | ||||
| 		return | ||||
| 	} | ||||
| 	if e.enforceAuth(w, r, event) == "" { | ||||
| 	if e.EnforceAuth(w, r, event) == "" { | ||||
| 		return | ||||
| 	} | ||||
| 	e.db.store.DeleteExpired(storage.TblName.Sessions, "token", userTOKEN) | ||||
| @@ -164,14 +165,14 @@ func (e mainEnv) getUserSessions(w http.ResponseWriter, r *http.Request, ps http | ||||
| 	var offset int32 | ||||
| 	var limit int32 = 10 | ||||
| 	if value, ok := args["offset"]; ok { | ||||
| 		offset = atoi(value[0]) | ||||
| 		offset = utils.Atoi(value[0]) | ||||
| 	} | ||||
| 	if value, ok := args["limit"]; ok { | ||||
| 		limit = atoi(value[0]) | ||||
| 		limit = utils.Atoi(value[0]) | ||||
| 	} | ||||
| 	records, count, err := e.db.getUserSessionsByToken(userTOKEN, offset, limit) | ||||
| 	if err != nil { | ||||
| 		returnError(w, r, "internal error", 405, err, event) | ||||
| 		ReturnError(w, r, "internal error", 405, err, event) | ||||
| 		return | ||||
| 	} | ||||
| 	data := strings.Join(records, ",") | ||||
| @@ -194,11 +195,11 @@ func (e mainEnv) getSession(w http.ResponseWriter, r *http.Request, ps httproute | ||||
| 		e.db.store.DeleteExpired(storage.TblName.Sessions, "token", userTOKEN) | ||||
| 	} | ||||
| 	if err != nil { | ||||
| 		returnError(w, r, err.Error(), 405, err, event) | ||||
| 		ReturnError(w, r, err.Error(), 405, err, event) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	if e.enforceAuth(w, r, event) == "" { | ||||
| 	if e.EnforceAuth(w, r, event) == "" { | ||||
| 		return | ||||
| 	} | ||||
| 	w.Header().Set("Content-Type", "application/json; charset=utf-8") | ||||
|   | ||||
| @@ -7,6 +7,7 @@ import ( | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/securitybunker/databunker/src/storage" | ||||
| 	"github.com/securitybunker/databunker/src/utils" | ||||
| 	"go.mongodb.org/mongo-driver/bson" | ||||
| ) | ||||
|  | ||||
| @@ -20,7 +21,7 @@ func (dbobj dbcon) createSessionRecord(sessionUUID string, userTOKEN string, exp | ||||
| 	var err error | ||||
| 	now := int32(time.Now().Unix()) | ||||
| 	if len(expiration) > 0 { | ||||
| 		endtime, err = parseExpiration(expiration) | ||||
| 		endtime, err = utils.ParseExpiration(expiration) | ||||
| 		if err != nil { | ||||
| 			return "", err | ||||
| 		} | ||||
|   | ||||
| @@ -9,6 +9,7 @@ import ( | ||||
| 	"strings" | ||||
|  | ||||
| 	"github.com/julienschmidt/httprouter" | ||||
| 	"github.com/securitybunker/databunker/src/utils" | ||||
| 	"github.com/tidwall/gjson" | ||||
| ) | ||||
|  | ||||
| @@ -22,12 +23,12 @@ func (e mainEnv) newSharedRecord(w http.ResponseWriter, r *http.Request, ps http | ||||
| 	if userTOKEN == "" { | ||||
| 		return | ||||
| 	} | ||||
| 	if e.enforceAuth(w, r, event) == "" { | ||||
| 	if e.EnforceAuth(w, r, event) == "" { | ||||
| 		return | ||||
| 	} | ||||
| 	records, err := getJSONPostMap(r) | ||||
| 	records, err := utils.GetJSONPostMap(r) | ||||
| 	if err != nil { | ||||
| 		returnError(w, r, "failed to decode request body", 405, err, event) | ||||
| 		ReturnError(w, r, "failed to decode request body", 405, err, event) | ||||
| 		return | ||||
| 	} | ||||
| 	fields := "" | ||||
| @@ -52,21 +53,21 @@ func (e mainEnv) newSharedRecord(w http.ResponseWriter, r *http.Request, ps http | ||||
| 	} | ||||
| 	if value, ok := records["expiration"]; ok { | ||||
| 		if reflect.TypeOf(value) == reflect.TypeOf("string") { | ||||
| 			expiration = setExpiration(e.conf.Policy.MaxShareableRecordRetentionPeriod, value.(string)) | ||||
| 			expiration = utils.SetExpiration(e.conf.Policy.MaxShareableRecordRetentionPeriod, value.(string)) | ||||
| 		} else { | ||||
| 			returnError(w, r, "failed to parse expiration field", 405, err, event) | ||||
| 			ReturnError(w, r, "failed to parse expiration field", 405, err, event) | ||||
| 			return | ||||
| 		} | ||||
| 	} | ||||
| 	if value, ok := records["app"]; ok { | ||||
| 		if reflect.TypeOf(value) == reflect.TypeOf("string") { | ||||
| 			appName = strings.ToLower(value.(string)) | ||||
| 			if len(appName) > 0 && isValidApp(appName) == false { | ||||
| 				returnError(w, r, "unknown app name", 405, nil, event) | ||||
| 			if len(appName) > 0 && utils.CheckValidApp(appName) == false { | ||||
| 				ReturnError(w, r, "unknown app name", 405, nil, event) | ||||
| 			} | ||||
| 		} else { | ||||
| 			// type is different | ||||
| 			returnError(w, r, "failed to parse app field", 405, nil, event) | ||||
| 			ReturnError(w, r, "failed to parse app field", 405, nil, event) | ||||
| 		} | ||||
| 	} | ||||
| 	if len(expiration) == 0 { | ||||
| @@ -75,7 +76,7 @@ func (e mainEnv) newSharedRecord(w http.ResponseWriter, r *http.Request, ps http | ||||
| 	} | ||||
| 	recordUUID, err := e.db.saveSharedRecord(userTOKEN, fields, expiration, session, appName, partner, e.conf) | ||||
| 	if err != nil { | ||||
| 		returnError(w, r, err.Error(), 405, err, event) | ||||
| 		ReturnError(w, r, err.Error(), 405, err, event) | ||||
| 		return | ||||
| 	} | ||||
| 	event.Record = userTOKEN | ||||
| @@ -90,7 +91,7 @@ func (e mainEnv) getRecord(w http.ResponseWriter, r *http.Request, ps httprouter | ||||
| 	event := audit("get shareable record by token", record, "record", record) | ||||
| 	defer func() { event.submit(e.db, e.conf) }() | ||||
|  | ||||
| 	if enforceUUID(w, record, event) == false { | ||||
| 	if EnforceUUID(w, record, event) == false { | ||||
| 		return | ||||
| 	} | ||||
| 	recordInfo, err := e.db.getSharedRecord(record) | ||||
| @@ -114,18 +115,18 @@ func (e mainEnv) getRecord(w http.ResponseWriter, r *http.Request, ps httprouter | ||||
| 			resultJSON, err = e.db.getUserJSON(recordInfo.token) | ||||
| 		} | ||||
| 		if err != nil { | ||||
| 			returnError(w, r, "internal error", 405, err, event) | ||||
| 			ReturnError(w, r, "internal error", 405, err, event) | ||||
| 			return | ||||
| 		} | ||||
| 		if resultJSON == nil { | ||||
| 			returnError(w, r, "not found", 405, err, event) | ||||
| 			ReturnError(w, r, "not found", 405, err, event) | ||||
| 			return | ||||
| 		} | ||||
| 		log.Printf("Full json: %s\n", resultJSON) | ||||
| 		if len(recordInfo.fields) > 0 { | ||||
| 			raw := make(map[string]interface{}) | ||||
| 			//var newJSON json | ||||
| 			allFields := parseFields(recordInfo.fields) | ||||
| 			allFields := utils.ParseFields(recordInfo.fields) | ||||
| 			for _, f := range allFields { | ||||
| 				if f == "token" { | ||||
| 					raw["token"] = recordInfo.token | ||||
|   | ||||
| @@ -8,11 +8,12 @@ import ( | ||||
|  | ||||
| 	uuid "github.com/hashicorp/go-uuid" | ||||
| 	"github.com/securitybunker/databunker/src/storage" | ||||
| 	"github.com/securitybunker/databunker/src/utils" | ||||
| 	"go.mongodb.org/mongo-driver/bson" | ||||
| ) | ||||
|  | ||||
| func (dbobj dbcon) saveSharedRecord(userTOKEN string, fields string, expiration string, session string, appName string, partner string, conf Config) (string, error) { | ||||
| 	if isValidUUID(userTOKEN) == false { | ||||
| 	if utils.CheckValidUUID(userTOKEN) == false { | ||||
| 		return "", errors.New("bad uuid") | ||||
| 	} | ||||
| 	if len(expiration) == 0 { | ||||
| @@ -26,7 +27,7 @@ func (dbobj dbcon) saveSharedRecord(userTOKEN string, fields string, expiration | ||||
| 	} | ||||
|  | ||||
| 	log.Printf("Expiration is : %s\n", expiration) | ||||
| 	start, err := parseExpiration(expiration) | ||||
| 	start, err := utils.ParseExpiration(expiration) | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
| @@ -67,7 +68,7 @@ func (dbobj dbcon) saveSharedRecord(userTOKEN string, fields string, expiration | ||||
|  | ||||
| func (dbobj dbcon) getSharedRecord(recordUUID string) (checkRecordResult, error) { | ||||
| 	var result checkRecordResult | ||||
| 	//if isValidUUID(recordUUID) == false { | ||||
| 	//if utils.CheckValidUUID(recordUUID) == false { | ||||
| 	//	return result, errors.New("failed to authenticate") | ||||
| 	//} | ||||
| 	record, err := dbobj.store.GetRecord(storage.TblName.Sharedrecords, "record", recordUUID) | ||||
|   | ||||
| @@ -861,7 +861,7 @@ func (dbobj MySQLDB) GetAllTables() ([]string, error) { | ||||
|  | ||||
| // ValidateNewApp function check if app name can be part of the table name | ||||
| func (dbobj MySQLDB) ValidateNewApp(appName string) bool { | ||||
| 	if contains(allTables, appName) == true { | ||||
| 	if SliceContains(allTables, appName) == true { | ||||
| 		return true | ||||
| 	} | ||||
| 	return true | ||||
| @@ -891,7 +891,7 @@ func (dbobj MySQLDB) execQueries(queries []string) error { | ||||
|  | ||||
| // CreateNewAppTable creates a new app table and creates indexes for it. | ||||
| func (dbobj MySQLDB) CreateNewAppTable(appName string) { | ||||
| 	if contains(allTables, appName) == false { | ||||
| 	if SliceContains(allTables, appName) == false { | ||||
| 		// it is a new app, create an index | ||||
| 		log.Printf("This is a new app, creating table & index for: %s\n", appName) | ||||
| 		queries := []string{ | ||||
|   | ||||
| @@ -865,7 +865,7 @@ func (dbobj PGSQLDB) GetAllTables() ([]string, error) { | ||||
|  | ||||
| // ValidateNewApp function check if app name can be part of the table name | ||||
| func (dbobj PGSQLDB) ValidateNewApp(appName string) bool { | ||||
| 	if contains(allTables, appName) == true { | ||||
| 	if SliceContains(allTables, appName) == true { | ||||
| 		return true | ||||
| 	} | ||||
| 	if len(allTables) >= 100 { | ||||
| @@ -898,7 +898,7 @@ func (dbobj PGSQLDB) execQueries(queries []string) error { | ||||
|  | ||||
| // CreateNewAppTable creates a new app table and creates indexes for it. | ||||
| func (dbobj PGSQLDB) CreateNewAppTable(appName string) { | ||||
| 	if contains(allTables, appName) == false { | ||||
| 	if SliceContains(allTables, appName) == false { | ||||
| 		// it is a new app, create an index | ||||
| 		log.Printf("This is a new app, creating table & index for: %s\n", appName) | ||||
| 		queries := []string{ | ||||
|   | ||||
| @@ -849,7 +849,7 @@ func (dbobj SQLiteDB) GetAllTables() ([]string, error) { | ||||
|  | ||||
| // ValidateNewApp function check if app name can be part of the table name | ||||
| func (dbobj SQLiteDB) ValidateNewApp(appName string) bool { | ||||
| 	if contains(knownApps, appName) == true { | ||||
| 	if SliceContains(knownApps, appName) == true { | ||||
| 		return true | ||||
| 	} | ||||
| 	return true | ||||
| @@ -875,7 +875,7 @@ func (dbobj SQLiteDB) execQueries(queries []string) error { | ||||
|  | ||||
| // CreateNewAppTable creates a new app table and creates indexes for it. | ||||
| func (dbobj SQLiteDB) CreateNewAppTable(appName string) { | ||||
| 	if contains(knownApps, appName) == false { | ||||
| 	if SliceContains(knownApps, appName) == false { | ||||
| 		// it is a new app, create an index | ||||
| 		log.Printf("This is a new app, creating table & index for: %s\n", appName) | ||||
| 		queries := []string{"CREATE TABLE IF NOT EXISTS " + appName + ` ( | ||||
|   | ||||
| @@ -143,7 +143,7 @@ func CreateTestDB() string { | ||||
| 	return db.CreateTestDB() | ||||
| } | ||||
|  | ||||
| func contains(slice []string, item string) bool { | ||||
| func SliceContains(slice []string, item string) bool { | ||||
| 	set := make(map[string]struct{}, len(slice)) | ||||
| 	for _, s := range slice { | ||||
| 		set[s] = struct{}{} | ||||
|   | ||||
| @@ -7,6 +7,7 @@ import ( | ||||
| 	"strings" | ||||
|  | ||||
| 	"github.com/julienschmidt/httprouter" | ||||
| 	"github.com/securitybunker/databunker/src/utils" | ||||
| ) | ||||
|  | ||||
| func (e mainEnv) userappNew(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { | ||||
| @@ -20,38 +21,38 @@ func (e mainEnv) userappNew(w http.ResponseWriter, r *http.Request, ps httproute | ||||
| 	if userTOKEN == "" { | ||||
| 		return | ||||
| 	} | ||||
| 	if e.enforceAuth(w, r, event) == "" { | ||||
| 	if e.EnforceAuth(w, r, event) == "" { | ||||
| 		return | ||||
| 	} | ||||
| 	if isValidApp(appName) == false { | ||||
| 		returnError(w, r, "bad appname", 405, nil, event) | ||||
| 	if utils.CheckValidApp(appName) == false { | ||||
| 		ReturnError(w, r, "bad appname", 405, nil, event) | ||||
| 		return | ||||
| 	} | ||||
| 	if e.db.store.ValidateNewApp("app_"+appName) == false { | ||||
| 		returnError(w, r, "db limitation", 405, nil, event) | ||||
| 		ReturnError(w, r, "db limitation", 405, nil, event) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	data, err := getJSONPostMap(r) | ||||
| 	data, err := utils.GetJSONPostMap(r) | ||||
| 	if err != nil { | ||||
| 		returnError(w, r, "failed to decode request body", 405, err, event) | ||||
| 		ReturnError(w, r, "failed to decode request body", 405, err, event) | ||||
| 		return | ||||
| 	} | ||||
| 	if len(data) == 0 { | ||||
| 		returnError(w, r, "empty body", 405, nil, event) | ||||
| 		ReturnError(w, r, "empty body", 405, nil, event) | ||||
| 		return | ||||
| 	} | ||||
| 	jsonData, err := json.Marshal(data) | ||||
| 	if err != nil { | ||||
| 		returnError(w, r, "internal error", 405, err, event) | ||||
| 		ReturnError(w, r, "internal error", 405, err, event) | ||||
| 		return | ||||
| 	} | ||||
| 	_, err = e.db.createAppRecord(jsonData, userTOKEN, appName, event, e.conf) | ||||
| 	if err != nil { | ||||
| 		returnError(w, r, "internal error", 405, err, event) | ||||
| 		ReturnError(w, r, "internal error", 405, err, event) | ||||
| 		return | ||||
| 	} | ||||
| 	returnUUID(w, userTOKEN) | ||||
| 	utils.ReturnUUID(w, userTOKEN) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| @@ -65,58 +66,58 @@ func (e mainEnv) userappChange(w http.ResponseWriter, r *http.Request, ps httpro | ||||
| 	if userTOKEN == "" { | ||||
| 		return | ||||
| 	} | ||||
| 	authResult := e.enforceAuth(w, r, event) | ||||
| 	authResult := e.EnforceAuth(w, r, event) | ||||
| 	if authResult == "" { | ||||
| 		return | ||||
| 	} | ||||
| 	if isValidApp(appName) == false { | ||||
| 		returnError(w, r, "bad appname", 405, nil, event) | ||||
| 	if utils.CheckValidApp(appName) == false { | ||||
| 		ReturnError(w, r, "bad appname", 405, nil, event) | ||||
| 		return | ||||
| 	} | ||||
| 	jsonData, err := getJSONPostData(r) | ||||
| 	jsonData, err := utils.GetJSONPostData(r) | ||||
| 	if err != nil { | ||||
| 		returnError(w, r, "failed to decode request body", 405, err, event) | ||||
| 		ReturnError(w, r, "failed to decode request body", 405, err, event) | ||||
| 		return | ||||
| 	} | ||||
| 	if jsonData == nil { | ||||
| 		returnError(w, r, "empty body", 405, nil, event) | ||||
| 		ReturnError(w, r, "empty body", 405, nil, event) | ||||
| 		return | ||||
| 	} | ||||
| 	// make sure userapp exists | ||||
| 	resultJSON, err := e.db.getUserApp(userTOKEN, appName, e.conf) | ||||
| 	if err != nil { | ||||
| 		returnError(w, r, "internal error", 405, err, event) | ||||
| 		ReturnError(w, r, "internal error", 405, err, event) | ||||
| 		return | ||||
| 	} | ||||
| 	if resultJSON == nil { | ||||
| 		returnError(w, r, "not found", 405, nil, event) | ||||
| 		ReturnError(w, r, "not found", 405, nil, event) | ||||
| 		return | ||||
| 	} | ||||
| 	if authResult != "login" { | ||||
| 		_, err = e.db.updateAppRecord(jsonData, userTOKEN, appName, event, e.conf) | ||||
| 		if err != nil { | ||||
| 			returnError(w, r, "internal error", 405, err, event) | ||||
| 			ReturnError(w, r, "internal error", 405, err, event) | ||||
| 			return | ||||
| 		} | ||||
| 		returnUUID(w, userTOKEN) | ||||
| 		utils.ReturnUUID(w, userTOKEN) | ||||
| 		return | ||||
| 	} | ||||
| 	if e.conf.SelfService.AppRecordChange != nil { | ||||
| 		for _, name := range e.conf.SelfService.AppRecordChange { | ||||
| 			if stringPatternMatch(strings.ToLower(name), appName) { | ||||
| 			if utils.StringPatternMatch(strings.ToLower(name), appName) { | ||||
| 				_, err = e.db.updateAppRecord(jsonData, userTOKEN, appName, event, e.conf) | ||||
| 				if err != nil { | ||||
| 					returnError(w, r, "internal error", 405, err, event) | ||||
| 					ReturnError(w, r, "internal error", 405, err, event) | ||||
| 					return | ||||
| 				} | ||||
| 				returnUUID(w, userTOKEN) | ||||
| 				utils.ReturnUUID(w, userTOKEN) | ||||
| 				return | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	rtoken, rstatus, err := e.db.saveUserRequest("change-app-data", userTOKEN, appName, "", jsonData, e.conf) | ||||
| 	if err != nil { | ||||
| 		returnError(w, r, "internal error", 405, err, event) | ||||
| 		ReturnError(w, r, "internal error", 405, err, event) | ||||
| 		return | ||||
| 	} | ||||
| 	w.Header().Set("Content-Type", "application/json; charset=utf-8") | ||||
| @@ -133,12 +134,12 @@ func (e mainEnv) userappList(w http.ResponseWriter, r *http.Request, ps httprout | ||||
| 	if userTOKEN == "" { | ||||
| 		return | ||||
| 	} | ||||
| 	if e.enforceAuth(w, r, event) == "" { | ||||
| 	if e.EnforceAuth(w, r, event) == "" { | ||||
| 		return | ||||
| 	} | ||||
| 	result, err := e.db.listUserApps(userTOKEN, e.conf) | ||||
| 	if err != nil { | ||||
| 		returnError(w, r, "internal error", 405, err, event) | ||||
| 		ReturnError(w, r, "internal error", 405, err, event) | ||||
| 		return | ||||
| 	} | ||||
| 	w.Header().Set("Content-Type", "application/json; charset=utf-8") | ||||
| @@ -156,20 +157,20 @@ func (e mainEnv) userappGet(w http.ResponseWriter, r *http.Request, ps httproute | ||||
| 	if userTOKEN == "" { | ||||
| 		return | ||||
| 	} | ||||
| 	if e.enforceAuth(w, r, event) == "" { | ||||
| 	if e.EnforceAuth(w, r, event) == "" { | ||||
| 		return | ||||
| 	} | ||||
| 	if isValidApp(appName) == false { | ||||
| 		returnError(w, r, "bad appname", 405, nil, event) | ||||
| 	if utils.CheckValidApp(appName) == false { | ||||
| 		ReturnError(w, r, "bad appname", 405, nil, event) | ||||
| 		return | ||||
| 	} | ||||
| 	resultJSON, err := e.db.getUserApp(userTOKEN, appName, e.conf) | ||||
| 	if err != nil { | ||||
| 		returnError(w, r, "internal error", 405, err, event) | ||||
| 		ReturnError(w, r, "internal error", 405, err, event) | ||||
| 		return | ||||
| 	} | ||||
| 	if resultJSON == nil { | ||||
| 		returnError(w, r, "not found", 405, nil, event) | ||||
| 		ReturnError(w, r, "not found", 405, nil, event) | ||||
| 		return | ||||
| 	} | ||||
| 	finalJSON := fmt.Sprintf(`{"status":"ok","token":"%s","data":%s}`, userTOKEN, resultJSON) | ||||
| @@ -188,11 +189,11 @@ func (e mainEnv) userappDelete(w http.ResponseWriter, r *http.Request, ps httpro | ||||
| 	if userTOKEN == "" { | ||||
| 		return | ||||
| 	} | ||||
| 	if e.enforceAuth(w, r, event) == "" { | ||||
| 	if e.EnforceAuth(w, r, event) == "" { | ||||
| 		return | ||||
| 	} | ||||
| 	if isValidApp(appName) == false { | ||||
| 		returnError(w, r, "bad appname", 405, nil, event) | ||||
| 	if utils.CheckValidApp(appName) == false { | ||||
| 		ReturnError(w, r, "bad appname", 405, nil, event) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| @@ -205,12 +206,12 @@ func (e mainEnv) userappDelete(w http.ResponseWriter, r *http.Request, ps httpro | ||||
| } | ||||
|  | ||||
| func (e mainEnv) appList(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { | ||||
| 	if e.enforceAuth(w, r, nil) == "" { | ||||
| 	if e.EnforceAuth(w, r, nil) == "" { | ||||
| 		return | ||||
| 	} | ||||
| 	result, err := e.db.listAllApps(e.conf) | ||||
| 	if err != nil { | ||||
| 		returnError(w, r, "internal error", 405, err, nil) | ||||
| 		ReturnError(w, r, "internal error", 405, err, nil) | ||||
| 		return | ||||
| 	} | ||||
| 	w.Header().Set("Content-Type", "application/json; charset=utf-8") | ||||
|   | ||||
							
								
								
									
										157
									
								
								src/users_api.go
									
									
									
									
									
								
							
							
						
						
									
										157
									
								
								src/users_api.go
									
									
									
									
									
								
							| @@ -8,6 +8,7 @@ import ( | ||||
|  | ||||
| 	"github.com/julienschmidt/httprouter" | ||||
| 	"github.com/securitybunker/databunker/src/storage" | ||||
| 	"github.com/securitybunker/databunker/src/utils" | ||||
| 	"go.mongodb.org/mongo-driver/bson" | ||||
| ) | ||||
|  | ||||
| @@ -17,98 +18,98 @@ func (e mainEnv) userCreate(w http.ResponseWriter, r *http.Request, ps httproute | ||||
|  | ||||
| 	if e.conf.Generic.CreateUserWithoutAccessToken == false { | ||||
| 		// anonymous user can not create user record, check token | ||||
| 		if e.enforceAuth(w, r, event) == "" { | ||||
| 		if e.EnforceAuth(w, r, event) == "" { | ||||
| 			log.Println("Failed to create user, access denied, try to configure Create_user_without_access_token") | ||||
| 			return | ||||
| 		} | ||||
| 	} | ||||
| 	userJSON, err := getUserJSON(r, e.conf.Sms.DefaultCountry) | ||||
| 	userJSON, err := utils.GetUserJSONStruct(r, e.conf.Sms.DefaultCountry) | ||||
| 	if err != nil { | ||||
| 		returnError(w, r, "failed to decode request body", 405, err, event) | ||||
| 		ReturnError(w, r, "failed to decode request body", 405, err, event) | ||||
| 		return | ||||
| 	} | ||||
| 	if len(userJSON.jsonData) == 0 { | ||||
| 		returnError(w, r, "empty request body", 405, nil, event) | ||||
| 	if len(userJSON.JsonData) == 0 { | ||||
| 		ReturnError(w, r, "empty request body", 405, nil, event) | ||||
| 		return | ||||
| 	} | ||||
| 	err = validateUserRecord(userJSON.jsonData) | ||||
| 	err = validateUserRecord(userJSON.JsonData) | ||||
| 	if err != nil { | ||||
| 		returnError(w, r, "user schema error: "+err.Error(), 405, err, event) | ||||
| 		ReturnError(w, r, "user schema error: "+err.Error(), 405, err, event) | ||||
| 		return | ||||
| 	} | ||||
| 	// make sure that login, email and phone are unique | ||||
| 	if len(userJSON.loginIdx) > 0 { | ||||
| 		otherUserBson, err := e.db.lookupUserRecordByIndex("login", userJSON.loginIdx, e.conf) | ||||
| 	if len(userJSON.LoginIdx) > 0 { | ||||
| 		otherUserBson, err := e.db.lookupUserRecordByIndex("login", userJSON.LoginIdx, e.conf) | ||||
| 		if err != nil { | ||||
| 			returnError(w, r, "internal error", 405, err, event) | ||||
| 			ReturnError(w, r, "internal error", 405, err, event) | ||||
| 			return | ||||
| 		} | ||||
| 		if otherUserBson != nil { | ||||
| 			returnError(w, r, "duplicate index: login", 405, nil, event) | ||||
| 			ReturnError(w, r, "duplicate index: login", 405, nil, event) | ||||
| 			return | ||||
| 		} | ||||
| 	} | ||||
| 	if len(userJSON.emailIdx) > 0 { | ||||
| 		otherUserBson, err := e.db.lookupUserRecordByIndex("email", userJSON.emailIdx, e.conf) | ||||
| 	if len(userJSON.EmailIdx) > 0 { | ||||
| 		otherUserBson, err := e.db.lookupUserRecordByIndex("email", userJSON.EmailIdx, e.conf) | ||||
| 		if err != nil { | ||||
| 			returnError(w, r, "internal error", 405, err, event) | ||||
| 			ReturnError(w, r, "internal error", 405, err, event) | ||||
| 			return | ||||
| 		} | ||||
| 		if otherUserBson != nil { | ||||
| 			returnError(w, r, "duplicate index: email", 405, nil, event) | ||||
| 			ReturnError(w, r, "duplicate index: email", 405, nil, event) | ||||
| 			return | ||||
| 		} | ||||
| 	} | ||||
| 	if len(userJSON.phoneIdx) > 0 { | ||||
| 		otherUserBson, err := e.db.lookupUserRecordByIndex("phone", userJSON.phoneIdx, e.conf) | ||||
| 	if len(userJSON.PhoneIdx) > 0 { | ||||
| 		otherUserBson, err := e.db.lookupUserRecordByIndex("phone", userJSON.PhoneIdx, e.conf) | ||||
| 		if err != nil { | ||||
| 			returnError(w, r, "internal error", 405, err, event) | ||||
| 			ReturnError(w, r, "internal error", 405, err, event) | ||||
| 			return | ||||
| 		} | ||||
| 		if otherUserBson != nil { | ||||
| 			returnError(w, r, "duplicate index: phone", 405, nil, event) | ||||
| 			ReturnError(w, r, "duplicate index: phone", 405, nil, event) | ||||
| 			return | ||||
| 		} | ||||
| 	} | ||||
| 	if len(userJSON.customIdx) > 0 { | ||||
| 		otherUserBson, err := e.db.lookupUserRecordByIndex("custom", userJSON.customIdx, e.conf) | ||||
| 	if len(userJSON.CustomIdx) > 0 { | ||||
| 		otherUserBson, err := e.db.lookupUserRecordByIndex("custom", userJSON.CustomIdx, e.conf) | ||||
| 		if err != nil { | ||||
| 			returnError(w, r, "internal error", 405, err, event) | ||||
| 			ReturnError(w, r, "internal error", 405, err, event) | ||||
| 			return | ||||
| 		} | ||||
| 		if otherUserBson != nil { | ||||
| 			returnError(w, r, "duplicate index: custom", 405, nil, event) | ||||
| 			ReturnError(w, r, "duplicate index: custom", 405, nil, event) | ||||
| 			return | ||||
| 		} | ||||
| 	} | ||||
| 	if len(userJSON.loginIdx) == 0 && | ||||
| 		len(userJSON.emailIdx) == 0 && | ||||
| 		len(userJSON.phoneIdx) == 0 && | ||||
| 		len(userJSON.customIdx) == 0 { | ||||
| 		returnError(w, r, "failed to create user, all user lookup fields are missing", 405, err, event) | ||||
| 	if len(userJSON.LoginIdx) == 0 && | ||||
| 		len(userJSON.EmailIdx) == 0 && | ||||
| 		len(userJSON.PhoneIdx) == 0 && | ||||
| 		len(userJSON.CustomIdx) == 0 { | ||||
| 		ReturnError(w, r, "failed to create user, all user lookup fields are missing", 405, err, event) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	userTOKEN, err := e.db.createUserRecord(userJSON, event) | ||||
| 	if err != nil { | ||||
| 		returnError(w, r, "internal error", 405, err, event) | ||||
| 		ReturnError(w, r, "internal error", 405, err, event) | ||||
| 		return | ||||
| 	} | ||||
| 	encPhoneIdx := "" | ||||
| 	if len(userJSON.emailIdx) > 0 { | ||||
| 		encEmailIdx, _ := basicStringEncrypt(userJSON.emailIdx, e.db.masterKey, e.db.GetCode()) | ||||
| 	if len(userJSON.EmailIdx) > 0 { | ||||
| 		encEmailIdx, _ := basicStringEncrypt(userJSON.EmailIdx, e.db.masterKey, e.db.GetCode()) | ||||
| 		e.db.linkAgreementRecords(userTOKEN, encEmailIdx) | ||||
| 	} | ||||
| 	if len(userJSON.phoneIdx) > 0 { | ||||
| 		encPhoneIdx, _ = basicStringEncrypt(userJSON.phoneIdx, e.db.masterKey, e.db.GetCode()) | ||||
| 	if len(userJSON.PhoneIdx) > 0 { | ||||
| 		encPhoneIdx, _ = basicStringEncrypt(userJSON.PhoneIdx, e.db.masterKey, e.db.GetCode()) | ||||
| 		e.db.linkAgreementRecords(userTOKEN, encPhoneIdx) | ||||
| 	} | ||||
| 	if len(userJSON.emailIdx) > 0 && len(userJSON.phoneIdx) > 0 { | ||||
| 	if len(userJSON.EmailIdx) > 0 && len(userJSON.PhoneIdx) > 0 { | ||||
| 		// delete duplicate consent records for user | ||||
| 		records, _ := e.db.store.GetList(storage.TblName.Agreements, "token", userTOKEN, 0, 0, "") | ||||
| 		var briefCodes []string | ||||
| 		for _, val := range records { | ||||
| 			if contains(briefCodes, val["brief"].(string)) == true { | ||||
| 			if utils.SliceContains(briefCodes, val["brief"].(string)) == true { | ||||
| 				e.db.store.DeleteRecord2(storage.TblName.Agreements, "token", userTOKEN, "who", encPhoneIdx) | ||||
| 			} else { | ||||
| 				briefCodes = append(briefCodes, val["brief"].(string)) | ||||
| @@ -116,9 +117,9 @@ func (e mainEnv) userCreate(w http.ResponseWriter, r *http.Request, ps httproute | ||||
| 		} | ||||
| 	} | ||||
| 	event.Record = userTOKEN | ||||
| 	returnUUID(w, userTOKEN) | ||||
| 	utils.ReturnUUID(w, userTOKEN) | ||||
| 	notifyURL := e.conf.Notification.NotificationURL | ||||
| 	notifyProfileNew(notifyURL, userJSON.jsonData, "token", userTOKEN) | ||||
| 	notifyProfileNew(notifyURL, userJSON.JsonData, "token", userTOKEN) | ||||
| } | ||||
|  | ||||
| func (e mainEnv) userGet(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { | ||||
| @@ -129,14 +130,14 @@ func (e mainEnv) userGet(w http.ResponseWriter, r *http.Request, ps httprouter.P | ||||
| 	event := audit("get user record by "+mode, identity, mode, identity) | ||||
| 	defer func() { event.submit(e.db, e.conf) }() | ||||
|  | ||||
| 	if validateMode(mode) == false { | ||||
| 		returnError(w, r, "bad mode", 405, nil, event) | ||||
| 	if utils.ValidateMode(mode) == false { | ||||
| 		ReturnError(w, r, "bad mode", 405, nil, event) | ||||
| 		return | ||||
| 	} | ||||
| 	userTOKEN := "" | ||||
| 	authResult := "" | ||||
| 	if mode == "token" { | ||||
| 		if enforceUUID(w, identity, event) == false { | ||||
| 		if EnforceUUID(w, identity, event) == false { | ||||
| 			return | ||||
| 		} | ||||
| 		resultJSON, err = e.db.getUserJSON(identity) | ||||
| @@ -146,15 +147,15 @@ func (e mainEnv) userGet(w http.ResponseWriter, r *http.Request, ps httprouter.P | ||||
| 		event.Record = userTOKEN | ||||
| 	} | ||||
| 	if err != nil { | ||||
| 		returnError(w, r, "internal error", 405, err, event) | ||||
| 		ReturnError(w, r, "internal error", 405, err, event) | ||||
| 		return | ||||
| 	} | ||||
| 	authResult = e.enforceAuth(w, r, event) | ||||
| 	authResult = e.EnforceAuth(w, r, event) | ||||
| 	if authResult == "" { | ||||
| 		return | ||||
| 	} | ||||
| 	if resultJSON == nil { | ||||
| 		returnError(w, r, "record not found", 405, nil, event) | ||||
| 		ReturnError(w, r, "record not found", 405, nil, event) | ||||
| 		return | ||||
| 	} | ||||
| 	finalJSON := fmt.Sprintf(`{"status":"ok","token":"%s","data":%s}`, userTOKEN, resultJSON) | ||||
| @@ -166,21 +167,21 @@ func (e mainEnv) userGet(w http.ResponseWriter, r *http.Request, ps httprouter.P | ||||
| } | ||||
|  | ||||
| func (e mainEnv) userList(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { | ||||
| 	if e.enforceAdmin(w, r, nil) == "" { | ||||
| 	if e.EnforceAdmin(w, r, nil) == "" { | ||||
| 		return | ||||
| 	} | ||||
| 	if e.conf.Generic.ListUsers == false { | ||||
| 		returnError(w, r, "access denied", 403, nil, nil) | ||||
| 		ReturnError(w, r, "access denied", 403, nil, nil) | ||||
| 		return | ||||
| 	} | ||||
| 	var offset int32 = 0 | ||||
| 	var limit int32 = 10 | ||||
| 	args := r.URL.Query() | ||||
| 	if value, ok := args["offset"]; ok { | ||||
| 		offset = atoi(value[0]) | ||||
| 		offset = utils.Atoi(value[0]) | ||||
| 	} | ||||
| 	if value, ok := args["limit"]; ok { | ||||
| 		limit = atoi(value[0]) | ||||
| 		limit = utils.Atoi(value[0]) | ||||
| 	} | ||||
| 	resultJSON, counter, _ := e.db.getUsers(offset, limit) | ||||
| 	log.Printf("Total count of events: %d\n", counter) | ||||
| @@ -201,25 +202,25 @@ func (e mainEnv) userChange(w http.ResponseWriter, r *http.Request, ps httproute | ||||
| 	event := audit("change user record by "+mode, identity, mode, identity) | ||||
| 	defer func() { event.submit(e.db, e.conf) }() | ||||
|  | ||||
| 	if validateMode(mode) == false { | ||||
| 		returnError(w, r, "bad index", 405, nil, event) | ||||
| 	if utils.ValidateMode(mode) == false { | ||||
| 		ReturnError(w, r, "bad index", 405, nil, event) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	jsonData, err := getJSONPostData(r) | ||||
| 	jsonData, err := utils.GetJSONPostData(r) | ||||
| 	if err != nil { | ||||
| 		returnError(w, r, "failed to decode request body", 405, err, event) | ||||
| 		ReturnError(w, r, "failed to decode request body", 405, err, event) | ||||
| 		return | ||||
| 	} | ||||
| 	if jsonData == nil { | ||||
| 		returnError(w, r, "empty request body", 405, nil, event) | ||||
| 		ReturnError(w, r, "empty request body", 405, nil, event) | ||||
| 		return | ||||
| 	} | ||||
| 	userTOKEN := "" | ||||
| 	var userJSON []byte | ||||
| 	var userBSON bson.M | ||||
| 	if mode == "token" { | ||||
| 		if enforceUUID(w, identity, event) == false { | ||||
| 		if EnforceUUID(w, identity, event) == false { | ||||
| 			return | ||||
| 		} | ||||
| 		userTOKEN = identity | ||||
| @@ -229,14 +230,14 @@ func (e mainEnv) userChange(w http.ResponseWriter, r *http.Request, ps httproute | ||||
| 		event.Record = userTOKEN | ||||
| 	} | ||||
| 	if err != nil { | ||||
| 		returnError(w, r, "internal error", 405, err, event) | ||||
| 		ReturnError(w, r, "internal error", 405, err, event) | ||||
| 		return | ||||
| 	} | ||||
| 	if userJSON == nil { | ||||
| 		returnError(w, r, "user record not found", 405, nil, event) | ||||
| 		ReturnError(w, r, "user record not found", 405, nil, event) | ||||
| 		return | ||||
| 	} | ||||
| 	authResult := e.enforceAuth(w, r, event) | ||||
| 	authResult := e.EnforceAuth(w, r, event) | ||||
| 	if authResult == "" { | ||||
| 		return | ||||
| 	} | ||||
| @@ -244,7 +245,7 @@ func (e mainEnv) userChange(w http.ResponseWriter, r *http.Request, ps httproute | ||||
| 	if UserSchemaEnabled() { | ||||
| 		adminRecordChanged, err = e.db.validateUserRecordChange(userJSON, jsonData, userTOKEN, authResult) | ||||
| 		if err != nil { | ||||
| 			returnError(w, r, "schema validation error: "+err.Error(), 405, err, event) | ||||
| 			ReturnError(w, r, "schema validation error: "+err.Error(), 405, err, event) | ||||
| 			return | ||||
| 		} | ||||
| 	} | ||||
| @@ -253,7 +254,7 @@ func (e mainEnv) userChange(w http.ResponseWriter, r *http.Request, ps httproute | ||||
| 		if e.conf.SelfService.UserRecordChange == false || adminRecordChanged == true { | ||||
| 			rtoken, rstatus, err := e.db.saveUserRequest("change-profile", userTOKEN, "", "", jsonData, e.conf) | ||||
| 			if err != nil { | ||||
| 				returnError(w, r, "internal error", 405, err, event) | ||||
| 				ReturnError(w, r, "internal error", 405, err, event) | ||||
| 				return | ||||
| 			} | ||||
| 			w.Header().Set("Content-Type", "application/json; charset=utf-8") | ||||
| @@ -264,14 +265,14 @@ func (e mainEnv) userChange(w http.ResponseWriter, r *http.Request, ps httproute | ||||
| 	} | ||||
| 	oldJSON, newJSON, lookupErr, err := e.db.updateUserRecord(jsonData, userTOKEN, userBSON, event, e.conf) | ||||
| 	if lookupErr { | ||||
| 		returnError(w, r, "record not found", 405, errors.New("record not found"), event) | ||||
| 		ReturnError(w, r, "record not found", 405, errors.New("record not found"), event) | ||||
| 		return | ||||
| 	} | ||||
| 	if err != nil { | ||||
| 		returnError(w, r, "error updating user", 405, err, event) | ||||
| 		ReturnError(w, r, "error updating user", 405, err, event) | ||||
| 		return | ||||
| 	} | ||||
| 	returnUUID(w, userTOKEN) | ||||
| 	utils.ReturnUUID(w, userTOKEN) | ||||
| 	notifyURL := e.conf.Notification.NotificationURL | ||||
| 	notifyProfileChange(notifyURL, oldJSON, newJSON, "token", userTOKEN) | ||||
| } | ||||
| @@ -283,8 +284,8 @@ func (e mainEnv) userDelete(w http.ResponseWriter, r *http.Request, ps httproute | ||||
| 	event := audit("delete user record by "+mode, identity, mode, identity) | ||||
| 	defer func() { event.submit(e.db, e.conf) }() | ||||
|  | ||||
| 	if validateMode(mode) == false { | ||||
| 		returnError(w, r, "bad mode", 405, nil, event) | ||||
| 	if utils.ValidateMode(mode) == false { | ||||
| 		ReturnError(w, r, "bad mode", 405, nil, event) | ||||
| 		return | ||||
| 	} | ||||
| 	var err error | ||||
| @@ -292,7 +293,7 @@ func (e mainEnv) userDelete(w http.ResponseWriter, r *http.Request, ps httproute | ||||
| 	var userJSON []byte | ||||
| 	userTOKEN := identity | ||||
| 	if mode == "token" { | ||||
| 		if enforceUUID(w, identity, event) == false { | ||||
| 		if EnforceUUID(w, identity, event) == false { | ||||
| 			return | ||||
| 		} | ||||
| 		userJSON, userBSON, err = e.db.getUser(identity) | ||||
| @@ -301,10 +302,10 @@ func (e mainEnv) userDelete(w http.ResponseWriter, r *http.Request, ps httproute | ||||
| 		event.Record = userTOKEN | ||||
| 	} | ||||
| 	if err != nil { | ||||
| 		returnError(w, r, "internal error", 405, nil, event) | ||||
| 		ReturnError(w, r, "internal error", 405, nil, event) | ||||
| 		return | ||||
| 	} | ||||
| 	authResult := e.enforceAuth(w, r, event) | ||||
| 	authResult := e.EnforceAuth(w, r, event) | ||||
| 	if authResult == "" { | ||||
| 		return | ||||
| 	} | ||||
| @@ -315,7 +316,7 @@ func (e mainEnv) userDelete(w http.ResponseWriter, r *http.Request, ps httproute | ||||
| 			w.WriteHeader(200) | ||||
| 			fmt.Fprintf(w, `{"status":"ok","result":"done"}`) | ||||
| 		} | ||||
| 		returnError(w, r, "record not found", 405, nil, event) | ||||
| 		ReturnError(w, r, "record not found", 405, nil, event) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| @@ -324,7 +325,7 @@ func (e mainEnv) userDelete(w http.ResponseWriter, r *http.Request, ps httproute | ||||
| 		if e.conf.SelfService.ForgetMe == false { | ||||
| 			rtoken, rstatus, err := e.db.saveUserRequest("forget-me", userTOKEN, "", "", nil, e.conf) | ||||
| 			if err != nil { | ||||
| 				returnError(w, r, "internal error", 405, err, event) | ||||
| 				ReturnError(w, r, "internal error", 405, err, event) | ||||
| 				return | ||||
| 			} | ||||
| 			w.Header().Set("Content-Type", "application/json; charset=utf-8") | ||||
| @@ -333,14 +334,14 @@ func (e mainEnv) userDelete(w http.ResponseWriter, r *http.Request, ps httproute | ||||
| 			return | ||||
| 		} | ||||
| 	} | ||||
| 	email := getStringValue(userBSON["email"]) | ||||
| 	email := utils.GetStringValue(userBSON["email"]) | ||||
| 	if len(email) > 0 { | ||||
| 		e.globalUserDelete(email) | ||||
| 	} | ||||
| 	//fmt.Printf("deleting user %s\n", userTOKEN) | ||||
| 	_, err = e.db.deleteUserRecord(userJSON, userTOKEN, e.conf) | ||||
| 	if err != nil { | ||||
| 		returnError(w, r, "internal error", 405, err, event) | ||||
| 		ReturnError(w, r, "internal error", 405, err, event) | ||||
| 		return | ||||
| 	} | ||||
| 	w.Header().Set("Content-Type", "application/json; charset=utf-8") | ||||
| @@ -366,12 +367,12 @@ func (e mainEnv) userPrelogin(w http.ResponseWriter, r *http.Request, ps httprou | ||||
| 		return | ||||
| 	} | ||||
| 	if mode != "phone" && mode != "email" { | ||||
| 		returnError(w, r, "bad mode", 405, nil, event) | ||||
| 		ReturnError(w, r, "bad mode", 405, nil, event) | ||||
| 		return | ||||
| 	} | ||||
| 	userBson, err := e.db.lookupUserRecordByIndex(mode, identity, e.conf) | ||||
| 	if err != nil { | ||||
| 		returnError(w, r, "internal error", 405, err, event) | ||||
| 		ReturnError(w, r, "internal error", 405, err, event) | ||||
| 		return | ||||
| 	} | ||||
| 	if userBson != nil { | ||||
| @@ -394,7 +395,7 @@ func (e mainEnv) userPrelogin(w http.ResponseWriter, r *http.Request, ps httprou | ||||
| 			//notifyURL := e.conf.Notification.NotificationURL | ||||
| 			//notifyBadLogin(notifyURL, mode, identity) | ||||
| 			e.pluginUserLookup(identity) | ||||
| 			//returnError(w, r, "record not found", 405, errors.New("record not found"), event) | ||||
| 			//ReturnError(w, r, "record not found", 405, errors.New("record not found"), event) | ||||
| 			captcha, _ := generateCaptcha() | ||||
| 			w.Header().Set("Content-Type", "application/json; charset=utf-8") | ||||
| 			w.WriteHeader(403) | ||||
| @@ -409,20 +410,20 @@ func (e mainEnv) userPrelogin(w http.ResponseWriter, r *http.Request, ps httprou | ||||
| } | ||||
|  | ||||
| func (e mainEnv) userLogin(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { | ||||
| 	tmp := atoi(ps.ByName("tmp")) | ||||
| 	tmp := utils.Atoi(ps.ByName("tmp")) | ||||
| 	identity := ps.ByName("identity") | ||||
| 	mode := ps.ByName("mode") | ||||
| 	event := audit("user login by "+mode, identity, mode, identity) | ||||
| 	defer func() { event.submit(e.db, e.conf) }() | ||||
|  | ||||
| 	if mode != "phone" && mode != "email" { | ||||
| 		returnError(w, r, "bad mode", 405, nil, event) | ||||
| 		ReturnError(w, r, "bad mode", 405, nil, event) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	userBson, err := e.db.lookupUserRecordByIndex(mode, identity, e.conf) | ||||
| 	if userBson == nil || err != nil { | ||||
| 		returnError(w, r, "internal error", 405, err, event) | ||||
| 		ReturnError(w, r, "internal error", 405, err, event) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| @@ -438,7 +439,7 @@ func (e mainEnv) userLogin(w http.ResponseWriter, r *http.Request, ps httprouter | ||||
| 		xtoken, hashedToken, err := e.db.generateUserLoginXtoken(userTOKEN) | ||||
| 		//fmt.Printf("generate user access token: %s\n", xtoken) | ||||
| 		if err != nil { | ||||
| 			returnError(w, r, "internal error", 405, err, event) | ||||
| 			ReturnError(w, r, "internal error", 405, err, event) | ||||
| 			return | ||||
| 		} | ||||
| 		event.Msg = "generated: " + hashedToken | ||||
| @@ -447,5 +448,5 @@ func (e mainEnv) userLogin(w http.ResponseWriter, r *http.Request, ps httprouter | ||||
| 		fmt.Fprintf(w, `{"status":"ok","xtoken":"%s","token":"%s"}`, xtoken, userTOKEN) | ||||
| 		return | ||||
| 	} | ||||
| 	returnError(w, r, "internal error", 405, nil, event) | ||||
| 	ReturnError(w, r, "internal error", 405, nil, event) | ||||
| } | ||||
|   | ||||
| @@ -12,10 +12,11 @@ import ( | ||||
| 	jsonpatch "github.com/evanphx/json-patch" | ||||
| 	uuid "github.com/hashicorp/go-uuid" | ||||
| 	"github.com/securitybunker/databunker/src/storage" | ||||
| 	"github.com/securitybunker/databunker/src/utils" | ||||
| 	"go.mongodb.org/mongo-driver/bson" | ||||
| ) | ||||
|  | ||||
| func (dbobj dbcon) createUserRecord(parsedData userJSON, event *auditEvent) (string, error) { | ||||
| func (dbobj dbcon) createUserRecord(parsedData utils.UserJSONStruct, event *auditEvent) (string, error) { | ||||
| 	var userTOKEN string | ||||
| 	//var bdoc interface{} | ||||
| 	bdoc := bson.M{} | ||||
| @@ -28,7 +29,7 @@ func (dbobj dbcon) createUserRecord(parsedData userJSON, event *auditEvent) (str | ||||
| 		return "", err | ||||
| 	} | ||||
| 	//err = bson.UnmarshalExtJSON(jsonData, false, &bdoc) | ||||
| 	encoded, err := encrypt(dbobj.masterKey, userKeyBinary, parsedData.jsonData) | ||||
| 	encoded, err := encrypt(dbobj.masterKey, userKeyBinary, parsedData.JsonData) | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
| @@ -43,17 +44,17 @@ func (dbobj dbcon) createUserRecord(parsedData userJSON, event *auditEvent) (str | ||||
| 	// the index search field is hashed here, to be not-reversible | ||||
| 	// I use original md5(master_key) as a kind of salt here, | ||||
| 	// so no additional configuration field is needed here. | ||||
| 	if len(parsedData.loginIdx) > 0 { | ||||
| 		bdoc["loginidx"] = hashString(dbobj.hash, parsedData.loginIdx) | ||||
| 	if len(parsedData.LoginIdx) > 0 { | ||||
| 		bdoc["loginidx"] = utils.HashString(dbobj.hash, parsedData.LoginIdx) | ||||
| 	} | ||||
| 	if len(parsedData.emailIdx) > 0 { | ||||
| 		bdoc["emailidx"] = hashString(dbobj.hash, parsedData.emailIdx) | ||||
| 	if len(parsedData.EmailIdx) > 0 { | ||||
| 		bdoc["emailidx"] = utils.HashString(dbobj.hash, parsedData.EmailIdx) | ||||
| 	} | ||||
| 	if len(parsedData.phoneIdx) > 0 { | ||||
| 		bdoc["phoneidx"] = hashString(dbobj.hash, parsedData.phoneIdx) | ||||
| 	if len(parsedData.PhoneIdx) > 0 { | ||||
| 		bdoc["phoneidx"] = utils.HashString(dbobj.hash, parsedData.PhoneIdx) | ||||
| 	} | ||||
| 	if len(parsedData.customIdx) > 0 { | ||||
| 		bdoc["customidx"] = hashString(dbobj.hash, parsedData.customIdx) | ||||
| 	if len(parsedData.CustomIdx) > 0 { | ||||
| 		bdoc["customidx"] = utils.HashString(dbobj.hash, parsedData.CustomIdx) | ||||
| 	} | ||||
| 	if event != nil { | ||||
| 		event.After = encodedStr | ||||
| @@ -93,7 +94,7 @@ func (dbobj dbcon) updateUserExpStatus(userTOKEN string, status string) error { | ||||
| } | ||||
|  | ||||
| func (dbobj dbcon) generateTempLoginCode(userTOKEN string) int32 { | ||||
| 	rnd := randNum(6) | ||||
| 	rnd := utils.RandNum(6) | ||||
| 	log.Printf("Random: %d\n", rnd) | ||||
| 	bdoc := bson.M{} | ||||
| 	bdoc["tempcode"] = rnd | ||||
| @@ -185,7 +186,7 @@ func (dbobj dbcon) updateUserRecordDo(jsonDataPatch []byte, userTOKEN string, ol | ||||
| 	} | ||||
| 	oldEmail := "" | ||||
| 	if _, ok := raw2["email"]; ok { | ||||
| 		oldEmail = normalizeEmail(raw2["email"].(string)) | ||||
| 		oldEmail = utils.NormalizeEmail(raw2["email"].(string)) | ||||
| 	} | ||||
| 	// merge | ||||
| 	//log.Printf("old json: %s\n", decrypted) | ||||
| @@ -221,21 +222,21 @@ func (dbobj dbcon) updateUserRecordDo(jsonDataPatch []byte, userTOKEN string, ol | ||||
| 		actionCode := 1 | ||||
| 		newIdxFinalValue := "" | ||||
| 		if newIdxValue, ok3 := raw[idx]; ok3 { | ||||
| 			newIdxFinalValue = getIndexString(newIdxValue) | ||||
| 			newIdxFinalValue = utils.GetIndexString(newIdxValue) | ||||
| 			//log.Println("newIdxFinalValue0", newIdxFinalValue) | ||||
| 			if len(newIdxFinalValue) > 0 { | ||||
| 				if idx == "email" { | ||||
| 					newIdxFinalValue = normalizeEmail(newIdxFinalValue) | ||||
| 					newIdxFinalValue = utils.NormalizeEmail(newIdxFinalValue) | ||||
| 					newEmail = newIdxFinalValue | ||||
| 				} else if idx == "phone" { | ||||
| 					newIdxFinalValue = normalizePhone(newIdxFinalValue, conf.Sms.DefaultCountry) | ||||
| 					newIdxFinalValue = utils.NormalizePhone(newIdxFinalValue, conf.Sms.DefaultCountry) | ||||
| 				} | ||||
| 			} | ||||
| 			//log.Println("newIdxFinalValue", newIdxFinalValue) | ||||
| 		} | ||||
| 		if idxOldValue, ok := oldUserBson[idx+"idx"]; ok { | ||||
| 			if len(newIdxFinalValue) > 0 && len(idxOldValue.(string)) >= 0 { | ||||
| 				idxStringHashHex := hashString(dbobj.hash, newIdxFinalValue) | ||||
| 				idxStringHashHex := utils.HashString(dbobj.hash, newIdxFinalValue) | ||||
| 				if idxStringHashHex == idxOldValue.(string) { | ||||
| 					//log.Println("Index value NOT changed!") | ||||
| 					actionCode = 0 | ||||
| @@ -255,7 +256,7 @@ func (dbobj dbcon) updateUserRecordDo(jsonDataPatch []byte, userTOKEN string, ol | ||||
| 				return nil, nil, true, fmt.Errorf("duplicate %s index", idx) | ||||
| 			} | ||||
| 			//log.Printf("Adding index3? %s\n", raw[idx]) | ||||
| 			bdoc[idx+"idx"] = hashString(dbobj.hash, newIdxFinalValue) | ||||
| 			bdoc[idx+"idx"] = utils.HashString(dbobj.hash, newIdxFinalValue) | ||||
| 		} else if len(newIdxFinalValue) == 0 { | ||||
| 			bdel = append(bdel, idx+"idx") | ||||
| 		} | ||||
| @@ -301,9 +302,9 @@ func (dbobj dbcon) lookupUserRecord(userTOKEN string) (bson.M, error) { | ||||
|  | ||||
| func (dbobj dbcon) lookupUserRecordByIndex(indexName string, indexValue string, conf Config) (bson.M, error) { | ||||
| 	if indexName == "email" { | ||||
| 		indexValue = normalizeEmail(indexValue) | ||||
| 		indexValue = utils.NormalizeEmail(indexValue) | ||||
| 	} else if indexName == "phone" { | ||||
| 		indexValue = normalizePhone(indexValue, conf.Sms.DefaultCountry) | ||||
| 		indexValue = utils.NormalizePhone(indexValue, conf.Sms.DefaultCountry) | ||||
| 	} | ||||
| 	if len(indexValue) == 0 { | ||||
| 		return nil, nil | ||||
| @@ -311,7 +312,7 @@ func (dbobj dbcon) lookupUserRecordByIndex(indexName string, indexValue string, | ||||
| 	if indexName == "exptoken" { | ||||
| 		return dbobj.store.GetRecord(storage.TblName.Users, "exptoken", indexValue) | ||||
| 	} | ||||
| 	idxStringHashHex := hashString(dbobj.hash, indexValue) | ||||
| 	idxStringHashHex := utils.HashString(dbobj.hash, indexValue) | ||||
| 	//log.Printf("Loading by %s, value: %s\n", indexName, indexValue) | ||||
| 	return dbobj.store.GetRecord(storage.TblName.Users, indexName+"idx", idxStringHashHex) | ||||
| } | ||||
| @@ -416,7 +417,7 @@ func (dbobj dbcon) getUsers(offset int32, limit int32) ([]byte, int64, error) { | ||||
| 			} | ||||
| 			rec["private"] = raw2 | ||||
| 		} | ||||
| 		expstatus := getStringValue(element["expstatus"]) | ||||
| 		expstatus := utils.GetStringValue(element["expstatus"]) | ||||
| 		if len(expstatus) > 0 { | ||||
| 			rec["endtime"] = element["endtime"] | ||||
| 			rec["expstatus"] = expstatus | ||||
|   | ||||
| @@ -10,6 +10,7 @@ import ( | ||||
| 	"testing" | ||||
|  | ||||
| 	uuid "github.com/hashicorp/go-uuid" | ||||
| 	"github.com/securitybunker/databunker/src/utils" | ||||
| ) | ||||
|  | ||||
| func TestUtilUUID(t *testing.T) { | ||||
| @@ -18,7 +19,7 @@ func TestUtilUUID(t *testing.T) { | ||||
| 		t.Logf("Checking[%d]: %s\n", id, recordUUID) | ||||
| 		if err != nil { | ||||
| 			t.Fatalf("Failed to generate UUID %s: %s ", recordUUID, err) | ||||
| 		} else if isValidUUID(recordUUID) == false { | ||||
| 		} else if utils.CheckValidUUID(recordUUID) == false { | ||||
| 			t.Fatalf("Failed to validate UUID: %s ", recordUUID) | ||||
| 		} | ||||
| 	} | ||||
| @@ -27,13 +28,13 @@ func TestUtilUUID(t *testing.T) { | ||||
| func TestUtilAppNames(t *testing.T) { | ||||
| 	goodApps := []string{"penn", "teller", "a123", "good_app"} | ||||
| 	for _, value := range goodApps { | ||||
| 		if isValidApp(value) == false { | ||||
| 		if utils.CheckValidApp(value) == false { | ||||
| 			t.Fatalf("Failed to validate good app name: %s ", value) | ||||
| 		} | ||||
| 	} | ||||
| 	badApps := []string{"P1", "4as", "_a", "a.a", "a a", "a!b"} | ||||
| 	for _, value := range badApps { | ||||
| 		if isValidApp(value) == true { | ||||
| 		if utils.CheckValidApp(value) == true { | ||||
| 			t.Fatalf("Failed to validate bad app name: %s ", value) | ||||
| 		} | ||||
| 	} | ||||
| @@ -51,7 +52,7 @@ func TestUtilStringPatternMatch(t *testing.T) { | ||||
| 		{"pattern": "*test", "name": "123test", "result": true}, | ||||
| 	} | ||||
| 	for _, value := range goodJsons { | ||||
| 		if stringPatternMatch(value["pattern"].(string), value["name"].(string)) != value["result"].(bool) { | ||||
| 		if utils.StringPatternMatch(value["pattern"].(string), value["name"].(string)) != value["result"].(bool) { | ||||
| 			t.Fatalf("Failed in %s match %s\n", value["pattern"].(string), value["name"].(string)) | ||||
| 		} | ||||
| 	} | ||||
| @@ -67,11 +68,11 @@ func TestUtilGetJSONPost(t *testing.T) { | ||||
| 	for _, value := range goodJsons { | ||||
| 		request := httptest.NewRequest("POST", "/user", strings.NewReader(value)) | ||||
| 		request.Header.Set("Content-Type", "application/json") | ||||
| 		result, err := getUserJSON(request, "IL") | ||||
| 		result, err := utils.GetUserJSONStruct(request, "IL") | ||||
| 		if err != nil { | ||||
| 			t.Fatalf("Failed to parse json: %s, err: %s\n", value, err) | ||||
| 		} | ||||
| 		if len(result.loginIdx) == 0 { | ||||
| 		if len(result.LoginIdx) == 0 { | ||||
| 			t.Fatalf("Failed to parse login index from json: %s ", value) | ||||
| 		} | ||||
| 	} | ||||
| @@ -83,11 +84,11 @@ func TestUtilGetJSONPost(t *testing.T) { | ||||
| 	for _, value := range badJsons { | ||||
| 		request := httptest.NewRequest("POST", "/user", strings.NewReader(value)) | ||||
| 		request.Header.Set("Content-Type", "application/json") | ||||
| 		result, err := getUserJSON(request, "IL") | ||||
| 		result, err := utils.GetUserJSONStruct(request, "IL") | ||||
| 		if err != nil { | ||||
| 			t.Fatalf("Failed to parse json: %s, err: %s\n", value, err) | ||||
| 		} | ||||
| 		if len(result.loginIdx) != 0 { | ||||
| 		if len(result.LoginIdx) != 0 { | ||||
| 			t.Fatalf("Failed to parse login index from json: %s ", value) | ||||
| 		} | ||||
| 	} | ||||
|   | ||||
| @@ -6,6 +6,7 @@ import ( | ||||
|  | ||||
| 	uuid "github.com/hashicorp/go-uuid" | ||||
| 	"github.com/securitybunker/databunker/src/storage" | ||||
| 	"github.com/securitybunker/databunker/src/utils" | ||||
| 	"go.mongodb.org/mongo-driver/bson" | ||||
| ) | ||||
|  | ||||
| @@ -28,7 +29,7 @@ func (dbobj dbcon) createRootXtoken(customRootXtoken string) (string, error) { | ||||
| 		return "already-initialized", nil | ||||
| 	} | ||||
| 	if len(customRootXtoken) > 0 { | ||||
| 		if customRootXtoken != "DEMO" && !isValidUUID(customRootXtoken) { | ||||
| 		if customRootXtoken != "DEMO" && !utils.CheckValidUUID(customRootXtoken) { | ||||
| 			return "", errors.New("bad root token format") | ||||
| 		} | ||||
| 		rootToken = customRootXtoken | ||||
| @@ -39,7 +40,7 @@ func (dbobj dbcon) createRootXtoken(customRootXtoken string) (string, error) { | ||||
| 		} | ||||
| 	} | ||||
| 	bdoc := bson.M{} | ||||
| 	bdoc["xtoken"] = hashString(dbobj.hash, rootToken) | ||||
| 	bdoc["xtoken"] = utils.HashString(dbobj.hash, rootToken) | ||||
| 	bdoc["type"] = "root" | ||||
| 	bdoc["token"] = "" | ||||
| 	_, err = dbobj.store.CreateRecord(storage.TblName.Xtokens, &bdoc) | ||||
| @@ -60,7 +61,7 @@ func (dbobj dbcon) generateUserLoginXtoken(userTOKEN string) (string, string, er | ||||
| 	if err != nil { | ||||
| 		return "", "", err | ||||
| 	} | ||||
| 	hashedToken := hashString(dbobj.hash, tokenUUID) | ||||
| 	hashedToken := utils.HashString(dbobj.hash, tokenUUID) | ||||
| 	// by default login token for 30 minutes only | ||||
| 	expired := int32(time.Now().Unix()) + 10*60 | ||||
| 	bdoc := bson.M{} | ||||
| @@ -74,10 +75,10 @@ func (dbobj dbcon) generateUserLoginXtoken(userTOKEN string) (string, string, er | ||||
|  | ||||
| func (dbobj dbcon) checkUserAuthXToken(xtokenUUID string) (tokenAuthResult, error) { | ||||
| 	result := tokenAuthResult{} | ||||
| 	if xtokenUUID != "DEMO" && isValidUUID(xtokenUUID) == false { | ||||
| 	if xtokenUUID != "DEMO" && utils.CheckValidUUID(xtokenUUID) == false { | ||||
| 		return result, errors.New("failed to authenticate") | ||||
| 	} | ||||
| 	xtokenHashed := hashString(dbobj.hash, xtokenUUID) | ||||
| 	xtokenHashed := utils.HashString(dbobj.hash, xtokenUUID) | ||||
| 	if len(rootXTOKEN) > 0 && rootXTOKEN == xtokenHashed { | ||||
| 		//log.Println("It is a root token") | ||||
| 		result.ttype = "root" | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 yuli
					yuli