You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
68 lines
1.3 KiB
68 lines
1.3 KiB
package protection
|
|
|
|
import (
|
|
"reflect"
|
|
"time"
|
|
|
|
"github.com/modern-go/reflect2"
|
|
"go.mongodb.org/mongo-driver/bson/primitive"
|
|
)
|
|
|
|
// Key field stores unique document id and version
|
|
type Key struct {
|
|
X primitive.ObjectID `bson:"_x" json:"_x" index:",hashed"`
|
|
V int64 `bson:"_v" json:"_v"`
|
|
}
|
|
|
|
// Inject extends the doc with protection key values
|
|
func (k *Key) Inject(doc primitive.M) {
|
|
if reflect2.IsNil(doc) {
|
|
return
|
|
}
|
|
|
|
if k.X.IsZero() {
|
|
doc["_x"] = primitive.M{"$exists": false}
|
|
doc["_v"] = primitive.M{"$exists": false}
|
|
} else {
|
|
doc["_x"] = k.X
|
|
doc["_v"] = k.V
|
|
}
|
|
}
|
|
|
|
// Restate creates a new protection key
|
|
func (k *Key) Restate() {
|
|
k.X = primitive.NewObjectID()
|
|
k.V = time.Now().Unix()
|
|
}
|
|
|
|
// Get finds protection field in the source document otherwise returns nil
|
|
func Get(source interface{}) (key *Key) {
|
|
v := reflect.ValueOf(source)
|
|
if v.Kind() != reflect.Ptr || v.IsNil() {
|
|
return nil
|
|
}
|
|
|
|
el := v.Elem()
|
|
numField := el.NumField()
|
|
|
|
for i := 0; i < numField; i++ {
|
|
field := el.Field(i)
|
|
if !field.CanInterface() {
|
|
continue
|
|
}
|
|
|
|
switch field.Interface().(type) {
|
|
case *Key:
|
|
key = field.Interface().(*Key)
|
|
case Key:
|
|
ptr := field.Addr()
|
|
key = ptr.Interface().(*Key)
|
|
default:
|
|
continue
|
|
}
|
|
|
|
return key
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|