203 lines
3.6 KiB
Go
203 lines
3.6 KiB
Go
// ©AngelaMos | 2026
|
|
// config.go
|
|
|
|
package config
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
|
|
"github.com/pelletier/go-toml/v2"
|
|
)
|
|
|
|
const DefaultConfigFile = ".portia.toml"
|
|
|
|
type Config struct {
|
|
Rules RulesConfig `toml:"rules"`
|
|
Scan ScanConfig `toml:"scan"`
|
|
Output OutputConfig `toml:"output"`
|
|
HIBP HIBPConfig `toml:"hibp"`
|
|
Allowlist AllowlistConfig `toml:"allowlist"`
|
|
}
|
|
|
|
type RulesConfig struct {
|
|
Disable []string `toml:"disable"`
|
|
Enable []string `toml:"enable"`
|
|
}
|
|
|
|
type ScanConfig struct {
|
|
MaxFileSize int64 `toml:"max_file_size"`
|
|
Excludes []string `toml:"excludes"`
|
|
Depth int `toml:"depth"`
|
|
Since string `toml:"since"`
|
|
}
|
|
|
|
type OutputConfig struct {
|
|
Format string `toml:"format"`
|
|
Verbose bool `toml:"verbose"`
|
|
NoColor bool `toml:"no_color"`
|
|
}
|
|
|
|
type HIBPConfig struct {
|
|
Enabled bool `toml:"enabled"`
|
|
}
|
|
|
|
type AllowlistConfig struct {
|
|
Paths []string `toml:"paths"`
|
|
Values []string `toml:"values"`
|
|
Stopwords []string `toml:"stopwords"`
|
|
}
|
|
|
|
func Load(path string) (*Config, error) {
|
|
cfg := &Config{
|
|
Scan: ScanConfig{
|
|
MaxFileSize: 1 << 20,
|
|
},
|
|
Output: OutputConfig{
|
|
Format: "terminal",
|
|
},
|
|
}
|
|
|
|
if path == "" {
|
|
path = findConfig()
|
|
}
|
|
|
|
if path == "" {
|
|
if pyCfg, ok := loadFromPyproject(); ok {
|
|
return pyCfg, nil
|
|
}
|
|
return cfg, nil
|
|
}
|
|
|
|
data, err := os.ReadFile(path) //nolint:gosec
|
|
if err != nil {
|
|
if os.IsNotExist(err) {
|
|
return cfg, nil
|
|
}
|
|
return nil, err
|
|
}
|
|
|
|
if err := toml.Unmarshal(data, cfg); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return cfg, nil
|
|
}
|
|
|
|
type pyprojectWrapper struct {
|
|
Tool struct {
|
|
Portia Config `toml:"portia"`
|
|
} `toml:"tool"`
|
|
}
|
|
|
|
func loadFromPyproject() (*Config, bool) {
|
|
data, err := os.ReadFile("pyproject.toml")
|
|
if err != nil {
|
|
return nil, false
|
|
}
|
|
|
|
var wrapper pyprojectWrapper
|
|
if err := toml.Unmarshal(data, &wrapper); err != nil {
|
|
return nil, false
|
|
}
|
|
|
|
cfg := wrapper.Tool.Portia
|
|
if cfg.Output.Format == "" && !cfg.Output.Verbose &&
|
|
!cfg.Output.NoColor && !cfg.HIBP.Enabled &&
|
|
len(cfg.Rules.Disable) == 0 && len(cfg.Scan.Excludes) == 0 {
|
|
return nil, false
|
|
}
|
|
|
|
if cfg.Scan.MaxFileSize == 0 {
|
|
cfg.Scan.MaxFileSize = 1 << 20
|
|
}
|
|
if cfg.Output.Format == "" {
|
|
cfg.Output.Format = "terminal"
|
|
}
|
|
|
|
return &cfg, true
|
|
}
|
|
|
|
func findConfig() string {
|
|
candidates := []string{
|
|
DefaultConfigFile,
|
|
filepath.Join(".portia", "config.toml"),
|
|
}
|
|
|
|
for _, c := range candidates {
|
|
if _, err := os.Stat(c); err == nil {
|
|
return c
|
|
}
|
|
}
|
|
|
|
home, err := os.UserHomeDir()
|
|
if err == nil {
|
|
global := filepath.Join(home, ".config", "portia", "config.toml")
|
|
if _, err := os.Stat(global); err == nil {
|
|
return global
|
|
}
|
|
}
|
|
|
|
return ""
|
|
}
|
|
|
|
func PyprojectTemplate(name string) string {
|
|
return fmt.Sprintf(`[project]
|
|
name = "%s"
|
|
version = "0.1.0"
|
|
description = ""
|
|
requires-python = ">=3.13"
|
|
dependencies = []
|
|
|
|
[tool.portia]
|
|
# [tool.portia.rules]
|
|
# disable = ["generic-password"]
|
|
|
|
# [tool.portia.scan]
|
|
# max_file_size = 1048576
|
|
# excludes = ["*.test.js", "fixtures/"]
|
|
|
|
# [tool.portia.output]
|
|
# format = "terminal"
|
|
# verbose = false
|
|
# no_color = false
|
|
|
|
# [tool.portia.hibp]
|
|
# enabled = false
|
|
|
|
# [tool.portia.allowlist]
|
|
# paths = ["test/fixtures/"]
|
|
# values = ["my_test_value"]
|
|
# stopwords = ["mycompany"]
|
|
`, name)
|
|
}
|
|
|
|
func DefaultTemplate() string {
|
|
return `# ©AngelaMos | 2026
|
|
# .portia.toml
|
|
|
|
[rules]
|
|
# disable = ["generic-password"]
|
|
|
|
[scan]
|
|
max_file_size = 1048576
|
|
# excludes = ["*.test.js", "fixtures/"]
|
|
# depth = 0
|
|
# since = ""
|
|
|
|
[output]
|
|
format = "terminal"
|
|
verbose = false
|
|
no_color = false
|
|
|
|
[hibp]
|
|
enabled = false
|
|
|
|
[allowlist]
|
|
# paths = ["test/fixtures/"]
|
|
# values = ["my_test_value"]
|
|
# stopwords = ["mycompany"]
|
|
`
|
|
}
|