-
Notifications
You must be signed in to change notification settings - Fork 999
Recommendations/Documention for implementing an Audit Hook #830
Copy link
Copy link
Closed
Labels
Description
Hi there, looking for some guidance/ideas on how to implement a basic auditing hook in ent
Lets say I have the following Mixin
// AuditMixin struct
type AuditMixin struct{}
// Fields Default audit fields
func (AuditMixin) Fields() []ent.Field {
return []ent.Field{
field.Time("created_at").
Immutable().
Default(time.Now),
field.Int("created_by").Optional(),
field.Time("updated_at").
Default(time.Now).
UpdateDefault(time.Now),
field.Int("updated_by").Optional(),
}
}
... rest omittedAnd I Implement the following hook (first attempt)
const (
FieldCreatedBy = "created_by"
FieldCreatedAt = "created_at"
FieldUpdatedBy = "updated_by"
FieldUpdatedAt = "updated_at"
)
// AuditHook extracts the user from the context and populates the audit fields
func AuditHook(next ent.Mutator) ent.Mutator {
return ent.MutateFunc(func(ctx context.Context, m ent.Mutation) (ent.Value, error) {
// TODO: some way to find out if Auditing is applicable to this object
usr, err := internal.UserFromContext(ctx)
if err != nil {
return nil, err
}
if m.Op() == ent.OpCreate {
err := m.SetField(FieldCreatedAt, time.Now())
if err != nil {
return nil, err
}
_, set := m.Field(FieldCreatedBy)
if !set {
err = m.SetField(FieldCreatedBy, usr.ID)
if err != nil {
return nil, err
}
}
}
if m.Op() == ent.OpUpdate || m.Op() == ent.OpUpdateOne {
_, set := m.Field("updated_by")
if !set {
err = m.SetField("updated_by", usr.ID)
if err != nil {
return nil, err
}
err = m.SetField("updated_at", time.Now())
if err != nil {
return nil, err
}
}
}
return next.Mutate(ctx, m)
})
}The first issue I have encountered is that there is no easy way (that I could find) to identify which mixins apply to an object. Having access to the annotations could also work if we wanted to mark special processing for an update in that way.
Reactions are currently unavailable