Files
sendico/api/pkg/auth/internal/native/permission.go
Stephan D 62a6631b9a
All checks were successful
ci/woodpecker/push/db Pipeline was successful
ci/woodpecker/push/nats Pipeline was successful
service backend
2025-11-07 18:35:26 +01:00

102 lines
3.6 KiB
Go

package native
import (
"context"
"errors"
"github.com/tech/sendico/pkg/auth/internal/native/nstructures"
"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"
)
// PermissionManager manages permissions using Casbin.
type PermissionManager struct {
logger mlogger.Logger
enforcer *Enforcer
}
// GrantToRole adds a permission to a role in Casbin.
func (m *PermissionManager) GrantToRole(ctx context.Context, policy *model.RolePolicy) error {
objRef := "any"
if (policy.ObjectRef != nil) && (*policy.ObjectRef != primitive.NilObjectID) {
objRef = policy.ObjectRef.Hex()
}
m.logger.Debug("Granting permission to role", mzap.ObjRef("role_ref", policy.RoleDescriptionRef),
mzap.ObjRef("permission_ref", policy.DescriptionRef), zap.String("object_ref", objRef),
zap.String("action", string(policy.Effect.Action)), zap.String("effect", string(policy.Effect.Effect)),
)
assignment := nstructures.PolicyAssignment{
Policy: policy.Policy,
RoleRef: policy.RoleDescriptionRef,
}
if err := m.enforcer.pdb.Create(ctx, &assignment); err != nil {
m.logger.Warn("Failed to grant policy", zap.Error(err), mzap.ObjRef("role_ref", policy.RoleDescriptionRef),
mzap.ObjRef("permission_ref", policy.DescriptionRef), zap.String("object_ref", objRef),
zap.String("action", string(policy.Effect.Action)), zap.String("effect", string(policy.Effect.Effect)))
return err
}
return nil
}
// RevokeFromRole removes a permission from a role in Casbin.
func (m *PermissionManager) RevokeFromRole(ctx context.Context, policy *model.RolePolicy) error {
objRef := "*"
if policy.ObjectRef != nil {
objRef = policy.ObjectRef.Hex()
}
m.logger.Debug("Revoking permission from role", mzap.ObjRef("role_ref", policy.RoleDescriptionRef),
mzap.ObjRef("permission_ref", policy.DescriptionRef), zap.String("object_ref", objRef),
zap.String("action", string(policy.Effect.Action)), zap.String("effect", string(policy.Effect.Effect)),
)
if err := m.enforcer.pdb.Remove(ctx, policy); err != nil {
m.logger.Warn("Failed to revoke policy", zap.Error(err), mzap.ObjRef("role_ref", policy.RoleDescriptionRef),
mzap.ObjRef("permission_ref", policy.DescriptionRef), zap.String("object_ref", objRef),
zap.String("action", string(policy.Effect.Action)), zap.String("effect", string(policy.Effect.Effect)))
return err
}
return nil
}
// GetPolicies retrieves all policies for a specific role.
func (m *PermissionManager) GetPolicies(
ctx context.Context,
roleRef primitive.ObjectID,
) ([]model.RolePolicy, error) {
m.logger.Debug("Fetching policies for role", mzap.ObjRef("role_ref", roleRef))
assinments, err := m.enforcer.pdb.PoliciesForRole(ctx, roleRef)
if errors.Is(err, merrors.ErrNoData) {
m.logger.Debug("No policies found", mzap.ObjRef("role_ref", roleRef))
return []model.RolePolicy{}, nil
}
policies := make([]model.RolePolicy, len(assinments))
for i, assinment := range assinments {
policies[i] = model.RolePolicy{
Policy: assinment.Policy,
RoleDescriptionRef: assinment.RoleRef,
}
}
m.logger.Debug("Policies fetched successfully", mzap.ObjRef("role_ref", roleRef), zap.Int("count", len(policies)))
return policies, nil
}
// Save persists changes to the Casbin policy store.
func (m *PermissionManager) Save() error {
m.logger.Info("Policies successfully saved") // do nothing
return nil
}
func NewPermissionManager(logger mlogger.Logger, enforcer *Enforcer) *PermissionManager {
return &PermissionManager{
logger: logger.Named("permission"),
enforcer: enforcer,
}
}