Skip to content
Snippets Groups Projects
Select Git revision
  • d14e15cc870310f1fcd461bbd2f7eb2eaa934cbf
  • main default protected
  • v1.298.0
  • v1.297.0
  • v1.296.0
  • v1.295.0
  • v1.294.0
  • v1.293.0
  • v1.292.0
  • v1.291.0
  • v1.290.0
  • v1.289.0
  • v1.288.0
  • v1.287.0
  • v1.286.0
  • v1.285.0
  • v1.284.0
  • v1.283.0
  • v1.282.0
  • v1.281.0
  • v1.280.0
  • v1.279.0
22 results

audit.go

Blame
  • audit.go 3.34 KiB
    package audit
    
    import (
    	"reflect"
    	"regexp"
    	"strings"
    
    	"github.com/r3labs/diff/v2"
    	"gitlab.com/uafrica/go-utils/reflection"
    	"gitlab.com/uafrica/go-utils/string_utils"
    )
    
    type FieldChange struct {
    	From interface{} `json:"change_from"`
    	To   interface{} `json:"change_to"`
    }
    
    func GetChanges(original interface{}, new interface{}) (map[string]interface{}, error) {
    	changes := map[string]interface{}{}
    	changelog, err := diff.Diff(original, new)
    	if err != nil {
    		return changes, err
    	}
    
    	for _, change := range changelog {
    
    		if len(change.Path) == 1 {
    			// Root object change
    			field := ToSnakeCase(change.Path[0])
    			changes[field] = FieldChange{
    				From: change.From,
    				To:   change.To,
    			}
    		} else if len(change.Path) == 2 {
    			// Child object changed
    			// ["Account", "ID"]
    			// 0 = Object
    			// 1 = field
    
    			objectKey := ToSnakeCase(change.Path[0])
    			field := ToSnakeCase(change.Path[1])
    
    			existingObject, present := changes[objectKey]
    			if present {
    				if object, ok := existingObject.(map[string]interface{}); ok {
    					object[field] = FieldChange{
    						From: change.From,
    						To:   change.To,
    					}
    					changes[objectKey] = object
    				}
    			} else {
    				fieldChange := map[string]interface{}{
    					field: FieldChange{
    						From: change.From,
    						To:   change.To,
    					},
    				}
    				changes[objectKey] = fieldChange
    			}
    
    		} else if len(change.Path) == 3 {
    			// Array of objects
    			// ["Parcel", "0", "ActualWeight"]
    			// 0 = Object
    			// 1 = Index of object
    			// 2 = field
    
    			objectKey := ToSnakeCase(change.Path[0])
    			indexString := change.Path[1]
    			index, _ := string_utils.StringToInt64(indexString)
    			field := ToSnakeCase(change.Path[2])
    
    			arrayObject, present := changes[objectKey]
    			if present {
    				if arrayOfObjects, ok := arrayObject.([]map[string]interface{}); ok {
    					if len(arrayOfObjects) > int(index) {
    						// Add field to existing object in array
    						object := arrayOfObjects[index]
    						object[field] = FieldChange{
    							From: change.From,
    							To:   change.To,
    						}
    					} else {
    						// new object, append to existing array
    						fieldChange := map[string]interface{}{
    							field: FieldChange{
    								From: change.From,
    								To:   change.To,
    							},
    						}
    						changes[objectKey] = append(arrayOfObjects, fieldChange)
    					}
    
    				}
    			} else {
    				// Create array of objects
    				fieldChange := map[string]interface{}{
    					field: FieldChange{
    						From: change.From,
    						To:   change.To,
    					},
    				}
    				changes[objectKey] = []map[string]interface{}{
    					fieldChange,
    				}
    			}
    		}
    	}
    
    	return changes, nil
    }
    
    var matchFirstCap = regexp.MustCompile("(.)([A-Z][a-z]+)")
    var matchAllCap = regexp.MustCompile("([a-z0-9])([A-Z])")
    
    func ToSnakeCase(str string) string {
    	snake := matchFirstCap.ReplaceAllString(str, "${1}_${2}")
    	snake = matchAllCap.ReplaceAllString(snake, "${1}_${2}")
    	return strings.ToLower(snake)
    }
    
    func GetIntValue(object interface{}, key string) int64 {
    	structValue := reflect.ValueOf(object)
    	if structValue.Kind() == reflect.Struct {
    		field := structValue.FieldByName(key)
    		id := reflection.GetInt64Value(field)
    		return id
    	}
    	return 0
    }
    
    func GetStringValue(object interface{}, key string) string {
    	structValue := reflect.ValueOf(object)
    	if structValue.Kind() == reflect.Struct {
    		field := structValue.FieldByName(key)
    		id := reflection.GetStringValue(field)
    		return id
    	}
    	return ""
    }