feat(api): RequireAuth+RequireProjectAccess middleware, IDOR-scope check/apply по projectID

This commit is contained in:
2026-07-03 20:47:40 +07:00
parent 35ffe73ae3
commit 4533b0ca25
16 changed files with 498 additions and 143 deletions
+9 -7
View File
@@ -21,7 +21,7 @@ type DomainRef struct {
}
type Loader interface {
LoadDomain(ctx context.Context, domainID uuid.UUID) (DomainRef, error)
LoadDomain(ctx context.Context, projectID, domainID uuid.UUID) (DomainRef, error)
}
type Recorder interface {
@@ -45,8 +45,10 @@ func New(loader Loader, rec Recorder, reg *registry.Registry, cipher *crypto.Cip
}
// resolve loads the domain, its provider and decrypted credentials, and computes the diff.
func (s *DomainService) resolve(ctx context.Context, domainID uuid.UUID) (provider.Provider, provider.Credentials, DomainRef, diff.Changeset, error) {
ref, err := s.loader.LoadDomain(ctx, domainID)
// projectID scopes the lookup so a domainID belonging to another tenant's
// project can never be resolved here (closes IDOR).
func (s *DomainService) resolve(ctx context.Context, projectID, domainID uuid.UUID) (provider.Provider, provider.Credentials, DomainRef, diff.Changeset, error) {
ref, err := s.loader.LoadDomain(ctx, projectID, domainID)
if err != nil {
return nil, provider.Credentials{}, ref, diff.Changeset{}, err
}
@@ -68,8 +70,8 @@ func (s *DomainService) resolve(ctx context.Context, domainID uuid.UUID) (provid
}
// Check computes and records the diff between template and zone.
func (s *DomainService) Check(ctx context.Context, domainID uuid.UUID) (diff.Changeset, error) {
_, _, _, cs, err := s.resolve(ctx, domainID)
func (s *DomainService) Check(ctx context.Context, projectID, domainID uuid.UUID) (diff.Changeset, error) {
_, _, _, cs, err := s.resolve(ctx, projectID, domainID)
if err != nil {
return diff.Changeset{}, err
}
@@ -80,8 +82,8 @@ func (s *DomainService) Check(ctx context.Context, domainID uuid.UUID) (diff.Cha
}
// Apply applies updates always (when ApplyUpdates) and prunes only when ApplyPrunes.
func (s *DomainService) Apply(ctx context.Context, domainID uuid.UUID, req ApplyRequest) (diff.Changeset, error) {
p, creds, ref, cs, err := s.resolve(ctx, domainID)
func (s *DomainService) Apply(ctx context.Context, projectID, domainID uuid.UUID, req ApplyRequest) (diff.Changeset, error) {
p, creds, ref, cs, err := s.resolve(ctx, projectID, domainID)
if err != nil {
return diff.Changeset{}, err
}