Skip to content

Recommendations/Documention for implementing an Audit Hook #830

@cliedeman

Description

@cliedeman

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 omitted

And 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions