Add Audit cababilities. First try on deleteOne
This commit is contained in:
22
audit.go
Normal file
22
audit.go
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
package mongo
|
||||||
|
|
||||||
|
type Op string
|
||||||
|
|
||||||
|
const (
|
||||||
|
OpUpdate Op = "update"
|
||||||
|
OpDelete Op = "delete"
|
||||||
|
OpInsert Op = "insert"
|
||||||
|
OpArchive Op = "archive"
|
||||||
|
OpRestore Op = "restore"
|
||||||
|
)
|
||||||
|
|
||||||
|
type AuditResult struct {
|
||||||
|
Op Op `bson:"op" json:"op"`
|
||||||
|
Entity string `bson:"entity" json:"entity"`
|
||||||
|
Data any `bson:"data" json:"data"`
|
||||||
|
Before any `bson:"before" json:"before"`
|
||||||
|
After any `bson:"after" json:"after"`
|
||||||
|
Context any `bson:"context" json:"context"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type OnAudit func(audit *AuditResult) error
|
||||||
54
delete.go
Normal file
54
delete.go
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
package mongo
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"slices"
|
||||||
|
|
||||||
|
"go.mongodb.org/mongo-driver/v2/bson"
|
||||||
|
|
||||||
|
"git.gsuntres.com/general/mongo/options"
|
||||||
|
"git.gsuntres.com/general/commons"
|
||||||
|
)
|
||||||
|
|
||||||
|
// DeleteOne will delete the first document that matches the filter.
|
||||||
|
func (c *MongoClient) DeleteOne(ctx context.Context, database, name string, filter bson.M, opts ...options.Lister[options.DeleteOneOptions]) error {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
// 1. Prepare query.
|
||||||
|
collection := c.GetCollection(database, name)
|
||||||
|
|
||||||
|
// 2. Check discriminator and mongofy
|
||||||
|
if err := c.DiscriminatorCheckAndApplyToFilter(ctx, name, filter); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
f := Mongofy(&Query{ Filter: filter })
|
||||||
|
|
||||||
|
var found bson.M
|
||||||
|
if c.WithAudit {
|
||||||
|
err = collection.FindOne(ctx, f).Decode(&found)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. Delete
|
||||||
|
_, err = collection.DeleteOne(ctx, f)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.WithAudit && !slices.Contains(c.IgnoreAudit, name) {
|
||||||
|
contx := commons.ContextSerialize(ctx, c.ContextFields)
|
||||||
|
audit := &AuditResult {
|
||||||
|
Entity: name,
|
||||||
|
Op: OpDelete,
|
||||||
|
Before: found,
|
||||||
|
Context: contx,
|
||||||
|
}
|
||||||
|
|
||||||
|
(*c.OnAudit)(audit)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
package mongo
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"go.mongodb.org/mongo-driver/v2/bson"
|
|
||||||
)
|
|
||||||
|
|
||||||
// DeleteOne will delete the first document that matches the filter.
|
|
||||||
func (c *MongoClient) DeleteOne(ctx context.Context, database, name string, filter bson.M) error {
|
|
||||||
|
|
||||||
// 1. Prepare query.
|
|
||||||
collection := c.GetCollection(database, name)
|
|
||||||
|
|
||||||
// 2. Query
|
|
||||||
_, err := collection.DeleteOne(ctx, filter)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
234
delete_test.go
Normal file
234
delete_test.go
Normal file
@@ -0,0 +1,234 @@
|
|||||||
|
package mongo
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"fmt"
|
||||||
|
"context"
|
||||||
|
"testing"
|
||||||
|
"encoding/json"
|
||||||
|
|
||||||
|
"go.mongodb.org/mongo-driver/v2/bson"
|
||||||
|
|
||||||
|
"git.gsuntres.com/general/commons"
|
||||||
|
"git.gsuntres.com/general/events"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestDeleteOne(t *testing.T) {
|
||||||
|
client := GetMongoClient()
|
||||||
|
|
||||||
|
data := map[string]any {
|
||||||
|
"_id": "su_123458",
|
||||||
|
"name": "MyNameTODelete",
|
||||||
|
"age": int32(25),
|
||||||
|
}
|
||||||
|
|
||||||
|
o, err := client.InsertOne(context.Background(), "mydb", "mycollection", data)
|
||||||
|
if err != nil { t.Fatalf("Failed to insertOne %#v", err) }
|
||||||
|
|
||||||
|
// now delete it
|
||||||
|
err = client.DeleteOne(context.Background(), "mydb", "mycollection", bson.M{"_id": o["_id"].(string)})
|
||||||
|
if err != nil { t.Fatalf("Failed to deleteOne %#v", err) }
|
||||||
|
|
||||||
|
// raw query
|
||||||
|
var results bson.M
|
||||||
|
filter := bson.M{ "name": "MyName" }
|
||||||
|
|
||||||
|
c := client.Client.Database("mydb").Collection("mycollection")
|
||||||
|
c.FindOne(context.Background(), filter).Decode(&results)
|
||||||
|
|
||||||
|
if results != nil {
|
||||||
|
t.Fatalf("Should have no results not %v", results)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDelete_Discriminator(t *testing.T) {
|
||||||
|
// 1. Register schemas
|
||||||
|
schemaStore, err := os.ReadFile("./.test/store.json")
|
||||||
|
if err != nil { t.Fatal(err) }
|
||||||
|
|
||||||
|
schemaOffer, err := os.ReadFile("./.test/offer.json")
|
||||||
|
if err != nil { t.Fatal(err) }
|
||||||
|
|
||||||
|
var store bson.M
|
||||||
|
if err := json.Unmarshal(schemaStore, &store); err != nil {
|
||||||
|
t.Fatalf("Length: %d, First bytes: %x\n", len(schemaStore), schemaStore[:4])
|
||||||
|
}
|
||||||
|
|
||||||
|
var offer bson.M
|
||||||
|
if err := json.Unmarshal(schemaOffer, &offer); err != nil {
|
||||||
|
t.Fatalf("Length: %d, First bytes: %x\n", len(schemaOffer), schemaOffer[:4])
|
||||||
|
}
|
||||||
|
|
||||||
|
client := GetMongoClient()
|
||||||
|
client.AddDefinition(store)
|
||||||
|
client.AddDefinition(offer)
|
||||||
|
|
||||||
|
// Store str_1234 has BOOMRAW 1.
|
||||||
|
ctx1 := context.Background()
|
||||||
|
ctx1 = context.WithValue(ctx1, "store", "str_1234")
|
||||||
|
offer1 := map[string]any { "name": "BOOMRAW 1" }
|
||||||
|
_, err = client.InsertOne(ctx1, "mydb", "offer", offer1)
|
||||||
|
if err != nil { t.Fatalf("Failed to insertOne %#v", err) }
|
||||||
|
|
||||||
|
// Store str_4321 has BOOMRAW 2
|
||||||
|
ctx2 := context.Background()
|
||||||
|
ctx2 = context.WithValue(ctx2, "store", "str_4321")
|
||||||
|
offer2 := map[string]any { "name": "BOOMRAW 2" }
|
||||||
|
_, err = client.InsertOne(ctx2, "mydb", "offer", offer2)
|
||||||
|
if err != nil { t.Fatalf("Failed to insertOne %#v", err) }
|
||||||
|
|
||||||
|
// Attempt to delete BOOMRAW2 in str_1234
|
||||||
|
err = client.DeleteOne(ctx1, "mydb", "offer", bson.M{"name": "BOOMRAW2"})
|
||||||
|
|
||||||
|
// Within store str_4321 searching for BOOMRAW should return one result
|
||||||
|
filter := bson.M{"name": bson.M{"$regex": "BOOMRAW*"}}
|
||||||
|
findResult, err := client.Find(ctx2, "mydb", "offer", filter, &FindOptions{ Offset: int64(0) })
|
||||||
|
if err != nil { t.Fatalf("Failed to find %#v", err) }
|
||||||
|
|
||||||
|
dataAny, hasData := findResult["data"]
|
||||||
|
if !hasData { t.Fatal("no data") }
|
||||||
|
|
||||||
|
data := dataAny.(bson.A)
|
||||||
|
|
||||||
|
if len(data) != 1 {
|
||||||
|
t.Fatalf("Expected to return 1 document but got %d", len(data))
|
||||||
|
}
|
||||||
|
|
||||||
|
arr, _ := commons.BsonAToSlice(data)
|
||||||
|
|
||||||
|
o := arr[0]
|
||||||
|
|
||||||
|
name := o["name"]
|
||||||
|
|
||||||
|
if name != "BOOMRAW 2" {
|
||||||
|
t.Fatalf("Expected BOOMRAW 2 not %s", name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDeleteOne_WithAudit(t *testing.T) {
|
||||||
|
client := GetMongoClient()
|
||||||
|
|
||||||
|
data := map[string]any {
|
||||||
|
"_id": "su_123458",
|
||||||
|
"name": "MyNameTODelete",
|
||||||
|
"age": int32(25),
|
||||||
|
}
|
||||||
|
|
||||||
|
o, err := client.InsertOne(context.Background(), "mydb", "mycollection", data)
|
||||||
|
if err != nil { t.Fatalf("Failed to insertOne %#v", err) }
|
||||||
|
|
||||||
|
// now delete it
|
||||||
|
|
||||||
|
var (
|
||||||
|
onAudit_calls int
|
||||||
|
onAudit_before any
|
||||||
|
onAudit_context any
|
||||||
|
)
|
||||||
|
|
||||||
|
events.Subscribe(func(audit *AuditResult) error {
|
||||||
|
onAudit_calls++
|
||||||
|
onAudit_before = audit.Before
|
||||||
|
onAudit_context = audit.Context
|
||||||
|
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
ctx := context.Background()
|
||||||
|
ctx = context.WithValue(ctx, "account", "xxxxxx")
|
||||||
|
ctx = context.WithValue(ctx, "store", "str_4321")
|
||||||
|
err = client.DeleteOne(ctx, "mydb", "mycollection", bson.M{"_id": o["_id"].(string)})
|
||||||
|
if err != nil { t.Fatalf("Failed to deleteOne %#v", err) }
|
||||||
|
|
||||||
|
// raw query
|
||||||
|
var results bson.M
|
||||||
|
filter := bson.M{ "name": "MyName" }
|
||||||
|
|
||||||
|
c := client.Client.Database("mydb").Collection("mycollection")
|
||||||
|
c.FindOne(context.Background(), filter).Decode(&results)
|
||||||
|
|
||||||
|
if results != nil {
|
||||||
|
t.Fatalf("Should have no results not %v", results)
|
||||||
|
}
|
||||||
|
|
||||||
|
if onAudit_calls != 1 {
|
||||||
|
t.Fatalf("ondelete should have been called once, not %d", onAudit_calls)
|
||||||
|
}
|
||||||
|
|
||||||
|
if onAudit_before != nil {
|
||||||
|
tp := fmt.Sprintf("%T", onAudit_before)
|
||||||
|
if tp != "bson.M" {
|
||||||
|
t.Fatalf("before has the wrong type %s", tp)
|
||||||
|
}
|
||||||
|
|
||||||
|
before := onAudit_before.(bson.M)
|
||||||
|
|
||||||
|
AssertSubset(t, before, o, "Should have been equal")
|
||||||
|
}
|
||||||
|
|
||||||
|
if onAudit_context != nil {
|
||||||
|
ctx := onAudit_context.(map[string]any)
|
||||||
|
AssertSubset(t, ctx, map[string]any{"account": "xxxxxx", "store": "str_4321"}, "Should have been equal")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDeleteOne_WithAuditButIgnored(t *testing.T) {
|
||||||
|
client := GetMongoClient()
|
||||||
|
client.IgnoredAudit = []string{"mycollection"}
|
||||||
|
|
||||||
|
data := map[string]any {
|
||||||
|
"_id": "su_123458",
|
||||||
|
"name": "MyNameTODelete",
|
||||||
|
"age": int32(25),
|
||||||
|
}
|
||||||
|
|
||||||
|
o, err := client.InsertOne(context.Background(), "mydb", "mycollection", data)
|
||||||
|
if err != nil { t.Fatalf("Failed to insertOne %#v", err) }
|
||||||
|
|
||||||
|
// now delete it
|
||||||
|
|
||||||
|
var (
|
||||||
|
onAudit_calls int
|
||||||
|
onAudit_before any
|
||||||
|
onAudit_context any
|
||||||
|
)
|
||||||
|
|
||||||
|
events.Subscribe(func(audit *AuditResult) error {
|
||||||
|
onAudit_calls++
|
||||||
|
onAudit_before = audit.Before
|
||||||
|
onAudit_context = audit.Context
|
||||||
|
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
ctx := context.Background()
|
||||||
|
ctx = context.WithValue(ctx, "account", "xxxxxx")
|
||||||
|
ctx = context.WithValue(ctx, "store", "str_4321")
|
||||||
|
err = client.DeleteOne(ctx, "mydb", "mycollection", bson.M{"_id": o["_id"].(string)})
|
||||||
|
if err != nil { t.Fatalf("Failed to deleteOne %#v", err) }
|
||||||
|
|
||||||
|
// raw query
|
||||||
|
var results bson.M
|
||||||
|
filter := bson.M{ "name": "MyName" }
|
||||||
|
|
||||||
|
c := client.Client.Database("mydb").Collection("mycollection")
|
||||||
|
c.FindOne(context.Background(), filter).Decode(&results)
|
||||||
|
|
||||||
|
if results != nil {
|
||||||
|
t.Fatalf("Should have no results not %v", results)
|
||||||
|
}
|
||||||
|
|
||||||
|
if onAudit_calls != 1 {
|
||||||
|
t.Fatalf("ondelete should have been called once, not %d", onAudit_calls)
|
||||||
|
}
|
||||||
|
|
||||||
|
if onAudit_before != nil {
|
||||||
|
tp := fmt.Sprintf("%T", onAudit_before)
|
||||||
|
if tp != "bson.M" {
|
||||||
|
t.Fatalf("before has the wrong type %s", tp)
|
||||||
|
}
|
||||||
|
|
||||||
|
before := onAudit_before.(bson.M)
|
||||||
|
|
||||||
|
AssertSubset(t, before, o, "Should have been equal")
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -21,8 +21,6 @@ func makeFilter(name string, value any) *Filter {
|
|||||||
|
|
||||||
var v string
|
var v string
|
||||||
|
|
||||||
log.Printf("TYPE %T", value)
|
|
||||||
|
|
||||||
switch value.(type) {
|
switch value.(type) {
|
||||||
case string:
|
case string:
|
||||||
op = "eq"
|
op = "eq"
|
||||||
@@ -30,7 +28,6 @@ func makeFilter(name string, value any) *Filter {
|
|||||||
case bson.M:
|
case bson.M:
|
||||||
vMap := value.(bson.M)
|
vMap := value.(bson.M)
|
||||||
|
|
||||||
log.Printf("GEO its map[string]any %v", vMap)
|
|
||||||
for kk, vv := range vMap {
|
for kk, vv := range vMap {
|
||||||
op = kk
|
op = kk
|
||||||
v = vv.(string)
|
v = vv.(string)
|
||||||
@@ -41,7 +38,6 @@ func makeFilter(name string, value any) *Filter {
|
|||||||
case map[string]any:
|
case map[string]any:
|
||||||
vMap := value.(map[string]any)
|
vMap := value.(map[string]any)
|
||||||
|
|
||||||
log.Printf("GEO its bson.M %v", vMap)
|
|
||||||
for kk, vv := range vMap {
|
for kk, vv := range vMap {
|
||||||
op = kk
|
op = kk
|
||||||
v = vv.(string)
|
v = vv.(string)
|
||||||
@@ -59,8 +55,6 @@ func makeFilter(name string, value any) *Filter {
|
|||||||
Value: v,
|
Value: v,
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Printf("FILTER -> %#v", o)
|
|
||||||
|
|
||||||
return o
|
return o
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -69,7 +63,7 @@ func Mongofy(q *Query) map[string]any {
|
|||||||
conditions := make([]map[string]interface{}, 0)
|
conditions := make([]map[string]interface{}, 0)
|
||||||
|
|
||||||
logic := "and"
|
logic := "and"
|
||||||
log.Printf("GEO q.Filter %#v", q.Filter)
|
|
||||||
for k, v := range q.Filter {
|
for k, v := range q.Filter {
|
||||||
if k == "_logic" {
|
if k == "_logic" {
|
||||||
logic = v.(string)
|
logic = v.(string)
|
||||||
|
|||||||
3
go.mod
3
go.mod
@@ -3,7 +3,8 @@ module git.gsuntres.com/general/mongo
|
|||||||
go 1.25.0
|
go 1.25.0
|
||||||
|
|
||||||
require (
|
require (
|
||||||
git.gsuntres.com/general/commons v0.0.0-20260422140002-55de9c34e8c1
|
git.gsuntres.com/general/commons v0.0.0-20260423171748-0ce3f3b5eb8c
|
||||||
|
git.gsuntres.com/general/events v0.0.0-20260423140000-1435849fb2c0
|
||||||
git.gsuntres.com/general/sys v0.0.1
|
git.gsuntres.com/general/sys v0.0.1
|
||||||
github.com/go-viper/mapstructure/v2 v2.5.0
|
github.com/go-viper/mapstructure/v2 v2.5.0
|
||||||
github.com/google/go-cmp v0.7.0
|
github.com/google/go-cmp v0.7.0
|
||||||
|
|||||||
8
go.sum
8
go.sum
@@ -1,7 +1,11 @@
|
|||||||
dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8=
|
dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8=
|
||||||
dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA=
|
dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA=
|
||||||
git.gsuntres.com/general/commons v0.0.0-20260422140002-55de9c34e8c1 h1:g96tzABUPqaAaftDBLbDkf/za21kBAUiex8LU//NsFE=
|
git.gsuntres.com/general/commons v0.0.0-20260422214453-1e9e43668f5e h1:UFlnWT0u8ywStd7VRPNHmooZw3bSdXqhe/MwOpgWmvI=
|
||||||
git.gsuntres.com/general/commons v0.0.0-20260422140002-55de9c34e8c1/go.mod h1:s774W5vN/53DLYKeY4iwFnwPOIHfSg8/V6Ft7sEdl9M=
|
git.gsuntres.com/general/commons v0.0.0-20260422214453-1e9e43668f5e/go.mod h1:s774W5vN/53DLYKeY4iwFnwPOIHfSg8/V6Ft7sEdl9M=
|
||||||
|
git.gsuntres.com/general/commons v0.0.0-20260423171748-0ce3f3b5eb8c h1:YZJWYDqqUC0x687yYrcCYzMIvSO40H25IsInBCl+g6A=
|
||||||
|
git.gsuntres.com/general/commons v0.0.0-20260423171748-0ce3f3b5eb8c/go.mod h1:S93xcBczrgN+gZU0JWkPRnTcAMvQuTp1ChyKkOd/I50=
|
||||||
|
git.gsuntres.com/general/events v0.0.0-20260423140000-1435849fb2c0 h1:j4qqM1K6BMIG9ydzbuAljcAeaR/XbImEfs7GF6jtHlY=
|
||||||
|
git.gsuntres.com/general/events v0.0.0-20260423140000-1435849fb2c0/go.mod h1:IQEt0/YT7vYHLTmRhjpqdHgHhagIHZNaay83fndui7s=
|
||||||
git.gsuntres.com/general/sys v0.0.1 h1:JpGG6HCkJrTaCICR09kURhMTIc+/s8yb0lHQjo/TDVI=
|
git.gsuntres.com/general/sys v0.0.1 h1:JpGG6HCkJrTaCICR09kURhMTIc+/s8yb0lHQjo/TDVI=
|
||||||
git.gsuntres.com/general/sys v0.0.1/go.mod h1:OVs7w4/tJO1GT7cLIeEsb90LuZqH2xYIVQODI5P1GJs=
|
git.gsuntres.com/general/sys v0.0.1/go.mod h1:OVs7w4/tJO1GT7cLIeEsb90LuZqH2xYIVQODI5P1GJs=
|
||||||
github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 h1:He8afgbRMd7mFxO99hRNu+6tazq8nFF9lIwo9JFroBk=
|
github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 h1:He8afgbRMd7mFxO99hRNu+6tazq8nFF9lIwo9JFroBk=
|
||||||
|
|||||||
44
main.go
44
main.go
@@ -17,6 +17,7 @@ import (
|
|||||||
|
|
||||||
"git.gsuntres.com/general/commons"
|
"git.gsuntres.com/general/commons"
|
||||||
"git.gsuntres.com/general/sys"
|
"git.gsuntres.com/general/sys"
|
||||||
|
"git.gsuntres.com/general/events"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@@ -87,6 +88,14 @@ type MongoClient struct {
|
|||||||
Registry map[string]*CollectionDefinition
|
Registry map[string]*CollectionDefinition
|
||||||
// Relaxed if set to true will not enforce schema
|
// Relaxed if set to true will not enforce schema
|
||||||
Relaxed bool
|
Relaxed bool
|
||||||
|
// Context fields to serialize when needed
|
||||||
|
ContextFields []string
|
||||||
|
// WithAudit enable auditing functionality.
|
||||||
|
WithAudit bool
|
||||||
|
// OnAudit callback called when audit is enabled.
|
||||||
|
OnAudit *OnAudit
|
||||||
|
// IgnoreAudit a list of entities to ignore
|
||||||
|
IgnoreAudit []string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *MongoClient) SetRelaxed() {
|
func (c *MongoClient) SetRelaxed() {
|
||||||
@@ -250,6 +259,7 @@ var client *MongoClient = &MongoClient{
|
|||||||
Limit: 10,
|
Limit: 10,
|
||||||
Registry: make(map[string]*CollectionDefinition, 0),
|
Registry: make(map[string]*CollectionDefinition, 0),
|
||||||
Relaxed: false,
|
Relaxed: false,
|
||||||
|
IgnoreAudit: []string{"event"},
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetMongoClient() *MongoClient {
|
func GetMongoClient() *MongoClient {
|
||||||
@@ -280,6 +290,9 @@ type MongoStartProps struct {
|
|||||||
MongoPass string
|
MongoPass string
|
||||||
MongoDebugQuery bool
|
MongoDebugQuery bool
|
||||||
MongoDBPrefix string
|
MongoDBPrefix string
|
||||||
|
ContextFields []string
|
||||||
|
WithAudit bool
|
||||||
|
OnAudit *OnAudit
|
||||||
AllowTruncatingDoubles bool
|
AllowTruncatingDoubles bool
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -314,18 +327,30 @@ func Start(props *MongoStartProps) error {
|
|||||||
}).
|
}).
|
||||||
SetRegistry(GetCustomRegistry())
|
SetRegistry(GetCustomRegistry())
|
||||||
|
|
||||||
|
colors := []string{
|
||||||
|
commons.EscapeGreen,
|
||||||
|
commons.EscapeRed,
|
||||||
|
commons.EscapeYellow,
|
||||||
|
commons.EscapeBlue,
|
||||||
|
commons.EscapeMagenta,
|
||||||
|
commons.EscapeCyan,
|
||||||
|
}
|
||||||
|
|
||||||
client.DebugQuery = props.MongoDebugQuery
|
client.DebugQuery = props.MongoDebugQuery
|
||||||
if client.DebugQuery {
|
if client.DebugQuery {
|
||||||
// Debug queries
|
// Debug queries
|
||||||
monitor := &event.CommandMonitor{
|
monitor := &event.CommandMonitor{
|
||||||
Started: func(_ context.Context, e *event.CommandStartedEvent) {
|
Started: func(_ context.Context, e *event.CommandStartedEvent) {
|
||||||
log.Printf("%d@Start %s#%s %s", e.RequestID, e.DatabaseName, e.CommandName, e.Command)
|
ecode := colors[e.RequestID % 6]
|
||||||
|
log.Printf("%s%d@Start%s %s#%s %s", ecode, e.RequestID, commons.EscapeReset, e.DatabaseName, e.CommandName, e.Command)
|
||||||
},
|
},
|
||||||
Succeeded: func(_ context.Context, e *event.CommandSucceededEvent) {
|
Succeeded: func(_ context.Context, e *event.CommandSucceededEvent) {
|
||||||
log.Printf("%d@OK in %s", e.RequestID, e.Reply)
|
ecode := colors[e.RequestID % 6]
|
||||||
|
log.Printf("%s%d@OK%s in %s", ecode, e.RequestID, commons.EscapeReset, e.Reply)
|
||||||
},
|
},
|
||||||
Failed: func(_ context.Context, e *event.CommandFailedEvent) {
|
Failed: func(_ context.Context, e *event.CommandFailedEvent) {
|
||||||
log.Printf("%d@Fail in %s", e.RequestID, e.Failure)
|
ecode := colors[e.RequestID % 6]
|
||||||
|
log.Printf("%s%d@Fail%s in %s", ecode, e.RequestID, commons.EscapeReset, e.Failure)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -335,6 +360,19 @@ func Start(props *MongoStartProps) error {
|
|||||||
// set DBPrefix
|
// set DBPrefix
|
||||||
client.DBPrefix = props.MongoDBPrefix
|
client.DBPrefix = props.MongoDBPrefix
|
||||||
|
|
||||||
|
client.ContextFields = props.ContextFields
|
||||||
|
|
||||||
|
client.WithAudit = props.WithAudit
|
||||||
|
|
||||||
|
client.OnAudit = props.OnAudit
|
||||||
|
|
||||||
|
if client.WithAudit {
|
||||||
|
var onAudit OnAudit = func(audit *AuditResult) error {
|
||||||
|
return events.Publish(audit)
|
||||||
|
}
|
||||||
|
client.OnAudit = &onAudit
|
||||||
|
}
|
||||||
|
|
||||||
if err := cOptions.Validate(); err != nil {
|
if err := cOptions.Validate(); err != nil {
|
||||||
log.Fatalf("Failed to validate mongo options: %+v", err.Error())
|
log.Fatalf("Failed to validate mongo options: %+v", err.Error())
|
||||||
|
|
||||||
|
|||||||
@@ -53,7 +53,9 @@ func TestMain(m *testing.M) {
|
|||||||
MongoUri: endpoint,
|
MongoUri: endpoint,
|
||||||
MongoUser: user,
|
MongoUser: user,
|
||||||
MongoPass: pass,
|
MongoPass: pass,
|
||||||
|
ContextFields: []string{"account", "store"},
|
||||||
MongoDebugQuery: mongoDebug,
|
MongoDebugQuery: mongoDebug,
|
||||||
|
WithAudit: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
// 3. Run tests
|
// 3. Run tests
|
||||||
|
|||||||
35
options/deleteoneoptions.go
Normal file
35
options/deleteoneoptions.go
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
package options
|
||||||
|
|
||||||
|
type DeleteAudit struct {
|
||||||
|
Id string
|
||||||
|
Before any
|
||||||
|
Context any
|
||||||
|
}
|
||||||
|
|
||||||
|
type OnDeleteAudit func(audit *DeleteAudit)
|
||||||
|
|
||||||
|
type DeleteOneOptions struct {
|
||||||
|
OnDeleteAudit *OnDeleteAudit
|
||||||
|
}
|
||||||
|
|
||||||
|
type DeleteOneOptionsBuilder struct {
|
||||||
|
Opts []func(*DeleteOneOptions) error
|
||||||
|
}
|
||||||
|
|
||||||
|
func DeleteOne() *DeleteOneOptionsBuilder{
|
||||||
|
return &DeleteOneOptionsBuilder{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dao *DeleteOneOptionsBuilder) List() []func(*DeleteOneOptions) error {
|
||||||
|
return dao.Opts
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dao *DeleteOneOptionsBuilder) WithOnDeleteAudit(oa *OnDeleteAudit) *DeleteOneOptionsBuilder {
|
||||||
|
dao.Opts = append(dao.Opts, func(opts *DeleteOneOptions) error {
|
||||||
|
opts.OnDeleteAudit = oa
|
||||||
|
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
return dao
|
||||||
|
}
|
||||||
5
options/lister.go
Normal file
5
options/lister.go
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
package options
|
||||||
|
|
||||||
|
type Lister[T any] interface {
|
||||||
|
List() []func(*T) error
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user