diff --git a/audit/audit.go b/audit/audit.go index 319083bc474ce03368a657dbab906a3ea7c8666d..44d786ed2aa5a9b9874403a863044e2f8d32872a 100644 --- a/audit/audit.go +++ b/audit/audit.go @@ -4,6 +4,7 @@ import ( "encoding/json" "fmt" "gitlab.bob.co.za/bob-public-utils/bobgroup-go-utils/errors" + "gitlab.bob.co.za/bob-public-utils/bobgroup-go-utils/logs" "gitlab.bob.co.za/bob-public-utils/bobgroup-go-utils/number_utils" "reflect" "regexp" @@ -39,6 +40,10 @@ func VerifyAuditEvents(original interface{}, new interface{}) error { } func GetChanges(original interface{}, new interface{}) (map[string]interface{}, error) { + // Clean audit events + original = cleanStruct(original) + new = cleanStruct(new) + changes := map[string]interface{}{} changelog, err := diff.Diff(original, new) if err != nil { @@ -128,6 +133,70 @@ func GetChanges(original interface{}, new interface{}) (map[string]interface{}, return changes, nil } + +func cleanStruct(object interface{}) interface{} { + defer func() { + if err := recover(); err != nil { + logs.ErrorMsg(fmt.Sprintf("audit event panic: %+v", err)) + } + }() + + // If the object is empty, we have nothing to do + if object == nil { + return object + } + + // Convert the object to a pointer + if reflect.ValueOf(object).Kind() != reflect.Ptr { + val := reflect.ValueOf(object) + // Create a new pointer to a new value of the type of the object + ptr := reflect.New(reflect.TypeOf(object)) + // Set the newly created pointer to point to the object + ptr.Elem().Set(val) + // Overwrite the original object + object = ptr.Interface() + } + + // Get the value of the object + val := reflect.ValueOf(object) + if val.Kind() == reflect.Ptr { + val = val.Elem() + } + + // We can only clean structs + if val.Kind() != reflect.Struct { + return object + } + + // Loop through the field tags to see if we should include the related object or not. + // We default to exclude, unless specified to include + for i := 0; i < val.NumField(); i++ { + fieldVal := val.Field(i) + structField := val.Type().Field(i) + + // Determine whether the field should be included or excluded + value, _ := structField.Tag.Lookup("audit") + shouldIncludeForAudit := value == "true" + shouldExcludeForAudit := value == "false" + + // If the audit tag is present and specified to 'true', we should always include the relation + if shouldIncludeForAudit { + continue + } + + // By default, all bun relations are excluded + isBunRelationField := strings.Contains(structField.Tag.Get("bun"), "rel:") + if shouldExcludeForAudit || isBunRelationField { + if fieldVal.CanSet() { + // Set the field to its zero value (nil for pointers) + fieldVal.Set(reflect.Zero(fieldVal.Type())) + } + } + } + + return object +} + func ChildObjectChanges(changes map[string]interface{}, objectPath string, fieldPath string, changeFrom interface{}, changeTo interface{}) { objectKey := ToSnakeCase(objectPath) diff --git a/date_utils/date_utils.go b/date_utils/date_utils.go index b0314232c3667a9d29e3f055dfc16f1ca95a4f89..ccca80d5014f376762ba0d395f13640e78e59b97 100644 --- a/date_utils/date_utils.go +++ b/date_utils/date_utils.go @@ -46,7 +46,7 @@ func DateLayoutYearMonthDayTime() string { } func DateLayoutFilenameSafe() string { - layout := "2006-01-02(15h04s05)" + layout := "02-Jan-2006-15h04" return layout } diff --git a/responses/responses.go b/responses/responses.go index cf94854b68e1b0e2484d07ee9edb06c3932210bf..41cbed323713709c4e9a5cb0b692f2637fceb5c2 100644 --- a/responses/responses.go +++ b/responses/responses.go @@ -2,9 +2,10 @@ package responses import ( "encoding/json" - "gitlab.bob.co.za/bob-public-utils/bobgroup-go-utils/map_utils" "net/http" + "gitlab.bob.co.za/bob-public-utils/bobgroup-go-utils/map_utils" + "gitlab.bob.co.za/bob-public-utils/bobgroup-go-utils/logs" "gitlab.bob.co.za/bob-public-utils/bobgroup-go-utils/utils" @@ -116,3 +117,10 @@ func OptionsResponse() events.APIGatewayProxyResponse { Headers: map_utils.MergeMaps(utils.CorsHeaders(), ContentTypeJSONHeader), } } + +func MovedPermanentlyResponse(url string) events.APIGatewayProxyResponse { + return events.APIGatewayProxyResponse{ + StatusCode: http.StatusMovedPermanently, + Headers: map_utils.MergeMaps(utils.CorsHeaders(), map[string]string{"Location": url}), + } +} diff --git a/utils/utils.go b/utils/utils.go index 1252424f69a2f7f7a628b34566e4759ca0452ff4..9bfa17700ffa38f994c85255b721b691b8dde10e 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -67,6 +67,32 @@ func ValidateEmailAddress(email string) (string, error) { return cleanEmail, nil } +func StripEmail(email string) (strippedEmail string, strippedDomain string) { + // Strip the email address from the + to the @ + // Define a regular expression pattern to match the "+" to "@" part + emailPattern := `(\+.*@)` + // Define the regular expression pattern to match the domain part after "@" + domainPattern := `@(.+)` + + // Compile the regular expression + emailRegex := regexp.MustCompile(emailPattern) + domainRegex := regexp.MustCompile(domainPattern) + + // Replace the matched part with an empty string + strippedEmail = emailRegex.ReplaceAllString(email, "@") + + // Find the first match in the email address + match := domainRegex.FindStringSubmatch(email) + + // Check if a match was found + if len(match) > 1 { + // The domain part (excluding "@") is in the first capture group (index 1) + strippedDomain = match[1] + } + + return strippedEmail, strippedDomain +} + // IsUrlStrict Returns whether a URL is valid in a strict way (Must have scheme and host) func IsUrlStrict(str string) bool { u, err := url.Parse(str)