Bootstrap copied BFF and local accounts with public Sendico contracts (#34)
This commit is contained in:
1 parent
67dc5b5b1e
commit
7062672a87
556 files changed
+42291
-777
No files matched your search
@@ -0,0 +1,71 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"git.sendico.io/tech/sxchnge/bff/pkg/merrors"
|
||||
"git.sendico.io/tech/sxchnge/bff/pkg/model"
|
||||
"git.sendico.io/tech/sxchnge/bff/pkg/mservice"
|
||||
"go.mongodb.org/mongo-driver/v2/bson"
|
||||
)
|
||||
|
||||
// ScopedAccessParams bundles everything needed to authorize an action against a
|
||||
// resource that follows the personal-vs-org ownership model.
|
||||
//
|
||||
// It is deliberately a plain struct (not an interface over a model) so it works
|
||||
// both for locally-stored objects and for objects whose ownership is learned
|
||||
// from a downstream service response.
|
||||
type ScopedAccessParams struct {
|
||||
// Service is the resource type, used only to build the access-denied error.
|
||||
Service mservice.Type
|
||||
// PolicyRef is the org policy consulted when the object is org-owned.
|
||||
PolicyRef bson.ObjectID
|
||||
// CallerRef is the subject taken from the auth token. Never from the request body.
|
||||
CallerRef bson.ObjectID
|
||||
// OrgRef is the organization the object belongs to. For org-owned objects
|
||||
// caller membership in it is checked before policy enforcement. Personal
|
||||
// objects are deliberately exempt from the membership check so the owner
|
||||
// keeps access after leaving the organization; membership for personal
|
||||
// objects is enforced once, at create time (see ScopedDBImp.Create).
|
||||
OrgRef bson.ObjectID
|
||||
// ObjectRef is the concrete object being accessed. Passing it enables
|
||||
// object-level checks in the Enforcer; use bson.NilObjectID for scope-only.
|
||||
ObjectRef bson.ObjectID
|
||||
// OwnerKind / OwnerRef describe the object's actual ownership, read FROM the
|
||||
// object — not derived from the request.
|
||||
OwnerKind model.OwnerKind
|
||||
OwnerRef bson.ObjectID
|
||||
// Action is the operation being authorized.
|
||||
Action model.Action
|
||||
}
|
||||
|
||||
// enforceOwnershipAccess decides access based on ownership and policy only.
|
||||
// It does NOT check organization membership — the caller must verify membership
|
||||
// before invoking this. Use ScopedAuthorizer.Authorize for the full
|
||||
// membership-aware access check.
|
||||
//
|
||||
// - personal (OwnerKindAccount): allowed iff OwnerRef == CallerRef.
|
||||
// - org (OwnerKindOrganization): allowed iff the Enforcer grants Action within OrgRef.
|
||||
// - anything else: denied by default.
|
||||
func enforceOwnershipAccess(ctx context.Context, enf Enforcer, p ScopedAccessParams) error {
|
||||
switch p.OwnerKind {
|
||||
case model.OwnerKindAccount:
|
||||
if p.OwnerRef == p.CallerRef {
|
||||
return nil
|
||||
}
|
||||
return merrors.AccessDenied(p.Service, string(p.Action), p.ObjectRef)
|
||||
|
||||
case model.OwnerKindOrganization:
|
||||
ok, err := enf.Enforce(ctx, p.PolicyRef, p.CallerRef, p.OrgRef, p.ObjectRef, p.Action)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !ok {
|
||||
return merrors.AccessDenied(p.Service, string(p.Action), p.ObjectRef)
|
||||
}
|
||||
return nil
|
||||
|
||||
default:
|
||||
return merrors.AccessDenied(p.Service, string(p.Action), p.ObjectRef)
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user