A read-only clone of the dehub project, for until dehub.dev can be brought back online.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

94 lines
2.5 KiB

package dehub
import (
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 == "" {
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
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")