fx build fix
This commit is contained in:
@@ -1,43 +0,0 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/tech/sendico/pkg/db/template"
|
||||
"github.com/tech/sendico/pkg/model"
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
)
|
||||
|
||||
// TaggableDB implements tag operations with permission checking
|
||||
type TaggableDB[T model.PermissionBoundStorable] interface {
|
||||
// AddTag adds a tag to an entity with permission checking
|
||||
AddTag(ctx context.Context, accountRef, objectRef, tagRef primitive.ObjectID) error
|
||||
// RemoveTagd removes a tags from the collection using organizationRef with permission checking
|
||||
RemoveTags(ctx context.Context, accountRef, organizationRef, tagRef primitive.ObjectID) error
|
||||
// RemoveTag removes a tag from an entity with permission checking
|
||||
RemoveTag(ctx context.Context, accountRef, objectRef, tagRef primitive.ObjectID) error
|
||||
// AddTags adds multiple tags to an entity with permission checking
|
||||
AddTags(ctx context.Context, accountRef, objectRef primitive.ObjectID, tagRefs []primitive.ObjectID) error
|
||||
// SetTags sets the tags for an entity with permission checking
|
||||
SetTags(ctx context.Context, accountRef, objectRef primitive.ObjectID, tagRefs []primitive.ObjectID) error
|
||||
// RemoveAllTags removes all tags from an entity with permission checking
|
||||
RemoveAllTags(ctx context.Context, accountRef, objectRef primitive.ObjectID) error
|
||||
// GetTags gets the tags for an entity with permission checking
|
||||
GetTags(ctx context.Context, accountRef, objectRef primitive.ObjectID) ([]primitive.ObjectID, error)
|
||||
// HasTag checks if an entity has a specific tag with permission checking
|
||||
HasTag(ctx context.Context, accountRef, objectRef, tagRef primitive.ObjectID) (bool, error)
|
||||
// FindByTag finds all entities that have a specific tag with permission checking
|
||||
FindByTag(ctx context.Context, accountRef, tagRef primitive.ObjectID) ([]T, error)
|
||||
// FindByTags finds all entities that have any of the specified tags with permission checking
|
||||
FindByTags(ctx context.Context, accountRef primitive.ObjectID, tagRefs []primitive.ObjectID) ([]T, error)
|
||||
}
|
||||
|
||||
// NewTaggableDBImp creates a new auth.TaggableDB instance
|
||||
func NewTaggableDB[T model.PermissionBoundStorable](
|
||||
dbImp *template.DBImp[T],
|
||||
enforcer Enforcer,
|
||||
createEmpty func() T,
|
||||
getTaggable func(T) *model.Taggable,
|
||||
) TaggableDB[T] {
|
||||
return newTaggableDBImp(dbImp, enforcer, createEmpty, getTaggable)
|
||||
}
|
||||
@@ -1,302 +0,0 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/tech/sendico/pkg/db/repository"
|
||||
"github.com/tech/sendico/pkg/db/repository/builder"
|
||||
"github.com/tech/sendico/pkg/db/template"
|
||||
"github.com/tech/sendico/pkg/merrors"
|
||||
"github.com/tech/sendico/pkg/mlogger"
|
||||
"github.com/tech/sendico/pkg/model"
|
||||
"github.com/tech/sendico/pkg/mutil/mzap"
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
// taggableDBImp implements tag operations with permission checking
|
||||
type taggableDBImp[T model.PermissionBoundStorable] struct {
|
||||
dbImp *template.DBImp[T]
|
||||
logger mlogger.Logger
|
||||
enforcer Enforcer
|
||||
createEmpty func() T
|
||||
getTaggable func(T) *model.Taggable
|
||||
}
|
||||
|
||||
func newTaggableDBImp[T model.PermissionBoundStorable](
|
||||
dbImp *template.DBImp[T],
|
||||
enforcer Enforcer,
|
||||
createEmpty func() T,
|
||||
getTaggable func(T) *model.Taggable,
|
||||
) TaggableDB[T] {
|
||||
return &taggableDBImp[T]{
|
||||
dbImp: dbImp,
|
||||
logger: dbImp.Logger.Named("taggable"),
|
||||
enforcer: enforcer,
|
||||
createEmpty: createEmpty,
|
||||
getTaggable: getTaggable,
|
||||
}
|
||||
}
|
||||
|
||||
func (db *taggableDBImp[T]) AddTag(ctx context.Context, accountRef, objectRef, tagRef primitive.ObjectID) error {
|
||||
// Check permissions using enforceObject helper
|
||||
if err := enforceObjectByRef(ctx, db.dbImp, db.enforcer, model.ActionUpdate, accountRef, objectRef); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Add the tag
|
||||
patch := repository.Patch().AddToSet(repository.TagRefsField(), tagRef)
|
||||
if err := db.dbImp.Patch(ctx, objectRef, patch); err != nil {
|
||||
db.logger.Warn("Failed to add tag to object", zap.Error(err),
|
||||
mzap.ObjRef("account_ref", accountRef), mzap.ObjRef("object_ref", objectRef), mzap.ObjRef("tag_ref", tagRef))
|
||||
return err
|
||||
}
|
||||
|
||||
db.logger.Debug("Successfully added tag to object", mzap.ObjRef("account_ref", accountRef),
|
||||
mzap.ObjRef("object_ref", objectRef), mzap.ObjRef("tag_ref", tagRef))
|
||||
return nil
|
||||
}
|
||||
|
||||
func (db *taggableDBImp[T]) removeTag(ctx context.Context, accountRef, targetRef, tagRef primitive.ObjectID, query builder.Query) error {
|
||||
// Check permissions using enforceObject helper
|
||||
if err := enforceObject(ctx, db.dbImp, db.enforcer, model.ActionUpdate, accountRef, query); err != nil {
|
||||
db.logger.Debug("Error enforcing permissions for removing tag", zap.Error(err),
|
||||
mzap.ObjRef("account_ref", accountRef), mzap.ObjRef("target_ref", targetRef), mzap.ObjRef("tag_ref", tagRef))
|
||||
return err
|
||||
}
|
||||
|
||||
// Remove the tag
|
||||
patch := repository.Patch().Pull(repository.TagRefsField(), tagRef)
|
||||
patched, err := db.dbImp.PatchMany(ctx, query, patch)
|
||||
if err != nil {
|
||||
db.logger.Warn("Failed to remove tag from object", zap.Error(err),
|
||||
mzap.ObjRef("account_ref", accountRef), mzap.ObjRef("target_ref", targetRef), mzap.ObjRef("tag_ref", tagRef))
|
||||
return err
|
||||
}
|
||||
|
||||
db.logger.Debug("Successfully removed tag from object", mzap.ObjRef("account_ref", accountRef),
|
||||
mzap.ObjRef("target_ref", targetRef), mzap.ObjRef("tag_ref", tagRef), zap.Int("patched_count", patched))
|
||||
return nil
|
||||
}
|
||||
|
||||
func (db *taggableDBImp[T]) RemoveTags(ctx context.Context, accountRef, organizationRef, tagRef primitive.ObjectID) error {
|
||||
return db.removeTag(ctx, accountRef, primitive.NilObjectID, tagRef, repository.OrgFilter(organizationRef))
|
||||
}
|
||||
|
||||
func (db *taggableDBImp[T]) RemoveTag(ctx context.Context, accountRef, objectRef, tagRef primitive.ObjectID) error {
|
||||
return db.removeTag(ctx, accountRef, objectRef, tagRef, repository.IDFilter(objectRef))
|
||||
}
|
||||
|
||||
// AddTags adds multiple tags to an entity with permission checking
|
||||
func (db *taggableDBImp[T]) AddTags(ctx context.Context, accountRef, objectRef primitive.ObjectID, tagRefs []primitive.ObjectID) error {
|
||||
// Check permissions using enforceObject helper
|
||||
if err := enforceObjectByRef(ctx, db.dbImp, db.enforcer, model.ActionUpdate, accountRef, objectRef); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Add the tags one by one using $addToSet to avoid duplicates
|
||||
for _, tagRef := range tagRefs {
|
||||
patch := repository.Patch().AddToSet(repository.TagRefsField(), tagRef)
|
||||
if err := db.dbImp.Patch(ctx, objectRef, patch); err != nil {
|
||||
db.logger.Warn("Failed to add tag to object", zap.Error(err),
|
||||
mzap.ObjRef("account_ref", accountRef), mzap.ObjRef("object_ref", objectRef), mzap.ObjRef("tag_ref", tagRef))
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
db.logger.Debug("Successfully added tags to object", mzap.ObjRef("account_ref", accountRef),
|
||||
mzap.ObjRef("object_ref", objectRef), zap.Int("tag_count", len(tagRefs)))
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetTags sets the tags for an entity with permission checking
|
||||
func (db *taggableDBImp[T]) SetTags(ctx context.Context, accountRef, objectRef primitive.ObjectID, tagRefs []primitive.ObjectID) error {
|
||||
// Check permissions using enforceObject helper
|
||||
if err := enforceObjectByRef(ctx, db.dbImp, db.enforcer, model.ActionUpdate, accountRef, objectRef); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Set the tags
|
||||
patch := repository.Patch().Set(repository.TagRefsField(), tagRefs)
|
||||
if err := db.dbImp.Patch(ctx, objectRef, patch); err != nil {
|
||||
db.logger.Warn("Failed to set tags for object", zap.Error(err),
|
||||
mzap.ObjRef("account_ref", accountRef), mzap.ObjRef("object_ref", objectRef))
|
||||
return err
|
||||
}
|
||||
|
||||
db.logger.Debug("Successfully set tags for object", mzap.ObjRef("account_ref", accountRef),
|
||||
mzap.ObjRef("object_ref", objectRef), zap.Int("tag_count", len(tagRefs)))
|
||||
return nil
|
||||
}
|
||||
|
||||
// RemoveAllTags removes all tags from an entity with permission checking
|
||||
func (db *taggableDBImp[T]) RemoveAllTags(ctx context.Context, accountRef, objectRef primitive.ObjectID) error {
|
||||
// Check permissions using enforceObject helper
|
||||
if err := enforceObjectByRef(ctx, db.dbImp, db.enforcer, model.ActionUpdate, accountRef, objectRef); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Remove all tags by setting to empty array
|
||||
patch := repository.Patch().Set(repository.TagRefsField(), []primitive.ObjectID{})
|
||||
if err := db.dbImp.Patch(ctx, objectRef, patch); err != nil {
|
||||
db.logger.Warn("Failed to remove all tags from object", zap.Error(err),
|
||||
mzap.ObjRef("account_ref", accountRef), mzap.ObjRef("object_ref", objectRef))
|
||||
return err
|
||||
}
|
||||
|
||||
db.logger.Debug("Successfully removed all tags from object", mzap.ObjRef("account_ref", accountRef),
|
||||
mzap.ObjRef("object_ref", objectRef))
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetTags gets the tags for an entity with permission checking
|
||||
func (db *taggableDBImp[T]) GetTags(ctx context.Context, accountRef, objectRef primitive.ObjectID) ([]primitive.ObjectID, error) {
|
||||
// Check permissions using enforceObject helper
|
||||
if err := enforceObjectByRef(ctx, db.dbImp, db.enforcer, model.ActionRead, accountRef, objectRef); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Get the object and extract tags
|
||||
obj := db.createEmpty()
|
||||
if err := db.dbImp.Get(ctx, objectRef, obj); err != nil {
|
||||
db.logger.Warn("Failed to get object for retrieving tags", zap.Error(err),
|
||||
mzap.ObjRef("account_ref", accountRef), mzap.ObjRef("object_ref", objectRef))
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Get the tags
|
||||
taggable := db.getTaggable(obj)
|
||||
db.logger.Debug("Successfully retrieved tags for object", mzap.ObjRef("account_ref", accountRef),
|
||||
mzap.ObjRef("object_ref", objectRef), zap.Int("tag_count", len(taggable.TagRefs)))
|
||||
return taggable.TagRefs, nil
|
||||
}
|
||||
|
||||
// HasTag checks if an entity has a specific tag with permission checking
|
||||
func (db *taggableDBImp[T]) HasTag(ctx context.Context, accountRef, objectRef, tagRef primitive.ObjectID) (bool, error) {
|
||||
// Check permissions using enforceObject helper
|
||||
if err := enforceObjectByRef(ctx, db.dbImp, db.enforcer, model.ActionRead, accountRef, objectRef); err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
// Get the object and check if the tag exists
|
||||
obj := db.createEmpty()
|
||||
if err := db.dbImp.Get(ctx, objectRef, obj); err != nil {
|
||||
db.logger.Warn("Failed to get object for checking tag", zap.Error(err),
|
||||
mzap.ObjRef("account_ref", accountRef), mzap.ObjRef("object_ref", objectRef), mzap.ObjRef("tag_ref", tagRef))
|
||||
return false, err
|
||||
}
|
||||
|
||||
// Check if the tag exists
|
||||
taggable := db.getTaggable(obj)
|
||||
for _, existingTag := range taggable.TagRefs {
|
||||
if existingTag == tagRef {
|
||||
db.logger.Debug("Object has tag", mzap.ObjRef("account_ref", accountRef),
|
||||
mzap.ObjRef("object_ref", objectRef), mzap.ObjRef("tag_ref", tagRef))
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
|
||||
db.logger.Debug("Object does not have tag", mzap.ObjRef("account_ref", accountRef),
|
||||
mzap.ObjRef("object_ref", objectRef), mzap.ObjRef("tag_ref", tagRef))
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// FindByTag finds all entities that have a specific tag with permission checking
|
||||
func (db *taggableDBImp[T]) FindByTag(ctx context.Context, accountRef, tagRef primitive.ObjectID) ([]T, error) {
|
||||
// Create filter to find objects with the tag
|
||||
filter := repository.Filter(model.TagRefsField, tagRef)
|
||||
|
||||
// Get all objects with the tag using ListPermissionBound
|
||||
objects, err := db.dbImp.ListPermissionBound(ctx, filter)
|
||||
if err != nil {
|
||||
db.logger.Warn("Failed to get objects with tag", zap.Error(err),
|
||||
mzap.ObjRef("account_ref", accountRef), mzap.ObjRef("tag_ref", tagRef))
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Check permissions for all objects using EnforceBatch
|
||||
db.logger.Debug("Checking permissions for objects with tag", mzap.ObjRef("account_ref", accountRef),
|
||||
mzap.ObjRef("tag_ref", tagRef), zap.Int("object_count", len(objects)))
|
||||
|
||||
permissions, err := db.enforcer.EnforceBatch(ctx, objects, accountRef, model.ActionRead)
|
||||
if err != nil {
|
||||
db.logger.Warn("Failed to check permissions for objects with tag", zap.Error(err),
|
||||
mzap.ObjRef("account_ref", accountRef), mzap.ObjRef("tag_ref", tagRef), zap.Int("object_count", len(objects)))
|
||||
return nil, merrors.Internal("failed to check permissions for objects with tag")
|
||||
}
|
||||
|
||||
// Filter objects based on permissions and decode them
|
||||
var results []T
|
||||
for _, obj := range objects {
|
||||
objID := *obj.GetID()
|
||||
if hasPermission, exists := permissions[objID]; exists && hasPermission {
|
||||
// Decode the object
|
||||
decodedObj := db.createEmpty()
|
||||
if err := db.dbImp.Get(ctx, objID, decodedObj); err != nil {
|
||||
db.logger.Warn("Failed to decode object with tag", zap.Error(err),
|
||||
mzap.ObjRef("account_ref", accountRef), mzap.ObjRef("object_ref", objID), mzap.ObjRef("tag_ref", tagRef))
|
||||
continue
|
||||
}
|
||||
results = append(results, decodedObj)
|
||||
}
|
||||
}
|
||||
|
||||
db.logger.Debug("Successfully found objects with tag", mzap.ObjRef("account_ref", accountRef),
|
||||
mzap.ObjRef("tag_ref", tagRef), zap.Int("total_objects", len(objects)), zap.Int("accessible_objects", len(results)))
|
||||
return results, nil
|
||||
}
|
||||
|
||||
// FindByTags finds all entities that have any of the specified tags with permission checking
|
||||
func (db *taggableDBImp[T]) FindByTags(ctx context.Context, accountRef primitive.ObjectID, tagRefs []primitive.ObjectID) ([]T, error) {
|
||||
if len(tagRefs) == 0 {
|
||||
return []T{}, nil
|
||||
}
|
||||
|
||||
// Convert []primitive.ObjectID to []any for the In method
|
||||
values := make([]any, len(tagRefs))
|
||||
for i, tagRef := range tagRefs {
|
||||
values[i] = tagRef
|
||||
}
|
||||
|
||||
// Create filter to find objects with any of the tags
|
||||
filter := repository.Query().In(repository.TagRefsField(), values...)
|
||||
|
||||
// Get all objects with any of the tags using ListPermissionBound
|
||||
objects, err := db.dbImp.ListPermissionBound(ctx, filter)
|
||||
if err != nil {
|
||||
db.logger.Warn("Failed to get objects with tags", zap.Error(err),
|
||||
mzap.ObjRef("account_ref", accountRef))
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Check permissions for all objects using EnforceBatch
|
||||
db.logger.Debug("Checking permissions for objects with tags", mzap.ObjRef("account_ref", accountRef),
|
||||
zap.Int("object_count", len(objects)), zap.Int("tag_count", len(tagRefs)))
|
||||
|
||||
permissions, err := db.enforcer.EnforceBatch(ctx, objects, accountRef, model.ActionRead)
|
||||
if err != nil {
|
||||
db.logger.Warn("Failed to check permissions for objects with tags", zap.Error(err),
|
||||
mzap.ObjRef("account_ref", accountRef), zap.Int("object_count", len(objects)))
|
||||
return nil, merrors.Internal("failed to check permissions for objects with tags")
|
||||
}
|
||||
|
||||
// Filter objects based on permissions and decode them
|
||||
var results []T
|
||||
for _, obj := range objects {
|
||||
objID := *obj.GetID()
|
||||
if hasPermission, exists := permissions[objID]; exists && hasPermission {
|
||||
// Decode the object
|
||||
decodedObj := db.createEmpty()
|
||||
if err := db.dbImp.Get(ctx, objID, decodedObj); err != nil {
|
||||
db.logger.Warn("Failed to decode object with tags", zap.Error(err),
|
||||
mzap.ObjRef("account_ref", accountRef), mzap.ObjRef("object_ref", objID))
|
||||
continue
|
||||
}
|
||||
results = append(results, decodedObj)
|
||||
}
|
||||
}
|
||||
|
||||
db.logger.Debug("Successfully found objects with tags", mzap.ObjRef("account_ref", accountRef),
|
||||
zap.Int("total_objects", len(objects)), zap.Int("accessible_objects", len(results)), zap.Int("tag_count", len(tagRefs)))
|
||||
return results, nil
|
||||
}
|
||||
Reference in New Issue
Block a user