package dehub import ( "errors" "fmt" "dehub.dev/src/dehub.git/accessctl" "dehub.dev/src/dehub.git/fs" "dehub.dev/src/dehub.git/sigcred" yaml "gopkg.in/yaml.v2" ) // Account represents a single account defined in the Config. type Account struct { ID string `yaml:"id"` Signifiers []sigcred.SignifierUnion `yaml:"signifiers"` Meta map[string]string `yaml:"meta,omitempty"` } // Config represents the structure of the main dehub configuration file, and is // used to marshal/unmarshal the yaml file. type Config struct { Accounts []Account `yaml:"accounts"` AccessControls []accessctl.AccessControl `yaml:"access_controls"` } func (proj *Project) loadConfig(fs fs.FS) (Config, error) { rc, err := fs.Open(ConfigPath) if err != nil { return Config{}, fmt.Errorf("could not open config.yml: %w", err) } defer rc.Close() var cfg Config if err := yaml.NewDecoder(rc).Decode(&cfg); err != nil { return cfg, fmt.Errorf("could not decode config.yml: %w", err) } // older config versions also had access_controls be an array, but not using // the action field. So filter out array elements without the action field. acl := cfg.AccessControls cfg.AccessControls = cfg.AccessControls[:0] for _, ac := range acl { if ac.Action == "" { continue } cfg.AccessControls = append(cfg.AccessControls, ac) } // TODO validate Config return cfg, nil } // LoadConfig loads the Config object from the HEAD of the project's git repo, // or directly from the filesystem if there is no HEAD yet. func (proj *Project) LoadConfig() (Config, error) { headFS, err := proj.headFS() if err != nil { return Config{}, fmt.Errorf("error retrieving repo HEAD: %w", err) } return proj.loadConfig(headFS) } func (proj *Project) signifierForCredential(fs fs.FS, cred sigcred.CredentialUnion) (sigcred.Signifier, error) { cfg, err := proj.loadConfig(fs) if err != nil { return nil, fmt.Errorf("error loading config: %w", err) } var account Account var ok bool for _, account = range cfg.Accounts { if account.ID == cred.AccountID { ok = true break } } if !ok { return nil, fmt.Errorf("no account object for account id %q present in config", cred.AccountID) } for i, sigUn := range account.Signifiers { sig := sigUn.Signifier(cred.AccountID) if ok, err := sig.Signed(fs, cred); err != nil { return nil, fmt.Errorf("error checking if signfier index:%d signed credential: %w", i, err) } else if ok { return sig, nil } } return nil, errors.New("no signifier found for credential") }