This commit is contained in:
Stephan D
2026-03-10 12:31:09 +01:00
parent d87e709f43
commit e77d1ab793
287 changed files with 2089 additions and 1550 deletions

47
api/pkg/.golangci.yml Normal file
View 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

View File

@@ -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 != "" {

View File

@@ -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
}

View File

@@ -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

View File

@@ -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
}

View File

@@ -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)

View File

@@ -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(),

View File

@@ -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")
}
}

View File

@@ -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))

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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)

View File

@@ -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())
}

View File

@@ -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 {

View File

@@ -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)
}

View File

@@ -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()},
}
}

View File

@@ -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)

View File

@@ -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 {

View File

@@ -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),

View File

@@ -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 {

View File

@@ -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
}

View File

@@ -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 {

View File

@@ -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))

View File

@@ -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)

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -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)
}
}

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -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)
}

View File

@@ -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))

View File

@@ -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)

View File

@@ -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

View File

@@ -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()
}

View File

@@ -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
}

View File

@@ -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())