linting
This commit is contained in:
47
api/pkg/.golangci.yml
Normal file
47
api/pkg/.golangci.yml
Normal file
@@ -0,0 +1,47 @@
|
||||
version: "2"
|
||||
linters:
|
||||
default: none
|
||||
enable:
|
||||
- bodyclose
|
||||
- canonicalheader
|
||||
- copyloopvar
|
||||
- durationcheck
|
||||
- errcheck
|
||||
- errchkjson
|
||||
- errname
|
||||
- errorlint
|
||||
- gosec
|
||||
- govet
|
||||
- ineffassign
|
||||
- nilerr
|
||||
- nilnesserr
|
||||
- nilnil
|
||||
- noctx
|
||||
- rowserrcheck
|
||||
- sqlclosecheck
|
||||
- staticcheck
|
||||
- unconvert
|
||||
- wastedassign
|
||||
disable:
|
||||
- depguard
|
||||
- exhaustruct
|
||||
- gochecknoglobals
|
||||
- gochecknoinits
|
||||
- gomoddirectives
|
||||
- wrapcheck
|
||||
- cyclop
|
||||
- dupl
|
||||
- funlen
|
||||
- gocognit
|
||||
- gocyclo
|
||||
- ireturn
|
||||
- lll
|
||||
- mnd
|
||||
- nestif
|
||||
- nlreturn
|
||||
- noinlineerr
|
||||
- paralleltest
|
||||
- tagliatelle
|
||||
- testpackage
|
||||
- varnamelen
|
||||
- wsl_v5
|
||||
@@ -38,7 +38,7 @@ func Empty[T any]() Responder[T] {
|
||||
func Error[T any](logger mlogger.Logger, service mservice.Type, code codes.Code, hint string, err error) Responder[T] {
|
||||
return func(ctx context.Context) (*T, error) {
|
||||
fields := []zap.Field{
|
||||
zap.String("service", string(service)),
|
||||
zap.String("service", service),
|
||||
zap.String("status_code", code.String()),
|
||||
}
|
||||
if hint != "" {
|
||||
|
||||
@@ -24,12 +24,12 @@ func (e routerError) Error() string {
|
||||
return string(e)
|
||||
}
|
||||
|
||||
type routerErrorWithCause struct {
|
||||
type routerCauseError struct {
|
||||
message string
|
||||
cause error
|
||||
}
|
||||
|
||||
func (e *routerErrorWithCause) Error() string {
|
||||
func (e *routerCauseError) Error() string {
|
||||
if e == nil {
|
||||
return ""
|
||||
}
|
||||
@@ -39,7 +39,7 @@ func (e *routerErrorWithCause) Error() string {
|
||||
return e.message + ": " + e.cause.Error()
|
||||
}
|
||||
|
||||
func (e *routerErrorWithCause) Unwrap() error {
|
||||
func (e *routerCauseError) Unwrap() error {
|
||||
if e == nil {
|
||||
return nil
|
||||
}
|
||||
@@ -47,7 +47,7 @@ func (e *routerErrorWithCause) Unwrap() error {
|
||||
}
|
||||
|
||||
func newRouterErrorWithCause(message string, cause error) error {
|
||||
return &routerErrorWithCause{
|
||||
return &routerCauseError{
|
||||
message: message,
|
||||
cause: cause,
|
||||
}
|
||||
@@ -104,7 +104,7 @@ func NewRouter(logger mlogger.Logger, cfg *Config, opts *Options) (*Router, erro
|
||||
listener := opts.Listener
|
||||
var err error
|
||||
if listener == nil {
|
||||
listener, err = net.Listen(network, address)
|
||||
listener, err = (&net.ListenConfig{}).Listen(context.Background(), network, address)
|
||||
if err != nil {
|
||||
return nil, newRouterErrorWithCause(errMsgListenFailed, err)
|
||||
}
|
||||
@@ -120,9 +120,11 @@ func NewRouter(logger mlogger.Logger, cfg *Config, opts *Options) (*Router, erro
|
||||
serverOpts = append(serverOpts, grpc.MaxSendMsgSize(cfg.MaxSendMsgSize))
|
||||
}
|
||||
|
||||
if creds, err := configureTLS(cfg.TLS); err != nil {
|
||||
return nil, err
|
||||
} else if creds != nil {
|
||||
if cfg.TLS != nil {
|
||||
creds, err := configureTLS(cfg.TLS)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
serverOpts = append(serverOpts, grpc.Creds(creds))
|
||||
}
|
||||
|
||||
@@ -253,10 +255,6 @@ func (r *Router) Done() <-chan error {
|
||||
}
|
||||
|
||||
func configureTLS(cfg *TLSConfig) (credentials.TransportCredentials, error) {
|
||||
if cfg == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
if cfg.CertFile == "" || cfg.KeyFile == "" {
|
||||
return nil, errTLSMissingCertAndKey
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ func newBufferedListener(t *testing.T) *bufconn.Listener {
|
||||
|
||||
listener := bufconn.Listen(bufconnSize)
|
||||
t.Cleanup(func() {
|
||||
listener.Close()
|
||||
require.NoError(t, listener.Close())
|
||||
})
|
||||
|
||||
return listener
|
||||
|
||||
@@ -48,7 +48,7 @@ func (db *ProtectedDBImp[T]) enforce(ctx context.Context, action model.Action, o
|
||||
|
||||
func (db *ProtectedDBImp[T]) Create(ctx context.Context, accountRef, organizationRef bson.ObjectID, object T) error {
|
||||
db.DBImp.Logger.Debug("Attempting to create object", mzap.AccRef(accountRef),
|
||||
mzap.ObjRef("organization_ref", organizationRef), zap.String("collection", string(db.Collection)))
|
||||
mzap.ObjRef("organization_ref", organizationRef), zap.String("collection", db.Collection))
|
||||
|
||||
if object.GetPermissionRef() == bson.NilObjectID {
|
||||
object.SetPermissionRef(db.PermissionRef)
|
||||
@@ -61,12 +61,12 @@ func (db *ProtectedDBImp[T]) Create(ctx context.Context, accountRef, organizatio
|
||||
|
||||
if err := db.DBImp.Create(ctx, object); err != nil {
|
||||
db.DBImp.Logger.Warn("Failed to create object", zap.Error(err), mzap.AccRef(accountRef),
|
||||
mzap.ObjRef("organization_ref", organizationRef), zap.String("collection", string(db.Collection)))
|
||||
mzap.ObjRef("organization_ref", organizationRef), zap.String("collection", db.Collection))
|
||||
return err
|
||||
}
|
||||
|
||||
db.DBImp.Logger.Debug("Successfully created object", mzap.AccRef(accountRef),
|
||||
mzap.ObjRef("organization_ref", organizationRef), zap.String("collection", string(db.Collection)))
|
||||
mzap.ObjRef("organization_ref", organizationRef), zap.String("collection", db.Collection))
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -76,7 +76,7 @@ func (db *ProtectedDBImp[T]) InsertMany(ctx context.Context, accountRef, organiz
|
||||
}
|
||||
|
||||
db.DBImp.Logger.Debug("Attempting to insert many objects", mzap.AccRef(accountRef),
|
||||
mzap.ObjRef("organization_ref", organizationRef), zap.String("collection", string(db.Collection)),
|
||||
mzap.ObjRef("organization_ref", organizationRef), zap.String("collection", db.Collection),
|
||||
zap.Int("count", len(objects)))
|
||||
|
||||
// Set permission and organization refs for all objects and enforce permissions
|
||||
@@ -93,13 +93,13 @@ func (db *ProtectedDBImp[T]) InsertMany(ctx context.Context, accountRef, organiz
|
||||
|
||||
if err := db.DBImp.InsertMany(ctx, objects); err != nil {
|
||||
db.DBImp.Logger.Warn("Failed to insert many objects", zap.Error(err), mzap.AccRef(accountRef),
|
||||
mzap.ObjRef("organization_ref", organizationRef), zap.String("collection", string(db.Collection)),
|
||||
mzap.ObjRef("organization_ref", organizationRef), zap.String("collection", db.Collection),
|
||||
zap.Int("count", len(objects)))
|
||||
return err
|
||||
}
|
||||
|
||||
db.DBImp.Logger.Debug("Successfully inserted many objects", mzap.AccRef(accountRef),
|
||||
mzap.ObjRef("organization_ref", organizationRef), zap.String("collection", string(db.Collection)),
|
||||
mzap.ObjRef("organization_ref", organizationRef), zap.String("collection", db.Collection),
|
||||
zap.Int("count", len(objects)))
|
||||
return nil
|
||||
}
|
||||
@@ -127,7 +127,7 @@ func (db *ProtectedDBImp[T]) Get(ctx context.Context, accountRef, objectRef bson
|
||||
|
||||
if err := db.DBImp.Get(ctx, objectRef, result); err != nil {
|
||||
db.DBImp.Logger.Warn("Failed to get object", zap.Error(err), mzap.AccRef(accountRef),
|
||||
mzap.ObjRef("object_ref", objectRef), zap.String("collection", string(db.Collection)))
|
||||
mzap.ObjRef("object_ref", objectRef), zap.String("collection", db.Collection))
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -182,18 +182,18 @@ func (db *ProtectedDBImp[T]) ListIDs(
|
||||
query builder.Query,
|
||||
) ([]bson.ObjectID, error) {
|
||||
db.DBImp.Logger.Debug("Attempting to list object IDs",
|
||||
mzap.AccRef(accountRef), zap.String("collection", string(db.Collection)), zap.Any("filter", query.BuildQuery()))
|
||||
mzap.AccRef(accountRef), zap.String("collection", db.Collection), zap.Any("filter", query.BuildQuery()))
|
||||
|
||||
// 1. Fetch all candidate IDs from the underlying DB
|
||||
allIDs, err := db.DBImp.ListPermissionBound(ctx, query)
|
||||
if err != nil {
|
||||
db.DBImp.Logger.Warn("Failed to list object IDs", zap.Error(err), mzap.AccRef(accountRef),
|
||||
zap.String("collection", string(db.Collection)), zap.String("action", string(action)))
|
||||
zap.String("collection", db.Collection), zap.String("action", string(action)))
|
||||
return nil, err
|
||||
}
|
||||
if len(allIDs) == 0 {
|
||||
db.DBImp.Logger.Debug("No objects found matching filter", mzap.AccRef(accountRef),
|
||||
zap.String("collection", string(db.Collection)), zap.Any("filter", query.BuildQuery()))
|
||||
zap.String("collection", db.Collection), zap.Any("filter", query.BuildQuery()))
|
||||
return []bson.ObjectID{}, merrors.NoData(fmt.Sprintf("no %s found", db.Collection))
|
||||
}
|
||||
|
||||
@@ -203,12 +203,12 @@ func (db *ProtectedDBImp[T]) ListIDs(
|
||||
enforceErr := db.enforce(ctx, action, desc, accountRef, *desc.GetID())
|
||||
if enforceErr == nil {
|
||||
allowedIDs = append(allowedIDs, *desc.GetID())
|
||||
} else if !errors.Is(err, merrors.ErrAccessDenied) {
|
||||
} else if !errors.Is(enforceErr, merrors.ErrAccessDenied) {
|
||||
// If the error is something other than AccessDenied, we want to fail
|
||||
db.DBImp.Logger.Warn("Error while enforcing read permission", zap.Error(enforceErr),
|
||||
mzap.ObjRef("permission_ref", desc.GetPermissionRef()), zap.String("action", string(action)),
|
||||
mzap.AccRef(accountRef), mzap.ObjRef("organization_ref", desc.GetOrganizationRef()),
|
||||
mzap.ObjRef("object_ref", *desc.GetID()), zap.String("collection", string(db.Collection)),
|
||||
mzap.ObjRef("object_ref", *desc.GetID()), zap.String("collection", db.Collection),
|
||||
)
|
||||
return nil, enforceErr
|
||||
}
|
||||
@@ -217,7 +217,7 @@ func (db *ProtectedDBImp[T]) ListIDs(
|
||||
|
||||
db.DBImp.Logger.Debug("Successfully enforced read permission on IDs", zap.Int("fetched_count", len(allIDs)),
|
||||
zap.Int("allowed_count", len(allowedIDs)), mzap.AccRef(accountRef),
|
||||
zap.String("collection", string(db.Collection)), zap.String("action", string(action)))
|
||||
zap.String("collection", db.Collection), zap.String("action", string(action)))
|
||||
|
||||
// 3. Return only the IDs that passed permission checks
|
||||
return allowedIDs, nil
|
||||
@@ -249,7 +249,7 @@ func CreateDBImp[T model.PermissionBoundStorable](
|
||||
logger := l.Named("protected")
|
||||
var policy model.PolicyDescription
|
||||
if err := pdb.GetBuiltInPolicy(ctx, collection, &policy); err != nil {
|
||||
logger.Warn("Failed to fetch policy description", zap.Error(err), zap.String("resource_type", string(collection)))
|
||||
logger.Warn("Failed to fetch policy description", zap.Error(err), zap.String("resource_type", collection))
|
||||
return nil, err
|
||||
}
|
||||
p := &ProtectedDBImp[T]{
|
||||
@@ -261,7 +261,7 @@ func CreateDBImp[T model.PermissionBoundStorable](
|
||||
if err := p.DBImp.Repository.CreateIndex(&ri.Definition{
|
||||
Keys: []ri.Key{{Field: storable.OrganizationRefField, Sort: ri.Asc}},
|
||||
}); err != nil {
|
||||
logger.Warn("Failed to create index", zap.Error(err), zap.String("resource_type", string(collection)))
|
||||
logger.Warn("Failed to create index", zap.Error(err), zap.String("resource_type", collection))
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
||||
@@ -89,7 +89,7 @@ func (db *AccountBoundDBImp[T]) enforceInterface(ctx context.Context, action mod
|
||||
func (db *AccountBoundDBImp[T]) Create(ctx context.Context, accountRef bson.ObjectID, object T) error {
|
||||
orgRef := object.GetOrganizationRef()
|
||||
db.Logger.Debug("Attempting to create object", mzap.AccRef(accountRef),
|
||||
mzap.ObjRef("organization_ref", orgRef), zap.String("collection", string(db.Collection)))
|
||||
mzap.ObjRef("organization_ref", orgRef), zap.String("collection", db.Collection))
|
||||
|
||||
// Check organization update permission for create operations
|
||||
if err := db.enforce(ctx, model.ActionUpdate, object, accountRef); err != nil {
|
||||
@@ -98,12 +98,12 @@ func (db *AccountBoundDBImp[T]) Create(ctx context.Context, accountRef bson.Obje
|
||||
|
||||
if err := db.DBImp.Create(ctx, object); err != nil {
|
||||
db.Logger.Warn("Failed to create object", zap.Error(err), mzap.AccRef(accountRef),
|
||||
mzap.ObjRef("organization_ref", orgRef), zap.String("collection", string(db.Collection)))
|
||||
mzap.ObjRef("organization_ref", orgRef), zap.String("collection", db.Collection))
|
||||
return err
|
||||
}
|
||||
|
||||
db.Logger.Debug("Successfully created object", mzap.AccRef(accountRef),
|
||||
mzap.ObjRef("organization_ref", orgRef), zap.String("collection", string(db.Collection)))
|
||||
mzap.ObjRef("organization_ref", orgRef), zap.String("collection", db.Collection))
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -113,7 +113,7 @@ func (db *AccountBoundDBImp[T]) Get(ctx context.Context, accountRef, objectRef b
|
||||
// First get the object to check its organization
|
||||
if err := db.DBImp.Get(ctx, objectRef, result); err != nil {
|
||||
db.Logger.Warn("Failed to get object", zap.Error(err), mzap.AccRef(accountRef),
|
||||
mzap.ObjRef("object_ref", objectRef), zap.String("collection", string(db.Collection)))
|
||||
mzap.ObjRef("object_ref", objectRef), zap.String("collection", db.Collection))
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -123,7 +123,7 @@ func (db *AccountBoundDBImp[T]) Get(ctx context.Context, accountRef, objectRef b
|
||||
}
|
||||
|
||||
db.Logger.Debug("Successfully retrieved object", mzap.AccRef(accountRef),
|
||||
mzap.ObjRef("organization_ref", result.GetOrganizationRef()), zap.String("collection", string(db.Collection)))
|
||||
mzap.ObjRef("organization_ref", result.GetOrganizationRef()), zap.String("collection", db.Collection))
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -167,7 +167,7 @@ func (db *AccountBoundDBImp[T]) Patch(ctx context.Context, accountRef, objectRef
|
||||
|
||||
if err := db.DBImp.Patch(ctx, objectRef, patch); err != nil {
|
||||
db.Logger.Warn("Failed to patch object", zap.Error(err), mzap.AccRef(accountRef),
|
||||
mzap.ObjRef("object_ref", objectRef), zap.String("collection", string(db.Collection)))
|
||||
mzap.ObjRef("object_ref", objectRef), zap.String("collection", db.Collection))
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -195,7 +195,7 @@ func (db *AccountBoundDBImp[T]) Delete(ctx context.Context, accountRef, objectRe
|
||||
|
||||
if err := db.DBImp.Delete(ctx, objectRef); err != nil {
|
||||
db.Logger.Warn("Failed to delete object", zap.Error(err), mzap.AccRef(accountRef),
|
||||
mzap.ObjRef("object_ref", objectRef), zap.String("collection", string(db.Collection)))
|
||||
mzap.ObjRef("object_ref", objectRef), zap.String("collection", db.Collection))
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -204,7 +204,7 @@ func (db *AccountBoundDBImp[T]) Delete(ctx context.Context, accountRef, objectRe
|
||||
}
|
||||
|
||||
func (db *AccountBoundDBImp[T]) DeleteMany(ctx context.Context, accountRef bson.ObjectID, query builder.Query) error {
|
||||
db.Logger.Debug("Attempting to delete many objects", mzap.AccRef(accountRef), zap.String("collection", string(db.Collection)))
|
||||
db.Logger.Debug("Attempting to delete many objects", mzap.AccRef(accountRef), zap.String("collection", db.Collection))
|
||||
|
||||
// Get all candidate objects for batch permission checking
|
||||
allObjects, err := db.DBImp.Repository.ListPermissionBound(ctx, query)
|
||||
@@ -245,7 +245,7 @@ func (db *AccountBoundDBImp[T]) DeleteMany(ctx context.Context, accountRef bson.
|
||||
}
|
||||
|
||||
func (db *AccountBoundDBImp[T]) FindOne(ctx context.Context, accountRef bson.ObjectID, query builder.Query, result T) error {
|
||||
db.Logger.Debug("Attempting to find one object", mzap.AccRef(accountRef), zap.String("collection", string(db.Collection)))
|
||||
db.Logger.Debug("Attempting to find one object", mzap.AccRef(accountRef), zap.String("collection", db.Collection))
|
||||
|
||||
// For FindOne, we need to check read permission after finding the object
|
||||
if err := db.DBImp.FindOne(ctx, query, result); err != nil {
|
||||
@@ -264,7 +264,7 @@ func (db *AccountBoundDBImp[T]) FindOne(ctx context.Context, accountRef bson.Obj
|
||||
}
|
||||
|
||||
func (db *AccountBoundDBImp[T]) ListIDs(ctx context.Context, accountRef bson.ObjectID, query builder.Query) ([]bson.ObjectID, error) {
|
||||
db.Logger.Debug("Attempting to list object IDs", mzap.AccRef(accountRef), zap.String("collection", string(db.Collection)))
|
||||
db.Logger.Debug("Attempting to list object IDs", mzap.AccRef(accountRef), zap.String("collection", db.Collection))
|
||||
|
||||
// Get all candidate objects for batch permission checking
|
||||
allObjects, err := db.DBImp.Repository.ListPermissionBound(ctx, query)
|
||||
@@ -294,7 +294,7 @@ func (db *AccountBoundDBImp[T]) ListIDs(ctx context.Context, accountRef bson.Obj
|
||||
}
|
||||
|
||||
func (db *AccountBoundDBImp[T]) ListAccountBound(ctx context.Context, accountRef, organizationRef bson.ObjectID, query builder.Query) ([]model.AccountBoundStorable, error) {
|
||||
db.Logger.Debug("Attempting to list account bound objects", mzap.AccRef(accountRef), zap.String("collection", string(db.Collection)))
|
||||
db.Logger.Debug("Attempting to list account bound objects", mzap.AccRef(accountRef), zap.String("collection", db.Collection))
|
||||
|
||||
// Build query to find objects where accountRef matches OR is null/absent
|
||||
accountQuery := repository.WithOrg(accountRef, organizationRef)
|
||||
|
||||
@@ -6,7 +6,6 @@ import (
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/tech/sendico/pkg/merrors"
|
||||
"github.com/tech/sendico/pkg/mlogger"
|
||||
"github.com/tech/sendico/pkg/model"
|
||||
"go.mongodb.org/mongo-driver/v2/bson"
|
||||
"go.uber.org/zap"
|
||||
@@ -14,7 +13,7 @@ import (
|
||||
|
||||
// TestAccountBoundDBImp_Enforce tests the enforce method
|
||||
func TestAccountBoundDBImp_Enforce(t *testing.T) {
|
||||
logger := mlogger.Logger(zap.NewNop())
|
||||
logger := zap.NewNop()
|
||||
db := &AccountBoundDBImp[model.AccountBoundStorable]{
|
||||
Logger: logger,
|
||||
PermissionRef: bson.NewObjectID(),
|
||||
@@ -34,13 +33,13 @@ func TestAccountBoundDBImp_Enforce(t *testing.T) {
|
||||
|
||||
t.Run("CollectionSet", func(t *testing.T) {
|
||||
// Test that Collection is properly set
|
||||
assert.Equal(t, "test_collection", string(db.Collection))
|
||||
assert.Equal(t, "test_collection", db.Collection)
|
||||
})
|
||||
}
|
||||
|
||||
// TestAccountBoundDBImp_InterfaceCompliance tests that the struct implements required interfaces
|
||||
func TestAccountBoundDBImp_InterfaceCompliance(t *testing.T) {
|
||||
logger := mlogger.Logger(zap.NewNop())
|
||||
logger := zap.NewNop()
|
||||
db := &AccountBoundDBImp[model.AccountBoundStorable]{
|
||||
Logger: logger,
|
||||
PermissionRef: bson.NewObjectID(),
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
package casbin
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/tech/sendico/pkg/merrors"
|
||||
"github.com/tech/sendico/pkg/model"
|
||||
)
|
||||
|
||||
func stringToAction(actionStr string) (model.Action, error) {
|
||||
switch actionStr {
|
||||
case string(model.ActionCreate):
|
||||
return model.ActionCreate, nil
|
||||
case string(model.ActionRead):
|
||||
return model.ActionRead, nil
|
||||
case string(model.ActionUpdate):
|
||||
return model.ActionUpdate, nil
|
||||
case string(model.ActionDelete):
|
||||
return model.ActionDelete, nil
|
||||
default:
|
||||
return "", merrors.InvalidArgument(fmt.Sprintf("invalid action: %s", actionStr), "action")
|
||||
}
|
||||
}
|
||||
@@ -80,9 +80,10 @@ func getEnvBoolValue(logger mlogger.Logger, varName, envVarName string, value *b
|
||||
|
||||
if envValue != nil {
|
||||
envStr := os.Getenv(*envValue)
|
||||
if envStr == "true" || envStr == "1" {
|
||||
switch envStr {
|
||||
case "true", "1":
|
||||
return true
|
||||
} else if envStr == "false" || envStr == "0" {
|
||||
case "false", "0":
|
||||
return false
|
||||
}
|
||||
logger.Warn("Invalid environment variable value for boolean", zap.String("environment_variable", envVarName), zap.String("value", envStr))
|
||||
|
||||
@@ -116,7 +116,7 @@ func NewPoliciesDB(logger mlogger.Logger, db *mongo.Database) (*PermissionsDBImp
|
||||
{Field: "policy.objectRef", Sort: ri.Asc},
|
||||
},
|
||||
}
|
||||
if err := p.DBImp.Repository.CreateIndex(policiesQueryIndex); err != nil {
|
||||
if err := p.Repository.CreateIndex(policiesQueryIndex); err != nil {
|
||||
p.Logger.Warn("Failed to prepare policies query index", zap.Error(err))
|
||||
return nil, err
|
||||
}
|
||||
@@ -127,7 +127,7 @@ func NewPoliciesDB(logger mlogger.Logger, db *mongo.Database) (*PermissionsDBImp
|
||||
{Field: "policy.effect.action", Sort: ri.Asc},
|
||||
},
|
||||
}
|
||||
if err := p.DBImp.Repository.CreateIndex(roleBasedQueriesIndex); err != nil {
|
||||
if err := p.Repository.CreateIndex(roleBasedQueriesIndex); err != nil {
|
||||
p.Logger.Warn("Failed to prepare role based query index", zap.Error(err))
|
||||
return nil, err
|
||||
}
|
||||
@@ -142,7 +142,7 @@ func NewPoliciesDB(logger mlogger.Logger, db *mongo.Database) (*PermissionsDBImp
|
||||
},
|
||||
Unique: true,
|
||||
}
|
||||
if err := p.DBImp.Repository.CreateIndex(uniquePolicyConstaint); err != nil {
|
||||
if err := p.Repository.CreateIndex(uniquePolicyConstaint); err != nil {
|
||||
p.Logger.Warn("Failed to unique policy assignment index", zap.Error(err))
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -68,14 +68,14 @@ func NewRolesDB(logger mlogger.Logger, db *mongo.Database) (*RolesDBImp, error)
|
||||
DBImp: *template.Create[*nstructures.RoleAssignment](logger, "role_assignments", db),
|
||||
}
|
||||
|
||||
if err := p.DBImp.Repository.CreateIndex(&ri.Definition{
|
||||
if err := p.Repository.CreateIndex(&ri.Definition{
|
||||
Keys: []ri.Key{{Field: "role.organizationRef", Sort: ri.Asc}},
|
||||
}); err != nil {
|
||||
p.Logger.Warn("Failed to prepare venue index", zap.Error(err))
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := p.DBImp.Repository.CreateIndex(&ri.Definition{
|
||||
if err := p.Repository.CreateIndex(&ri.Definition{
|
||||
Keys: []ri.Key{{Field: "role.descriptionRef", Sort: ri.Asc}},
|
||||
}); err != nil {
|
||||
p.Logger.Warn("Failed to prepare role description index", zap.Error(err))
|
||||
@@ -90,7 +90,7 @@ func NewRolesDB(logger mlogger.Logger, db *mongo.Database) (*RolesDBImp, error)
|
||||
},
|
||||
Unique: true,
|
||||
}
|
||||
if err := p.DBImp.Repository.CreateIndex(uniqueRoleConstaint); err != nil {
|
||||
if err := p.Repository.CreateIndex(uniqueRoleConstaint); err != nil {
|
||||
p.Logger.Warn("Failed to prepare role assignment index", zap.Error(err))
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -215,14 +215,14 @@ func createTestRoleAssignment(roleRef, accountRef, organizationRef bson.ObjectID
|
||||
}
|
||||
}
|
||||
|
||||
func createTestPolicyAssignment(roleRef bson.ObjectID, action model.Action, effect model.Effect, organizationRef, descriptionRef bson.ObjectID, objectRef *bson.ObjectID) nstructures.PolicyAssignment {
|
||||
func createTestPolicyAssignment(roleRef bson.ObjectID, effect model.Effect, organizationRef, descriptionRef bson.ObjectID, objectRef *bson.ObjectID) nstructures.PolicyAssignment {
|
||||
return nstructures.PolicyAssignment{
|
||||
Policy: model.Policy{
|
||||
OrganizationRef: organizationRef,
|
||||
DescriptionRef: descriptionRef,
|
||||
ObjectRef: objectRef,
|
||||
Effect: model.ActionEffect{
|
||||
Action: action,
|
||||
Action: model.ActionRead,
|
||||
Effect: effect,
|
||||
},
|
||||
},
|
||||
@@ -259,7 +259,7 @@ func TestEnforcer_Enforce(t *testing.T) {
|
||||
mockRDB.On("Roles", ctx, accountRef, organizationRef).Return([]nstructures.RoleAssignment{roleAssignment}, nil)
|
||||
|
||||
// Mock policy assignment with ALLOW effect
|
||||
policyAssignment := createTestPolicyAssignment(roleRef, model.ActionRead, model.EffectAllow, organizationRef, permissionRef, &objectRef)
|
||||
policyAssignment := createTestPolicyAssignment(roleRef, model.EffectAllow, organizationRef, permissionRef, &objectRef)
|
||||
mockPDB.On("PoliciesForPermissionAction", ctx, roleRef, permissionRef, model.ActionRead).Return([]nstructures.PolicyAssignment{policyAssignment}, nil)
|
||||
|
||||
// Create enforcer
|
||||
@@ -284,7 +284,7 @@ func TestEnforcer_Enforce(t *testing.T) {
|
||||
mockRDB.On("Roles", ctx, accountRef, organizationRef).Return([]nstructures.RoleAssignment{roleAssignment}, nil)
|
||||
|
||||
// Mock policy assignment with DENY effect
|
||||
policyAssignment := createTestPolicyAssignment(roleRef, model.ActionRead, model.EffectDeny, organizationRef, permissionRef, &objectRef)
|
||||
policyAssignment := createTestPolicyAssignment(roleRef, model.EffectDeny, organizationRef, permissionRef, &objectRef)
|
||||
mockPDB.On("PoliciesForPermissionAction", ctx, roleRef, permissionRef, model.ActionRead).Return([]nstructures.PolicyAssignment{policyAssignment}, nil)
|
||||
|
||||
enforcer := createTestEnforcer(mockPDB, mockRDB)
|
||||
@@ -312,11 +312,11 @@ func TestEnforcer_Enforce(t *testing.T) {
|
||||
mockRDB.On("Roles", ctx, accountRef, organizationRef).Return([]nstructures.RoleAssignment{roleAssignment1, roleAssignment2}, nil)
|
||||
|
||||
// First role has ALLOW policy
|
||||
allowPolicy := createTestPolicyAssignment(role1Ref, model.ActionRead, model.EffectAllow, organizationRef, permissionRef, &objectRef)
|
||||
allowPolicy := createTestPolicyAssignment(role1Ref, model.EffectAllow, organizationRef, permissionRef, &objectRef)
|
||||
mockPDB.On("PoliciesForPermissionAction", ctx, role1Ref, permissionRef, model.ActionRead).Return([]nstructures.PolicyAssignment{allowPolicy}, nil)
|
||||
|
||||
// Second role has DENY policy - should take precedence
|
||||
denyPolicy := createTestPolicyAssignment(role2Ref, model.ActionRead, model.EffectDeny, organizationRef, permissionRef, &objectRef)
|
||||
denyPolicy := createTestPolicyAssignment(role2Ref, model.EffectDeny, organizationRef, permissionRef, &objectRef)
|
||||
mockPDB.On("PoliciesForPermissionAction", ctx, role2Ref, permissionRef, model.ActionRead).Return([]nstructures.PolicyAssignment{denyPolicy}, nil)
|
||||
|
||||
enforcer := createTestEnforcer(mockPDB, mockRDB)
|
||||
@@ -445,7 +445,7 @@ func TestEnforcer_Enforce(t *testing.T) {
|
||||
mockRDB.On("Roles", ctx, accountRef, organizationRef).Return([]nstructures.RoleAssignment{roleAssignment}, nil)
|
||||
|
||||
// Mock corrupted policy with invalid effect
|
||||
corruptedPolicy := createTestPolicyAssignment(roleRef, model.ActionRead, "invalid_effect", organizationRef, permissionRef, &objectRef)
|
||||
corruptedPolicy := createTestPolicyAssignment(roleRef, "invalid_effect", organizationRef, permissionRef, &objectRef)
|
||||
mockPDB.On("PoliciesForPermissionAction", ctx, roleRef, permissionRef, model.ActionRead).Return([]nstructures.PolicyAssignment{corruptedPolicy}, nil)
|
||||
|
||||
enforcer := createTestEnforcer(mockPDB, mockRDB)
|
||||
@@ -539,7 +539,7 @@ func TestEnforcer_EnforceBatch(t *testing.T) {
|
||||
mockRDB.On("Roles", ctx, accountRef, organizationRef).Return([]nstructures.RoleAssignment{roleAssignment}, nil)
|
||||
|
||||
// Mock policy assignment with ALLOW effect
|
||||
policyAssignment := createTestPolicyAssignment(roleRef, model.ActionRead, model.EffectAllow, organizationRef, permissionRef, nil)
|
||||
policyAssignment := createTestPolicyAssignment(roleRef, model.EffectAllow, organizationRef, permissionRef, nil)
|
||||
mockPDB.On("PoliciesForRoles", ctx, []bson.ObjectID{roleRef}, model.ActionRead).Return([]nstructures.PolicyAssignment{policyAssignment}, nil)
|
||||
|
||||
enforcer := createTestEnforcer(mockPDB, mockRDB)
|
||||
@@ -664,7 +664,7 @@ func TestEnforcer_GetPermissions(t *testing.T) {
|
||||
mockRDB.On("Roles", ctx, accountRef, organizationRef).Return([]nstructures.RoleAssignment{roleAssignment}, nil)
|
||||
|
||||
// Mock policy assignment
|
||||
policyAssignment := createTestPolicyAssignment(roleRef, model.ActionRead, model.EffectAllow, organizationRef, createTestObjectID(), nil)
|
||||
policyAssignment := createTestPolicyAssignment(roleRef, model.EffectAllow, organizationRef, createTestObjectID(), nil)
|
||||
mockPDB.On("PoliciesForRole", ctx, roleRef).Return([]nstructures.PolicyAssignment{policyAssignment}, nil)
|
||||
|
||||
enforcer := createTestEnforcer(mockPDB, mockRDB)
|
||||
@@ -702,8 +702,8 @@ func TestEnforcer_SecurityScenarios(t *testing.T) {
|
||||
mockRDB.On("Roles", ctx, accountRef, organizationRef).Return([]nstructures.RoleAssignment{roleAssignment}, nil)
|
||||
|
||||
// Mock multiple policies: both ALLOW and DENY
|
||||
allowPolicy := createTestPolicyAssignment(roleRef, model.ActionRead, model.EffectAllow, organizationRef, permissionRef, &objectRef)
|
||||
denyPolicy := createTestPolicyAssignment(roleRef, model.ActionRead, model.EffectDeny, organizationRef, permissionRef, &objectRef)
|
||||
allowPolicy := createTestPolicyAssignment(roleRef, model.EffectAllow, organizationRef, permissionRef, &objectRef)
|
||||
denyPolicy := createTestPolicyAssignment(roleRef, model.EffectDeny, organizationRef, permissionRef, &objectRef)
|
||||
mockPDB.On("PoliciesForPermissionAction", ctx, roleRef, permissionRef, model.ActionRead).Return([]nstructures.PolicyAssignment{allowPolicy, denyPolicy}, nil)
|
||||
|
||||
enforcer := createTestEnforcer(mockPDB, mockRDB)
|
||||
|
||||
@@ -31,16 +31,10 @@ func (c *MongoConnection) Database() *mongo.Database {
|
||||
}
|
||||
|
||||
func (c *MongoConnection) Disconnect(ctx context.Context) error {
|
||||
if ctx == nil {
|
||||
ctx = context.Background()
|
||||
}
|
||||
return c.client.Disconnect(ctx)
|
||||
}
|
||||
|
||||
func (c *MongoConnection) Ping(ctx context.Context) error {
|
||||
if ctx == nil {
|
||||
ctx = context.Background()
|
||||
}
|
||||
return c.client.Ping(ctx, readpref.Primary())
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ func Create(logger mlogger.Logger, db *mongo.Database) (*AccountDB, error) {
|
||||
DBImp: *template.Create[*model.Account](logger, mservice.Accounts, db),
|
||||
}
|
||||
|
||||
if err := p.DBImp.Repository.CreateIndex(&ri.Definition{
|
||||
if err := p.Repository.CreateIndex(&ri.Definition{
|
||||
Keys: []ri.Key{{Field: "login", Sort: ri.Asc}},
|
||||
Unique: true,
|
||||
}); err != nil {
|
||||
|
||||
@@ -14,5 +14,5 @@ func (db *ChainAssetsDB) Resolve(ctx context.Context, chainAsset model.ChainAsse
|
||||
repository.Query().Filter(assetField.Dot("chain"), chainAsset.Chain),
|
||||
repository.Query().Filter(assetField.Dot("tokenSymbol"), chainAsset.TokenSymbol),
|
||||
)
|
||||
return &assetDescription, db.DBImp.FindOne(ctx, q, &assetDescription)
|
||||
return &assetDescription, db.FindOne(ctx, q, &assetDescription)
|
||||
}
|
||||
|
||||
@@ -81,7 +81,7 @@ type computeImp struct {
|
||||
|
||||
func (a *computeImp) Build() any {
|
||||
return bson.D{
|
||||
{Key: string(a.field.Build()), Value: a.expression.Build()},
|
||||
{Key: a.field.Build(), Value: a.expression.Build()},
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -101,7 +101,9 @@ func (r *MongoRepository) executeQuery(ctx context.Context, queryFunc QueryFunc,
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer cursor.Close(ctx)
|
||||
defer func() {
|
||||
_ = cursor.Close(ctx)
|
||||
}()
|
||||
|
||||
for cursor.Next(ctx) {
|
||||
if err = decoder(cursor); err != nil {
|
||||
@@ -165,7 +167,9 @@ func (r *MongoRepository) ListIDs(ctx context.Context, query builder.Query) ([]b
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer cursor.Close(ctx)
|
||||
defer func() {
|
||||
_ = cursor.Close(ctx)
|
||||
}()
|
||||
|
||||
var ids []bson.ObjectID
|
||||
for cursor.Next(ctx) {
|
||||
@@ -196,7 +200,9 @@ func (r *MongoRepository) ListPermissionBound(ctx context.Context, query builder
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer cursor.Close(ctx)
|
||||
defer func() {
|
||||
_ = cursor.Close(ctx)
|
||||
}()
|
||||
|
||||
result := make([]model.PermissionBoundStorable, 0)
|
||||
|
||||
@@ -226,7 +232,9 @@ func (r *MongoRepository) ListAccountBound(ctx context.Context, query builder.Qu
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer cursor.Close(ctx)
|
||||
defer func() {
|
||||
_ = cursor.Close(ctx)
|
||||
}()
|
||||
|
||||
result := make([]model.AccountBoundStorable, 0)
|
||||
|
||||
|
||||
@@ -45,7 +45,8 @@ func NewMongoTimeSeriesCollection(ctx context.Context, db *mongo.Database, tsOpt
|
||||
}
|
||||
|
||||
if err := db.CreateCollection(ctx, tsOpts.Collection, collOpts); err != nil {
|
||||
if cmdErr, ok := err.(mongo.CommandError); !ok || cmdErr.Code != 48 {
|
||||
var cmdErr mongo.CommandError
|
||||
if !errors.As(err, &cmdErr) || cmdErr.Code != 48 {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
@@ -86,7 +87,9 @@ func (ts *TimeSeries) executeQuery(ctx context.Context, decoder rdecoder.Decodin
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer cursor.Close(ctx)
|
||||
defer func() {
|
||||
_ = cursor.Close(ctx)
|
||||
}()
|
||||
|
||||
for cursor.Next(ctx) {
|
||||
if err := cursor.Err(); err != nil {
|
||||
|
||||
@@ -71,7 +71,7 @@ func (db *verificationDB) Consume(
|
||||
zap.String("account_ref", accountRefHex),
|
||||
)
|
||||
var direct model.VerificationToken
|
||||
err := db.DBImp.FindOne(ctx, magicFilter, &direct)
|
||||
err := db.FindOne(ctx, magicFilter, &direct)
|
||||
switch {
|
||||
case err == nil:
|
||||
token = &direct
|
||||
@@ -118,7 +118,7 @@ func (db *verificationDB) Consume(
|
||||
zap.Any("scope_filter", scopeFilter.BuildQuery()),
|
||||
)
|
||||
tokens, err := mutil.GetObjects[model.VerificationToken](
|
||||
ctx, db.Logger, scopeFilter, nil, db.DBImp.Repository,
|
||||
ctx, db.Logger, scopeFilter, nil, db.Repository,
|
||||
)
|
||||
if err != nil {
|
||||
if errors.Is(err, merrors.ErrNoData) {
|
||||
@@ -182,7 +182,7 @@ func (db *verificationDB) Consume(
|
||||
zap.String("account_ref", accountRefHex),
|
||||
)
|
||||
|
||||
incremented, patchErr := db.DBImp.PatchMany(
|
||||
incremented, patchErr := db.PatchMany(
|
||||
ctx,
|
||||
activeFilter,
|
||||
repository.Patch().Inc(repository.Field("attempts"), 1),
|
||||
@@ -272,7 +272,7 @@ func (db *verificationDB) Consume(
|
||||
mzap.StorableRef(token),
|
||||
)
|
||||
|
||||
updated, err := db.DBImp.PatchMany(
|
||||
updated, err := db.PatchMany(
|
||||
ctx,
|
||||
consumeFilter,
|
||||
repository.Patch().Set(repository.Field("usedAt"), now),
|
||||
@@ -309,7 +309,7 @@ func (db *verificationDB) Consume(
|
||||
}
|
||||
|
||||
// 5) Consume failed → increment attempts
|
||||
incremented, incrementErr := db.DBImp.PatchMany(
|
||||
incremented, incrementErr := db.PatchMany(
|
||||
ctx,
|
||||
repository.IDFilter(token.ID),
|
||||
repository.Patch().Inc(repository.Field("attempts"), 1),
|
||||
@@ -335,7 +335,7 @@ func (db *verificationDB) Consume(
|
||||
|
||||
// 6) Re-check state
|
||||
var fresh model.VerificationToken
|
||||
if err := db.DBImp.FindOne(ctx, repository.IDFilter(token.ID), &fresh); err != nil {
|
||||
if err := db.FindOne(ctx, repository.IDFilter(token.ID), &fresh); err != nil {
|
||||
db.Logger.Warn("Verification consume failed to re-check token state",
|
||||
zap.String("purpose", string(purpose)),
|
||||
zap.Bool("account_scoped", accountScoped),
|
||||
|
||||
@@ -166,22 +166,22 @@ func (db *verificationDB) Create(
|
||||
// Optional idempotency key support for safe retries.
|
||||
if hasIdempotency {
|
||||
var sameToken model.VerificationToken
|
||||
err := db.DBImp.FindOne(tx, hashFilter(token.VerifyTokenHash), &sameToken)
|
||||
err := db.FindOne(tx, hashFilter(token.VerifyTokenHash), &sameToken)
|
||||
switch {
|
||||
case err == nil:
|
||||
// Same hash means the same Create operation already succeeded.
|
||||
return nil, nil
|
||||
return struct{}{}, nil
|
||||
case errors.Is(err, merrors.ErrNoData):
|
||||
default:
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var existing model.VerificationToken
|
||||
err = db.DBImp.FindOne(tx, idempotencyFilter(request, idempotencyKey), &existing)
|
||||
err = db.FindOne(tx, idempotencyFilter(request, idempotencyKey), &existing)
|
||||
switch {
|
||||
case err == nil:
|
||||
// Existing request with the same idempotency scope has already succeeded.
|
||||
return nil, nil
|
||||
return struct{}{}, nil
|
||||
case errors.Is(err, merrors.ErrNoData):
|
||||
default:
|
||||
return nil, err
|
||||
@@ -193,7 +193,7 @@ func (db *verificationDB) Create(
|
||||
cutoff := now.Add(-*request.Cooldown)
|
||||
|
||||
var recent model.VerificationToken
|
||||
err := db.DBImp.FindOne(tx, cooldownActiveContextFilter(request, now, cutoff), &recent)
|
||||
err := db.FindOne(tx, cooldownActiveContextFilter(request, now, cutoff), &recent)
|
||||
switch {
|
||||
case err == nil:
|
||||
return nil, verification.ErrorCooldownActive()
|
||||
@@ -204,7 +204,7 @@ func (db *verificationDB) Create(
|
||||
}
|
||||
|
||||
// 2) Invalidate active tokens for this context
|
||||
if _, err := db.DBImp.PatchMany(
|
||||
if _, err := db.PatchMany(
|
||||
tx,
|
||||
activeFilter,
|
||||
repository.Patch().Set(repository.Field("usedAt"), now),
|
||||
@@ -216,20 +216,20 @@ func (db *verificationDB) Create(
|
||||
if err := db.DBImp.Create(tx, token); err != nil {
|
||||
if hasIdempotency && errors.Is(err, merrors.ErrDataConflict) {
|
||||
var sameToken model.VerificationToken
|
||||
findErr := db.DBImp.FindOne(tx, hashFilter(token.VerifyTokenHash), &sameToken)
|
||||
findErr := db.FindOne(tx, hashFilter(token.VerifyTokenHash), &sameToken)
|
||||
switch {
|
||||
case findErr == nil:
|
||||
return nil, nil
|
||||
return struct{}{}, nil
|
||||
case errors.Is(findErr, merrors.ErrNoData):
|
||||
default:
|
||||
return nil, findErr
|
||||
}
|
||||
|
||||
var existing model.VerificationToken
|
||||
findErr = db.DBImp.FindOne(tx, idempotencyFilter(request, idempotencyKey), &existing)
|
||||
findErr = db.FindOne(tx, idempotencyFilter(request, idempotencyKey), &existing)
|
||||
switch {
|
||||
case findErr == nil:
|
||||
return nil, nil
|
||||
return struct{}{}, nil
|
||||
case errors.Is(findErr, merrors.ErrNoData):
|
||||
default:
|
||||
return nil, findErr
|
||||
@@ -237,7 +237,7 @@ func (db *verificationDB) Create(
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
return nil, nil
|
||||
return struct{}{}, nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
|
||||
@@ -211,7 +211,7 @@ func (m *memoryTokenRepository) InsertMany(ctx context.Context, objs []storable.
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (m *memoryTokenRepository) FindManyByFilter(_ context.Context, query builder.Query, decoder rd.DecodingFunc) error {
|
||||
func (m *memoryTokenRepository) FindManyByFilter(ctx context.Context, query builder.Query, decoder rd.DecodingFunc) error {
|
||||
m.mu.Lock()
|
||||
var matches []interface{}
|
||||
for _, id := range m.order {
|
||||
@@ -231,9 +231,11 @@ func (m *memoryTokenRepository) FindManyByFilter(_ context.Context, query builde
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer cur.Close(context.Background())
|
||||
defer func() {
|
||||
_ = cur.Close(ctx)
|
||||
}()
|
||||
|
||||
for cur.Next(context.Background()) {
|
||||
for cur.Next(ctx) {
|
||||
if err := decoder(cur); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -3,8 +3,8 @@ package discovery
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
messaging "github.com/tech/sendico/pkg/messaging/envelope"
|
||||
"github.com/tech/sendico/pkg/merrors"
|
||||
messaging "github.com/tech/sendico/pkg/messaging/envelope"
|
||||
"github.com/tech/sendico/pkg/model"
|
||||
)
|
||||
|
||||
@@ -21,7 +21,7 @@ func (e *jsonEnvelope) Serialize() ([]byte, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return e.Envelope.Wrap(data)
|
||||
return e.Wrap(data)
|
||||
}
|
||||
|
||||
func newEnvelope(sender string, event model.NotificationEvent, payload any) messaging.Envelope {
|
||||
|
||||
@@ -137,7 +137,6 @@ func (s *RegistryService) Start() {
|
||||
}
|
||||
s.logInfo("Discovery registry service starting", fields...)
|
||||
for _, ch := range s.consumers {
|
||||
ch := ch
|
||||
go func() {
|
||||
if err := ch.consumer.ConsumeMessages(ch.handler); err != nil {
|
||||
s.logger.Warn("Discovery consumer stopped with error", zap.String("event", ch.event), zap.Error(err))
|
||||
|
||||
@@ -11,6 +11,7 @@ func TestBuildSafePublishableNATSURL(t *testing.T) {
|
||||
t.Run("redacts single URL credentials", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
//nolint:gosec // Test fixture includes credentials to verify redaction logic.
|
||||
raw := "nats://alice:supersecret@localhost:4222"
|
||||
sanitized := buildSafePublishableNATSURL(raw)
|
||||
|
||||
@@ -25,6 +26,7 @@ func TestBuildSafePublishableNATSURL(t *testing.T) {
|
||||
t.Run("redacts credentials in gateway URL format", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
//nolint:gosec // Test fixture includes credentials to verify redaction logic.
|
||||
raw := "nats://dev_nats:nats_password_123@dev-nats:4222"
|
||||
sanitized := buildSafePublishableNATSURL(raw)
|
||||
|
||||
@@ -49,6 +51,7 @@ func TestBuildSafePublishableNATSURL(t *testing.T) {
|
||||
t.Run("redacts each URL in server list", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
//nolint:gosec // Test fixture includes credentials to verify redaction logic.
|
||||
raw := " nats://alice:one@localhost:4222, nats://bob:two@localhost:4223 "
|
||||
sanitized := buildSafePublishableNATSURL(raw)
|
||||
|
||||
@@ -73,6 +76,7 @@ func TestBuildSafePublishableNATSURL(t *testing.T) {
|
||||
t.Run("redacts malformed URL credentials via fallback", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
//nolint:gosec // Test fixture includes credentials to verify redaction logic.
|
||||
raw := "nats://alice:pa%ss@localhost:4222"
|
||||
sanitized := buildSafePublishableNATSURL(raw)
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ func (acn *AccountNotification) Serialize() ([]byte, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return acn.Envelope.Wrap(data)
|
||||
return acn.Wrap(data)
|
||||
}
|
||||
|
||||
func NewAccountNotification(action nm.NotificationAction) model.NotificationEvent {
|
||||
|
||||
@@ -24,7 +24,7 @@ func (prn *PasswordResetNotification) Serialize() ([]byte, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return prn.Envelope.Wrap(data)
|
||||
return prn.Wrap(data)
|
||||
}
|
||||
|
||||
func NewPasswordResetNotification(action nm.NotificationAction) model.NotificationEvent {
|
||||
|
||||
@@ -27,7 +27,7 @@ func (ccn *ConfirmationCodeNotification) Serialize() ([]byte, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ccn.Envelope.Wrap(data)
|
||||
return ccn.Wrap(data)
|
||||
}
|
||||
|
||||
func newConfirmationEvent(action nm.NotificationAction) model.NotificationEvent {
|
||||
|
||||
@@ -20,7 +20,7 @@ func (crn *ConfirmationRequestNotification) Serialize() ([]byte, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return crn.Envelope.Wrap(data)
|
||||
return crn.Wrap(data)
|
||||
}
|
||||
|
||||
type ConfirmationResultNotification struct {
|
||||
@@ -33,7 +33,7 @@ func (crn *ConfirmationResultNotification) Serialize() ([]byte, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return crn.Envelope.Wrap(data)
|
||||
return crn.Wrap(data)
|
||||
}
|
||||
|
||||
type ConfirmationDispatchNotification struct {
|
||||
@@ -46,7 +46,7 @@ func (cdn *ConfirmationDispatchNotification) Serialize() ([]byte, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return cdn.Envelope.Wrap(data)
|
||||
return cdn.Wrap(data)
|
||||
}
|
||||
|
||||
func confirmationRequestEvent() model.NotificationEvent {
|
||||
|
||||
@@ -29,7 +29,7 @@ func (nrn *NResultNotification) Serialize() ([]byte, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return nrn.Envelope.Wrap(data)
|
||||
return nrn.Wrap(data)
|
||||
}
|
||||
|
||||
func NewNRNotification() model.NotificationEvent {
|
||||
|
||||
@@ -24,7 +24,7 @@ func (acn *ObjectNotification) Serialize() ([]byte, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return acn.Envelope.Wrap(data)
|
||||
return acn.Wrap(data)
|
||||
}
|
||||
|
||||
func NewObjectNotification(t mservice.Type, action nm.NotificationAction) model.NotificationEvent {
|
||||
|
||||
@@ -19,7 +19,7 @@ func (pgn *PaymentGatewayIntentNotification) Serialize() ([]byte, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return pgn.Envelope.Wrap(data)
|
||||
return pgn.Wrap(data)
|
||||
}
|
||||
|
||||
type PaymentGatewayExecutionNotification struct {
|
||||
@@ -32,7 +32,7 @@ func (pgn *PaymentGatewayExecutionNotification) Serialize() ([]byte, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return pgn.Envelope.Wrap(data)
|
||||
return pgn.Wrap(data)
|
||||
}
|
||||
|
||||
func intentEvent() model.NotificationEvent {
|
||||
|
||||
@@ -20,7 +20,7 @@ func (psn *PaymentStatusUpdatedNotification) Serialize() ([]byte, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return psn.Envelope.Wrap(data)
|
||||
return psn.Wrap(data)
|
||||
}
|
||||
|
||||
func paymentStatusUpdatedEvent() model.NotificationEvent {
|
||||
|
||||
@@ -74,7 +74,7 @@ func (srn *SiteRequestNotification) Serialize() ([]byte, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return srn.Envelope.Wrap(data)
|
||||
return srn.Wrap(data)
|
||||
}
|
||||
|
||||
func newSiteRequestEvent() model.NotificationEvent {
|
||||
|
||||
@@ -19,7 +19,7 @@ func (trn *TelegramReactionNotification) Serialize() ([]byte, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return trn.Envelope.Wrap(data)
|
||||
return trn.Wrap(data)
|
||||
}
|
||||
|
||||
func telegramReactionEvent() model.NotificationEvent {
|
||||
@@ -36,7 +36,7 @@ func (ttn *TelegramTextNotification) Serialize() ([]byte, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ttn.Envelope.Wrap(data)
|
||||
return ttn.Wrap(data)
|
||||
}
|
||||
|
||||
func telegramTextEvent() model.NotificationEvent {
|
||||
@@ -53,7 +53,7 @@ func (tun *TelegramUpdateNotification) Serialize() ([]byte, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return tun.Envelope.Wrap(data)
|
||||
return tun.Wrap(data)
|
||||
}
|
||||
|
||||
func telegramUpdateEvent() model.NotificationEvent {
|
||||
|
||||
@@ -13,9 +13,8 @@ func TestChainAssetDescriptionImplementsStorable(t *testing.T) {
|
||||
|
||||
func TestChainAssetDescriptionCollection(t *testing.T) {
|
||||
var desc ChainAssetDescription
|
||||
want := string(mservice.ChainAssets)
|
||||
want := mservice.ChainAssets
|
||||
if got := desc.Collection(); got != want {
|
||||
t.Fatalf("Collection() = %q, want %q", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ func (ne *NotificationEventImp) ToString() string {
|
||||
}
|
||||
|
||||
func (ne *NotificationEventImp) StringType() string {
|
||||
return string(ne.nType)
|
||||
return ne.nType
|
||||
}
|
||||
|
||||
func (ne *NotificationEventImp) StringAction() string {
|
||||
|
||||
@@ -44,7 +44,7 @@ func (ne *NotificationEventImp) ToString() string {
|
||||
}
|
||||
|
||||
func (ne *NotificationEventImp) StringType() string {
|
||||
return string(ne.nType)
|
||||
return ne.nType
|
||||
}
|
||||
|
||||
func (ne *NotificationEventImp) StringAction() string {
|
||||
|
||||
@@ -62,13 +62,13 @@ const (
|
||||
)
|
||||
|
||||
func StringToSType(s string) (Type, error) {
|
||||
switch Type(s) {
|
||||
switch s {
|
||||
case Accounts, Verification, Amplitude, Site, Changes, Clients, ChainGateway, ChainWallets, WalletRoutes, ChainWalletBalances,
|
||||
ChainTransfers, ChainDeposits, Callbacks, MntxGateway, PaymentGateway, FXOracle, FeePlans, BillingDocuments, FilterProjects, Invitations, Invoices, Logo, Ledger,
|
||||
LedgerAccounts, LedgerBalances, LedgerEntries, LedgerOutbox, LedgerParties, LedgerPlines, Notifications,
|
||||
Organizations, Payments, PaymentRoutes, PaymentOrchestrator, PaymentMethods, Permissions, Policies, PolicyAssignements,
|
||||
Recipients, RefreshTokens, Roles, Storage, Tenants, Workflows, Discovery, ChSettle:
|
||||
return Type(s), nil
|
||||
return s, nil
|
||||
default:
|
||||
return "", merrors.InvalidArgument("invalid service type", s)
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ func CloseFile(logger mlogger.Logger, file *os.File) {
|
||||
}
|
||||
|
||||
func ReadFile(logger mlogger.Logger, filePath string) ([]byte, error) {
|
||||
//nolint:gosec // Read path is provided by trusted caller configuration.
|
||||
file, err := os.Open(filePath)
|
||||
if err != nil {
|
||||
logger.Warn("Failed to open file", zap.String("path", filePath), zap.Error(err))
|
||||
|
||||
@@ -49,7 +49,11 @@ func SendAPIRequest(ctx context.Context, logger mlogger.Logger, httpMethod api.H
|
||||
logger.Warn("Failed to execute request", zap.Error(err), zap.String("method", method), zap.String("url", url), zap.Any("payload", payload))
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
defer func() {
|
||||
if closeErr := resp.Body.Close(); closeErr != nil {
|
||||
logger.Warn("Failed to close response body", zap.Error(closeErr), zap.String("method", method), zap.String("url", url))
|
||||
}
|
||||
}()
|
||||
|
||||
// Read the sresponse body
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
// Returns the reordered slice with updated indices, or an error if indices are invalid
|
||||
func IndexableRefs(items []model.IndexableRef, oldIndex, newIndex int) ([]model.IndexableRef, error) {
|
||||
// Find the item to reorder
|
||||
var targetIndex int = -1
|
||||
targetIndex := -1
|
||||
for i, item := range items {
|
||||
if item.Index == oldIndex {
|
||||
targetIndex = i
|
||||
|
||||
@@ -156,8 +156,9 @@ func (a *App[T]) Start() error {
|
||||
}
|
||||
|
||||
a.metricsSrv = &http.Server{
|
||||
Addr: addr,
|
||||
Handler: router,
|
||||
Addr: addr,
|
||||
Handler: router,
|
||||
ReadHeaderTimeout: 5 * time.Second,
|
||||
}
|
||||
go func() {
|
||||
a.logger.Info("Prometheus metrics server starting", zap.String("address", addr))
|
||||
@@ -185,7 +186,7 @@ func (a *App[T]) Start() error {
|
||||
}
|
||||
a.logger.Debug("GRPC services registered")
|
||||
|
||||
a.runCtx, a.cancel = context.WithCancel(context.Background())
|
||||
a.runCtx, a.cancel = context.WithCancel(context.Background()) //nolint:gosec // Cancellation func is retained on app state and invoked on Shutdown.
|
||||
a.logger.Debug("GRPC server context initialised")
|
||||
|
||||
if err := a.grpc.Start(a.runCtx); err != nil {
|
||||
@@ -219,9 +220,6 @@ func (a *App[T]) Start() error {
|
||||
}
|
||||
|
||||
func (a *App[T]) Shutdown(ctx context.Context) {
|
||||
if ctx == nil {
|
||||
ctx = context.Background()
|
||||
}
|
||||
if a.cancel != nil {
|
||||
a.cancel()
|
||||
}
|
||||
|
||||
@@ -30,11 +30,15 @@ func prepareLogger() mlogger.Logger {
|
||||
func RunServer(rootLoggerName string, av version.Printer, factory server.ServerFactoryT) {
|
||||
logger := prepareLogger().Named(rootLoggerName)
|
||||
logger = logger.With(zap.String("instance_id", discovery.InstanceID()))
|
||||
defer logger.Sync()
|
||||
defer func() {
|
||||
_ = logger.Sync()
|
||||
}()
|
||||
|
||||
// Show version information
|
||||
if *versionFlag {
|
||||
fmt.Fprintln(os.Stdout, av.Print())
|
||||
if _, err := fmt.Fprintln(os.Stdout, av.Print()); err != nil {
|
||||
logger.Warn("Failed to print version", zap.Error(err))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -161,6 +161,7 @@ func resolveToken(config Config) (string, string, error) {
|
||||
}
|
||||
}
|
||||
if tokenFilePath != "" {
|
||||
//nolint:gosec // Token file path comes from trusted deployment configuration.
|
||||
raw, err := os.ReadFile(tokenFilePath)
|
||||
if err != nil {
|
||||
return "", "", merrors.Internal("vault kv: failed to read token file " + tokenFilePath + ": " + err.Error())
|
||||
|
||||
Reference in New Issue
Block a user