package dehub import ( "dehub.dev/src/dehub.git/accessctl" "dehub.dev/src/dehub.git/fs" "dehub.dev/src/dehub.git/sigcred" "errors" "fmt" yaml "gopkg.in/yaml.v2" ) // Account represents a single account defined in the Config. type Account struct { ID string `yaml:"id"` Signifiers []sigcred.Signifier `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 (r *Repo) 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 repo, or directly // from the filesystem if there is no HEAD yet. func (r *Repo) LoadConfig() (Config, error) { headFS, err := r.headFS() if err != nil { return Config{}, fmt.Errorf("error retrieving repo HEAD: %w", err) } return r.loadConfig(headFS) } func (r *Repo) signifierForCredential(fs fs.FS, cred sigcred.Credential) (sigcred.SignifierInterface, error) { cfg, err := r.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, sig := range account.Signifiers { if sigInt, err := sig.Interface(cred.AccountID); err != nil { return nil, fmt.Errorf("error converting signifier index:%d to inteface: %w", i, err) } else if ok, err := sigInt.Signed(fs, cred); err != nil { return nil, fmt.Errorf("error checking if signfier index:%d signed credential: %w", i, err) } else if ok { return sigInt, nil } } return nil, errors.New("no signifier found for credential") }