mirror of
https://github.com/safedep/pmg.git
synced 2026-08-03 07:24:09 +02:00
164 lines
4.5 KiB
Go
164 lines
4.5 KiB
Go
package interceptors
|
|
|
|
import (
|
|
"sync"
|
|
"time"
|
|
|
|
"github.com/safedep/pmg/analyzer"
|
|
)
|
|
|
|
// CooldownBlock records a package blocked by the dependency cooldown policy.
|
|
type CooldownBlock struct {
|
|
Name string
|
|
Version string
|
|
PublishDate time.Time
|
|
DaysAgo int
|
|
DaysLeft int
|
|
CooldownDays int
|
|
}
|
|
|
|
// AnalysisStats contains aggregated statistics from analysis results
|
|
type AnalysisStats struct {
|
|
TotalAnalyzed int
|
|
AllowedCount int
|
|
ConfirmedCount int
|
|
BlockedCount int
|
|
UserCancelledCount int
|
|
CooldownBlockedCount int
|
|
}
|
|
|
|
// AnalysisStatsCollector tracks analysis statistics during proxy execution.
|
|
// It is separate from the cache to allow different cache implementations
|
|
// without coupling them to reporting concerns.
|
|
type AnalysisStatsCollector struct {
|
|
mu sync.RWMutex
|
|
stats AnalysisStats
|
|
blockedPackages []*analyzer.PackageVersionAnalysisResult
|
|
confirmedPackages []*analyzer.PackageVersionAnalysisResult
|
|
cooldownBlocks []CooldownBlock
|
|
}
|
|
|
|
// NewAnalysisStatsCollector creates a new stats collector
|
|
func NewAnalysisStatsCollector() *AnalysisStatsCollector {
|
|
return &AnalysisStatsCollector{}
|
|
}
|
|
|
|
// RecordAllowed records a package that was allowed (safe)
|
|
func (c *AnalysisStatsCollector) RecordAllowed(result *analyzer.PackageVersionAnalysisResult) {
|
|
if result == nil {
|
|
return
|
|
}
|
|
|
|
c.mu.Lock()
|
|
defer c.mu.Unlock()
|
|
|
|
c.stats.TotalAnalyzed++
|
|
c.stats.AllowedCount++
|
|
}
|
|
|
|
// RecordBlocked records a package that was automatically blocked (ActionBlock)
|
|
func (c *AnalysisStatsCollector) RecordBlocked(result *analyzer.PackageVersionAnalysisResult) {
|
|
if result == nil {
|
|
return
|
|
}
|
|
|
|
c.mu.Lock()
|
|
defer c.mu.Unlock()
|
|
|
|
c.stats.TotalAnalyzed++
|
|
c.stats.BlockedCount++
|
|
c.blockedPackages = append(c.blockedPackages, result)
|
|
}
|
|
|
|
// RecordUserCancelled records a package that was blocked because user declined confirmation (ActionConfirm declined)
|
|
func (c *AnalysisStatsCollector) RecordUserCancelled(result *analyzer.PackageVersionAnalysisResult) {
|
|
if result == nil {
|
|
return
|
|
}
|
|
|
|
c.mu.Lock()
|
|
defer c.mu.Unlock()
|
|
|
|
c.stats.TotalAnalyzed++
|
|
c.stats.UserCancelledCount++
|
|
|
|
// User cancelled packages are counted as blocked as well
|
|
c.stats.BlockedCount++
|
|
|
|
c.blockedPackages = append(c.blockedPackages, result)
|
|
}
|
|
|
|
// RecordConfirmed records a package where user confirmed installation despite warning
|
|
func (c *AnalysisStatsCollector) RecordConfirmed(result *analyzer.PackageVersionAnalysisResult) {
|
|
if result == nil {
|
|
return
|
|
}
|
|
|
|
c.mu.Lock()
|
|
defer c.mu.Unlock()
|
|
|
|
c.stats.TotalAnalyzed++
|
|
c.stats.ConfirmedCount++
|
|
c.confirmedPackages = append(c.confirmedPackages, result)
|
|
}
|
|
|
|
// GetStats returns the current statistics
|
|
func (c *AnalysisStatsCollector) GetStats() AnalysisStats {
|
|
c.mu.RLock()
|
|
defer c.mu.RUnlock()
|
|
|
|
return c.stats
|
|
}
|
|
|
|
// GetBlockedPackages returns all blocked packages
|
|
func (c *AnalysisStatsCollector) GetBlockedPackages() []*analyzer.PackageVersionAnalysisResult {
|
|
c.mu.RLock()
|
|
defer c.mu.RUnlock()
|
|
|
|
// Return a copy to avoid race conditions
|
|
result := make([]*analyzer.PackageVersionAnalysisResult, len(c.blockedPackages))
|
|
copy(result, c.blockedPackages)
|
|
return result
|
|
}
|
|
|
|
// GetConfirmedPackages returns all confirmed packages
|
|
func (c *AnalysisStatsCollector) GetConfirmedPackages() []*analyzer.PackageVersionAnalysisResult {
|
|
c.mu.RLock()
|
|
defer c.mu.RUnlock()
|
|
|
|
// Return a copy to avoid race conditions
|
|
result := make([]*analyzer.PackageVersionAnalysisResult, len(c.confirmedPackages))
|
|
copy(result, c.confirmedPackages)
|
|
return result
|
|
}
|
|
|
|
// RecordCooldownBlocked records a package blocked by the dependency cooldown policy.
|
|
// It increments both the cooldown-specific counter and the overall BlockedCount so that
|
|
// inferOutcome correctly treats cooldown-only sessions as OutcomeBlocked.
|
|
func (c *AnalysisStatsCollector) RecordCooldownBlocked(name, version string, publishDate time.Time, daysAgo, daysLeft, cooldownDays int) {
|
|
c.mu.Lock()
|
|
defer c.mu.Unlock()
|
|
|
|
c.stats.TotalAnalyzed++
|
|
c.stats.BlockedCount++
|
|
c.stats.CooldownBlockedCount++
|
|
c.cooldownBlocks = append(c.cooldownBlocks, CooldownBlock{
|
|
Name: name,
|
|
Version: version,
|
|
PublishDate: publishDate,
|
|
DaysAgo: daysAgo,
|
|
DaysLeft: daysLeft,
|
|
CooldownDays: cooldownDays,
|
|
})
|
|
}
|
|
|
|
// GetCooldownBlocks returns all packages blocked by the cooldown policy.
|
|
func (c *AnalysisStatsCollector) GetCooldownBlocks() []CooldownBlock {
|
|
c.mu.RLock()
|
|
defer c.mu.RUnlock()
|
|
|
|
result := make([]CooldownBlock, len(c.cooldownBlocks))
|
|
copy(result, c.cooldownBlocks)
|
|
return result
|
|
}
|