mirror of
https://github.com/hanzoai/team.git
synced 2026-09-30 01:57:35 +00:00
The server module named github.com/hanzoai/team/server/v8 — a path that resolves to the retired workspace's repository, not this one — while server/public still published github.com/mattermost/mattermost/server/public. Both are github.com/hanzoteam/server/... now, which is where this code actually lives. That second half is what made the binary unbootable. Upstream's public path stayed claimed by upstream, mattermost-plugin-ai imported it, and the build linked public/model twice; public/plugin's gob.Register then ran twice under one name and panicked at init, before main. Reverting the rename traded the brand for a working binary. Rebranding the plugin alongside it needs no such trade: the agents fork is github.com/hanzoteam/agents/v2 against our public module, so no module named mattermost/mattermost is in the graph at all. Measured: `go list -deps ./cmd/mattermost` names exactly one public/model, and it is ours.
589 lines
24 KiB
Go
589 lines
24 KiB
Go
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
|
// See LICENSE.txt for license information.
|
|
|
|
package properties
|
|
|
|
import (
|
|
"errors"
|
|
|
|
"github.com/hanzoteam/server/server/public/model"
|
|
"github.com/hanzoteam/server/server/public/shared/mlog"
|
|
"github.com/hanzoteam/server/server/public/shared/request"
|
|
)
|
|
|
|
// errNilHookResult is returned when a pre-hook returns a nil result without an
|
|
// error. This catches buggy hook implementations early rather than letting a
|
|
// nil propagate into the store layer.
|
|
var (
|
|
errNilHookResult = errors.New("property hook returned nil result")
|
|
errFieldCardinalityBroken = errors.New("PostGetPropertyFields hook returned fewer fields than it received")
|
|
)
|
|
|
|
// PropertyHook defines an interface for hooks that run before and after property
|
|
// service operations. Hooks can inspect and modify inputs (pre-hooks) or filter
|
|
// outputs (post-hooks). A pre-hook returns an error to block the operation; a
|
|
// post-hook returns an error to suppress the result. Returning nil means the
|
|
// hook has no objection and the operation may proceed.
|
|
//
|
|
// Pre-hooks receive the operation's input parameters and may return modified
|
|
// versions. Post-hooks receive the operation's results and may return filtered
|
|
// or modified versions.
|
|
//
|
|
// Multiple hooks are called in registration order. Each hook receives the
|
|
// output of the previous hook (or the original input for the first hook).
|
|
type PropertyHook interface {
|
|
// Field pre-hooks (write operations)
|
|
|
|
PreCreatePropertyField(rctx request.CTX, field *model.PropertyField) (*model.PropertyField, error)
|
|
PreUpdatePropertyField(rctx request.CTX, groupID string, field *model.PropertyField) (*model.PropertyField, error)
|
|
PreUpdatePropertyFields(rctx request.CTX, groupID string, fields []*model.PropertyField) ([]*model.PropertyField, error)
|
|
PreDeletePropertyField(rctx request.CTX, groupID string, id string) error
|
|
|
|
// PostUpdatePropertyFields runs after a successful field update (including
|
|
// the linked-field propagation pass). It receives the pre-update state of
|
|
// the requested fields (parallel to requested), the post-update requested
|
|
// fields, and the post-update propagated fields. Hooks may transform attrs
|
|
// on either bucket (e.g. redact information for the caller); the
|
|
// dispatcher enforces cardinality preservation on both buckets so a buggy
|
|
// hook that drops fields surfaces an error rather than silently truncating
|
|
// the broadcast. Returns the IDs of fields whose dependent property values
|
|
// were cleared as a side effect (e.g. type-change cleanup); the caller
|
|
// publishes the corresponding WS events. Errors are best-effort: the
|
|
// dispatcher logs and continues, the update is not rolled back.
|
|
PostUpdatePropertyFields(rctx request.CTX, groupID string, prev, requested, propagated []*model.PropertyField) (newRequested, newPropagated []*model.PropertyField, clearedFieldIDs []string, err error)
|
|
|
|
// Field pre-hook for count operations. Count operations return only a
|
|
// scalar so there is no post-hook — access control applied to per-row
|
|
// data does not apply, but license/group-level gating still does.
|
|
// Return an error to block the count.
|
|
PreCountPropertyFields(rctx request.CTX, groupID string) error
|
|
|
|
// Field post-hooks (read operations)
|
|
//
|
|
// PostGetPropertyField is called after retrieving a single field (by ID or by name).
|
|
// Implementations must return a non-nil field; returning nil is treated as a
|
|
// hook bug and the dispatcher surfaces errNilHookResult. To block a caller
|
|
// from seeing a field, return a sentinel error instead.
|
|
PostGetPropertyField(rctx request.CTX, field *model.PropertyField) (*model.PropertyField, error)
|
|
// PostGetPropertyFields is called after retrieving multiple fields (by IDs or search).
|
|
// Implementations must preserve slice length — the dispatcher enforces this and will
|
|
// return an error if a hook returns fewer fields than it received.
|
|
PostGetPropertyFields(rctx request.CTX, fields []*model.PropertyField) ([]*model.PropertyField, error)
|
|
|
|
// Value pre-hooks (write operations)
|
|
|
|
PreCreatePropertyValue(rctx request.CTX, value *model.PropertyValue) (*model.PropertyValue, error)
|
|
PreCreatePropertyValues(rctx request.CTX, values []*model.PropertyValue) ([]*model.PropertyValue, error)
|
|
PreUpdatePropertyValue(rctx request.CTX, groupID string, value *model.PropertyValue) (*model.PropertyValue, error)
|
|
PreUpdatePropertyValues(rctx request.CTX, groupID string, values []*model.PropertyValue) ([]*model.PropertyValue, error)
|
|
PreUpsertPropertyValue(rctx request.CTX, value *model.PropertyValue) (*model.PropertyValue, error)
|
|
PreUpsertPropertyValues(rctx request.CTX, values []*model.PropertyValue) ([]*model.PropertyValue, error)
|
|
PreDeletePropertyValue(rctx request.CTX, groupID string, id string) error
|
|
PreDeletePropertyValuesForTarget(rctx request.CTX, groupID string, targetType string, targetID string) error
|
|
PreDeletePropertyValuesForField(rctx request.CTX, groupID string, fieldID string) error
|
|
|
|
// Value post-hooks (write operations)
|
|
//
|
|
// These run after a successful store write. They are best-effort: the
|
|
// dispatcher logs and continues on a hook error, and the write is never
|
|
// rolled back; hooks must not mutate the values. Delete hooks receive the
|
|
// delete selector and, when available, the value's pre-delete snapshot.
|
|
PostCreatePropertyValue(rctx request.CTX, value *model.PropertyValue) error
|
|
PostCreatePropertyValues(rctx request.CTX, values []*model.PropertyValue) error
|
|
PostUpdatePropertyValue(rctx request.CTX, value *model.PropertyValue) error
|
|
PostUpdatePropertyValues(rctx request.CTX, values []*model.PropertyValue) error
|
|
PostUpsertPropertyValue(rctx request.CTX, value *model.PropertyValue) error
|
|
PostUpsertPropertyValues(rctx request.CTX, values []*model.PropertyValue) error
|
|
PostDeletePropertyValue(rctx request.CTX, groupID, valueID string, deleted *model.PropertyValue) error
|
|
PostDeletePropertyValuesForTarget(rctx request.CTX, groupID string, targetType string, targetID string) error
|
|
PostDeletePropertyValuesForField(rctx request.CTX, groupID string, fieldID string) error
|
|
|
|
// Value post-hooks (read operations)
|
|
//
|
|
// PostGetPropertyValue is called after retrieving a single value.
|
|
// Return nil value to indicate the value is not accessible.
|
|
PostGetPropertyValue(rctx request.CTX, value *model.PropertyValue) (*model.PropertyValue, error)
|
|
// PostGetPropertyValues is called after retrieving multiple values (by IDs or search).
|
|
// Implementations may remove entries from the returned slice.
|
|
PostGetPropertyValues(rctx request.CTX, values []*model.PropertyValue) ([]*model.PropertyValue, error)
|
|
}
|
|
|
|
// BasePropertyHook provides default passthrough implementations for every
|
|
// PropertyHook method. Embed it in concrete hooks to only override the
|
|
// methods you care about.
|
|
type BasePropertyHook struct{}
|
|
|
|
func (BasePropertyHook) PreCreatePropertyField(_ request.CTX, field *model.PropertyField) (*model.PropertyField, error) {
|
|
return field, nil
|
|
}
|
|
func (BasePropertyHook) PreUpdatePropertyField(_ request.CTX, _ string, field *model.PropertyField) (*model.PropertyField, error) {
|
|
return field, nil
|
|
}
|
|
func (BasePropertyHook) PreUpdatePropertyFields(_ request.CTX, _ string, fields []*model.PropertyField) ([]*model.PropertyField, error) {
|
|
return fields, nil
|
|
}
|
|
func (BasePropertyHook) PreDeletePropertyField(_ request.CTX, _ string, _ string) error {
|
|
return nil
|
|
}
|
|
func (BasePropertyHook) PostUpdatePropertyFields(_ request.CTX, _ string, _, requested, propagated []*model.PropertyField) ([]*model.PropertyField, []*model.PropertyField, []string, error) {
|
|
return requested, propagated, nil, nil
|
|
}
|
|
func (BasePropertyHook) PreCountPropertyFields(_ request.CTX, _ string) error {
|
|
return nil
|
|
}
|
|
func (BasePropertyHook) PostGetPropertyField(_ request.CTX, field *model.PropertyField) (*model.PropertyField, error) {
|
|
return field, nil
|
|
}
|
|
func (BasePropertyHook) PostGetPropertyFields(_ request.CTX, fields []*model.PropertyField) ([]*model.PropertyField, error) {
|
|
return fields, nil
|
|
}
|
|
func (BasePropertyHook) PreCreatePropertyValue(_ request.CTX, value *model.PropertyValue) (*model.PropertyValue, error) {
|
|
return value, nil
|
|
}
|
|
func (BasePropertyHook) PreCreatePropertyValues(_ request.CTX, values []*model.PropertyValue) ([]*model.PropertyValue, error) {
|
|
return values, nil
|
|
}
|
|
func (BasePropertyHook) PreUpdatePropertyValue(_ request.CTX, _ string, value *model.PropertyValue) (*model.PropertyValue, error) {
|
|
return value, nil
|
|
}
|
|
func (BasePropertyHook) PreUpdatePropertyValues(_ request.CTX, _ string, values []*model.PropertyValue) ([]*model.PropertyValue, error) {
|
|
return values, nil
|
|
}
|
|
func (BasePropertyHook) PreUpsertPropertyValue(_ request.CTX, value *model.PropertyValue) (*model.PropertyValue, error) {
|
|
return value, nil
|
|
}
|
|
func (BasePropertyHook) PreUpsertPropertyValues(_ request.CTX, values []*model.PropertyValue) ([]*model.PropertyValue, error) {
|
|
return values, nil
|
|
}
|
|
func (BasePropertyHook) PreDeletePropertyValue(_ request.CTX, _ string, _ string) error {
|
|
return nil
|
|
}
|
|
func (BasePropertyHook) PreDeletePropertyValuesForTarget(_ request.CTX, _ string, _ string, _ string) error {
|
|
return nil
|
|
}
|
|
func (BasePropertyHook) PreDeletePropertyValuesForField(_ request.CTX, _ string, _ string) error {
|
|
return nil
|
|
}
|
|
func (BasePropertyHook) PostCreatePropertyValue(_ request.CTX, _ *model.PropertyValue) error {
|
|
return nil
|
|
}
|
|
func (BasePropertyHook) PostCreatePropertyValues(_ request.CTX, _ []*model.PropertyValue) error {
|
|
return nil
|
|
}
|
|
func (BasePropertyHook) PostUpdatePropertyValue(_ request.CTX, _ *model.PropertyValue) error {
|
|
return nil
|
|
}
|
|
func (BasePropertyHook) PostUpdatePropertyValues(_ request.CTX, _ []*model.PropertyValue) error {
|
|
return nil
|
|
}
|
|
func (BasePropertyHook) PostUpsertPropertyValue(_ request.CTX, _ *model.PropertyValue) error {
|
|
return nil
|
|
}
|
|
func (BasePropertyHook) PostUpsertPropertyValues(_ request.CTX, _ []*model.PropertyValue) error {
|
|
return nil
|
|
}
|
|
func (BasePropertyHook) PostDeletePropertyValue(_ request.CTX, _, _ string, _ *model.PropertyValue) error {
|
|
return nil
|
|
}
|
|
func (BasePropertyHook) PostDeletePropertyValuesForTarget(_ request.CTX, _ string, _ string, _ string) error {
|
|
return nil
|
|
}
|
|
func (BasePropertyHook) PostDeletePropertyValuesForField(_ request.CTX, _ string, _ string) error {
|
|
return nil
|
|
}
|
|
func (BasePropertyHook) PostGetPropertyValue(_ request.CTX, value *model.PropertyValue) (*model.PropertyValue, error) {
|
|
return value, nil
|
|
}
|
|
func (BasePropertyHook) PostGetPropertyValues(_ request.CTX, values []*model.PropertyValue) ([]*model.PropertyValue, error) {
|
|
return values, nil
|
|
}
|
|
|
|
// AddHook registers a hook with the property service. Hooks are called in
|
|
// registration order for each operation.
|
|
func (ps *PropertyService) AddHook(hook PropertyHook) {
|
|
ps.hooks = append(ps.hooks, hook)
|
|
}
|
|
|
|
// runPreCreatePropertyField runs all registered pre-hooks for CreatePropertyField.
|
|
func (ps *PropertyService) runPreCreatePropertyField(rctx request.CTX, field *model.PropertyField) (*model.PropertyField, error) {
|
|
var err error
|
|
for _, hook := range ps.hooks {
|
|
field, err = hook.PreCreatePropertyField(rctx, field)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if field == nil {
|
|
return nil, errNilHookResult
|
|
}
|
|
}
|
|
return field, nil
|
|
}
|
|
|
|
// runPreUpdatePropertyField runs all registered pre-hooks for UpdatePropertyField.
|
|
func (ps *PropertyService) runPreUpdatePropertyField(rctx request.CTX, groupID string, field *model.PropertyField) (*model.PropertyField, error) {
|
|
var err error
|
|
for _, hook := range ps.hooks {
|
|
field, err = hook.PreUpdatePropertyField(rctx, groupID, field)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if field == nil {
|
|
return nil, errNilHookResult
|
|
}
|
|
}
|
|
return field, nil
|
|
}
|
|
|
|
// runPreUpdatePropertyFields runs all registered pre-hooks for UpdatePropertyFields.
|
|
func (ps *PropertyService) runPreUpdatePropertyFields(rctx request.CTX, groupID string, fields []*model.PropertyField) ([]*model.PropertyField, error) {
|
|
var err error
|
|
for _, hook := range ps.hooks {
|
|
fields, err = hook.PreUpdatePropertyFields(rctx, groupID, fields)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if fields == nil {
|
|
return nil, errNilHookResult
|
|
}
|
|
}
|
|
return fields, nil
|
|
}
|
|
|
|
// runPostUpdatePropertyFields runs all registered post-hooks for
|
|
// UpdatePropertyFields. Each hook may transform the requested and propagated
|
|
// buckets in place (e.g. redaction); the dispatcher chains the transformed
|
|
// slices through subsequent hooks and enforces cardinality preservation on
|
|
// both buckets so a buggy hook that drops fields surfaces an error rather
|
|
// than silently truncating the broadcast. The cleared field IDs returned by
|
|
// each hook are deduped into a single slice. Best-effort: hook errors and
|
|
// cardinality violations are logged and skipped (the offending hook's
|
|
// transform is dropped for the chain, but the update itself is not rolled
|
|
// back).
|
|
func (ps *PropertyService) runPostUpdatePropertyFields(rctx request.CTX, groupID string, prev, requested, propagated []*model.PropertyField) ([]*model.PropertyField, []*model.PropertyField, []string) {
|
|
seen := map[string]struct{}{}
|
|
var cleared []string
|
|
for _, hook := range ps.hooks {
|
|
newRequested, newPropagated, ids, err := hook.PostUpdatePropertyFields(rctx, groupID, prev, requested, propagated)
|
|
if err != nil {
|
|
rctx.Logger().Error("PostUpdatePropertyFields hook failed",
|
|
mlog.String("group_id", groupID),
|
|
mlog.Err(err),
|
|
)
|
|
continue
|
|
}
|
|
if len(newRequested) != len(requested) || len(newPropagated) != len(propagated) {
|
|
rctx.Logger().Error("PostUpdatePropertyFields hook returned wrong-length slice",
|
|
mlog.String("group_id", groupID),
|
|
mlog.Err(errFieldCardinalityBroken),
|
|
)
|
|
continue
|
|
}
|
|
requested = newRequested
|
|
propagated = newPropagated
|
|
for _, id := range ids {
|
|
if _, ok := seen[id]; ok {
|
|
continue
|
|
}
|
|
seen[id] = struct{}{}
|
|
cleared = append(cleared, id)
|
|
}
|
|
}
|
|
return requested, propagated, cleared
|
|
}
|
|
|
|
// runPreDeletePropertyField runs all registered pre-hooks for DeletePropertyField.
|
|
func (ps *PropertyService) runPreDeletePropertyField(rctx request.CTX, groupID string, id string) error {
|
|
for _, hook := range ps.hooks {
|
|
if err := hook.PreDeletePropertyField(rctx, groupID, id); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// runPreCountPropertyFields runs all registered pre-hooks for the public
|
|
// CountProperty* methods.
|
|
func (ps *PropertyService) runPreCountPropertyFields(rctx request.CTX, groupID string) error {
|
|
for _, hook := range ps.hooks {
|
|
if err := hook.PreCountPropertyFields(rctx, groupID); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// runPostGetPropertyField runs all registered post-hooks for single field retrieval.
|
|
func (ps *PropertyService) runPostGetPropertyField(rctx request.CTX, field *model.PropertyField) (*model.PropertyField, error) {
|
|
if field == nil {
|
|
return nil, nil
|
|
}
|
|
var err error
|
|
for _, hook := range ps.hooks {
|
|
field, err = hook.PostGetPropertyField(rctx, field)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if field == nil {
|
|
return nil, errNilHookResult
|
|
}
|
|
}
|
|
return field, nil
|
|
}
|
|
|
|
// runPostGetPropertyFields runs all registered post-hooks for multi-field retrieval.
|
|
// It enforces that hooks preserve slice length — a hook that drops fields is a bug.
|
|
func (ps *PropertyService) runPostGetPropertyFields(rctx request.CTX, fields []*model.PropertyField) ([]*model.PropertyField, error) {
|
|
var err error
|
|
for _, hook := range ps.hooks {
|
|
n := len(fields)
|
|
fields, err = hook.PostGetPropertyFields(rctx, fields)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if len(fields) != n {
|
|
return nil, errFieldCardinalityBroken
|
|
}
|
|
}
|
|
return fields, nil
|
|
}
|
|
|
|
// runPreCreatePropertyValue runs all registered pre-hooks for CreatePropertyValue.
|
|
func (ps *PropertyService) runPreCreatePropertyValue(rctx request.CTX, value *model.PropertyValue) (*model.PropertyValue, error) {
|
|
var err error
|
|
for _, hook := range ps.hooks {
|
|
value, err = hook.PreCreatePropertyValue(rctx, value)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if value == nil {
|
|
return nil, errNilHookResult
|
|
}
|
|
}
|
|
return value, nil
|
|
}
|
|
|
|
// runPreCreatePropertyValues runs all registered pre-hooks for CreatePropertyValues.
|
|
func (ps *PropertyService) runPreCreatePropertyValues(rctx request.CTX, values []*model.PropertyValue) ([]*model.PropertyValue, error) {
|
|
var err error
|
|
for _, hook := range ps.hooks {
|
|
values, err = hook.PreCreatePropertyValues(rctx, values)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if values == nil {
|
|
return nil, errNilHookResult
|
|
}
|
|
}
|
|
return values, nil
|
|
}
|
|
|
|
// runPreUpdatePropertyValue runs all registered pre-hooks for UpdatePropertyValue.
|
|
func (ps *PropertyService) runPreUpdatePropertyValue(rctx request.CTX, groupID string, value *model.PropertyValue) (*model.PropertyValue, error) {
|
|
var err error
|
|
for _, hook := range ps.hooks {
|
|
value, err = hook.PreUpdatePropertyValue(rctx, groupID, value)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if value == nil {
|
|
return nil, errNilHookResult
|
|
}
|
|
}
|
|
return value, nil
|
|
}
|
|
|
|
// runPreUpdatePropertyValues runs all registered pre-hooks for UpdatePropertyValues.
|
|
func (ps *PropertyService) runPreUpdatePropertyValues(rctx request.CTX, groupID string, values []*model.PropertyValue) ([]*model.PropertyValue, error) {
|
|
var err error
|
|
for _, hook := range ps.hooks {
|
|
values, err = hook.PreUpdatePropertyValues(rctx, groupID, values)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if values == nil {
|
|
return nil, errNilHookResult
|
|
}
|
|
}
|
|
return values, nil
|
|
}
|
|
|
|
// runPreUpsertPropertyValue runs all registered pre-hooks for UpsertPropertyValue.
|
|
func (ps *PropertyService) runPreUpsertPropertyValue(rctx request.CTX, value *model.PropertyValue) (*model.PropertyValue, error) {
|
|
var err error
|
|
for _, hook := range ps.hooks {
|
|
value, err = hook.PreUpsertPropertyValue(rctx, value)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if value == nil {
|
|
return nil, errNilHookResult
|
|
}
|
|
}
|
|
return value, nil
|
|
}
|
|
|
|
// runPreUpsertPropertyValues runs all registered pre-hooks for UpsertPropertyValues.
|
|
func (ps *PropertyService) runPreUpsertPropertyValues(rctx request.CTX, values []*model.PropertyValue) ([]*model.PropertyValue, error) {
|
|
var err error
|
|
for _, hook := range ps.hooks {
|
|
values, err = hook.PreUpsertPropertyValues(rctx, values)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if values == nil {
|
|
return nil, errNilHookResult
|
|
}
|
|
}
|
|
return values, nil
|
|
}
|
|
|
|
// runPreDeletePropertyValue runs all registered pre-hooks for DeletePropertyValue.
|
|
func (ps *PropertyService) runPreDeletePropertyValue(rctx request.CTX, groupID string, id string) error {
|
|
for _, hook := range ps.hooks {
|
|
if err := hook.PreDeletePropertyValue(rctx, groupID, id); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// runPreDeletePropertyValuesForTarget runs all registered pre-hooks for DeletePropertyValuesForTarget.
|
|
func (ps *PropertyService) runPreDeletePropertyValuesForTarget(rctx request.CTX, groupID string, targetType string, targetID string) error {
|
|
for _, hook := range ps.hooks {
|
|
if err := hook.PreDeletePropertyValuesForTarget(rctx, groupID, targetType, targetID); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// runPreDeletePropertyValuesForField runs all registered pre-hooks for DeletePropertyValuesForField.
|
|
func (ps *PropertyService) runPreDeletePropertyValuesForField(rctx request.CTX, groupID string, fieldID string) error {
|
|
for _, hook := range ps.hooks {
|
|
if err := hook.PreDeletePropertyValuesForField(rctx, groupID, fieldID); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// runPostCreatePropertyValue runs all registered post-hooks for CreatePropertyValue.
|
|
// Best-effort.
|
|
func (ps *PropertyService) runPostCreatePropertyValue(rctx request.CTX, value *model.PropertyValue) {
|
|
for _, hook := range ps.hooks {
|
|
if err := hook.PostCreatePropertyValue(rctx, value); err != nil {
|
|
rctx.Logger().Error("PostCreatePropertyValue hook failed", mlog.Err(err))
|
|
}
|
|
}
|
|
}
|
|
|
|
// runPostCreatePropertyValues runs all registered post-hooks for CreatePropertyValues.
|
|
// Best-effort.
|
|
func (ps *PropertyService) runPostCreatePropertyValues(rctx request.CTX, values []*model.PropertyValue) {
|
|
for _, hook := range ps.hooks {
|
|
if err := hook.PostCreatePropertyValues(rctx, values); err != nil {
|
|
rctx.Logger().Error("PostCreatePropertyValues hook failed", mlog.Err(err))
|
|
}
|
|
}
|
|
}
|
|
|
|
// runPostUpdatePropertyValue runs all registered post-hooks for UpdatePropertyValue.
|
|
// Best-effort.
|
|
func (ps *PropertyService) runPostUpdatePropertyValue(rctx request.CTX, value *model.PropertyValue) {
|
|
for _, hook := range ps.hooks {
|
|
if err := hook.PostUpdatePropertyValue(rctx, value); err != nil {
|
|
rctx.Logger().Error("PostUpdatePropertyValue hook failed", mlog.Err(err))
|
|
}
|
|
}
|
|
}
|
|
|
|
// runPostUpdatePropertyValues runs all registered post-hooks for UpdatePropertyValues.
|
|
// Best-effort.
|
|
func (ps *PropertyService) runPostUpdatePropertyValues(rctx request.CTX, values []*model.PropertyValue) {
|
|
for _, hook := range ps.hooks {
|
|
if err := hook.PostUpdatePropertyValues(rctx, values); err != nil {
|
|
rctx.Logger().Error("PostUpdatePropertyValues hook failed", mlog.Err(err))
|
|
}
|
|
}
|
|
}
|
|
|
|
// runPostUpsertPropertyValue runs all registered post-hooks for UpsertPropertyValue.
|
|
// Best-effort: hook errors are logged and skipped; the write is not rolled back.
|
|
func (ps *PropertyService) runPostUpsertPropertyValue(rctx request.CTX, value *model.PropertyValue) {
|
|
for _, hook := range ps.hooks {
|
|
if err := hook.PostUpsertPropertyValue(rctx, value); err != nil {
|
|
rctx.Logger().Error("PostUpsertPropertyValue hook failed", mlog.Err(err))
|
|
}
|
|
}
|
|
}
|
|
|
|
// runPostUpsertPropertyValues runs all registered post-hooks for UpsertPropertyValues.
|
|
// Best-effort.
|
|
func (ps *PropertyService) runPostUpsertPropertyValues(rctx request.CTX, values []*model.PropertyValue) {
|
|
for _, hook := range ps.hooks {
|
|
if err := hook.PostUpsertPropertyValues(rctx, values); err != nil {
|
|
rctx.Logger().Error("PostUpsertPropertyValues hook failed", mlog.Err(err))
|
|
}
|
|
}
|
|
}
|
|
|
|
// runPostDeletePropertyValue runs all registered post-hooks for DeletePropertyValue.
|
|
// deleted is the pre-delete snapshot. Best-effort.
|
|
func (ps *PropertyService) runPostDeletePropertyValue(rctx request.CTX, groupID, valueID string, deleted *model.PropertyValue) {
|
|
for _, hook := range ps.hooks {
|
|
if err := hook.PostDeletePropertyValue(rctx, groupID, valueID, deleted); err != nil {
|
|
rctx.Logger().Error("PostDeletePropertyValue hook failed", mlog.Err(err))
|
|
}
|
|
}
|
|
}
|
|
|
|
// runPostDeletePropertyValuesForTarget runs all registered post-hooks for DeletePropertyValuesForTarget.
|
|
// Best-effort.
|
|
func (ps *PropertyService) runPostDeletePropertyValuesForTarget(rctx request.CTX, groupID, targetType, targetID string) {
|
|
for _, hook := range ps.hooks {
|
|
if err := hook.PostDeletePropertyValuesForTarget(rctx, groupID, targetType, targetID); err != nil {
|
|
rctx.Logger().Error("PostDeletePropertyValuesForTarget hook failed", mlog.Err(err))
|
|
}
|
|
}
|
|
}
|
|
|
|
// runPostDeletePropertyValuesForField runs all registered post-hooks for DeletePropertyValuesForField.
|
|
// Best-effort.
|
|
func (ps *PropertyService) runPostDeletePropertyValuesForField(rctx request.CTX, groupID, fieldID string) {
|
|
for _, hook := range ps.hooks {
|
|
if err := hook.PostDeletePropertyValuesForField(rctx, groupID, fieldID); err != nil {
|
|
rctx.Logger().Error("PostDeletePropertyValuesForField hook failed", mlog.Err(err))
|
|
}
|
|
}
|
|
}
|
|
|
|
// runPostGetPropertyValue runs all registered post-hooks for single value retrieval.
|
|
func (ps *PropertyService) runPostGetPropertyValue(rctx request.CTX, value *model.PropertyValue) (*model.PropertyValue, error) {
|
|
if value == nil {
|
|
return nil, nil
|
|
}
|
|
var err error
|
|
for _, hook := range ps.hooks {
|
|
value, err = hook.PostGetPropertyValue(rctx, value)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if value == nil {
|
|
return nil, nil
|
|
}
|
|
}
|
|
return value, nil
|
|
}
|
|
|
|
// runPostGetPropertyValues runs all registered post-hooks for multi-value retrieval.
|
|
func (ps *PropertyService) runPostGetPropertyValues(rctx request.CTX, values []*model.PropertyValue) ([]*model.PropertyValue, error) {
|
|
var err error
|
|
for _, hook := range ps.hooks {
|
|
values, err = hook.PostGetPropertyValues(rctx, values)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
return values, nil
|
|
}
|