package backend import ( "encoding/json" "errors" "fmt" "git.faercol.me/faercol/polyculeconnect/polyculeconnect/connector" "github.com/dexidp/dex/connector/oidc" "github.com/dexidp/dex/storage" ) var ErrUnsupportedType = errors.New("unsupported connector type") type BackendConfig struct { ID string Name string Issuer string ClientID string ClientSecret string RedirectURI string } func (bc *BackendConfig) OIDC() oidc.Config { return oidc.Config{ Issuer: bc.Issuer, ClientID: bc.ClientID, ClientSecret: bc.ClientSecret, RedirectURI: bc.RedirectURI, } } func (bc *BackendConfig) Storage() (storage.Connector, error) { oidcJSON, err := json.Marshal(bc.OIDC()) if err != nil { return storage.Connector{}, fmt.Errorf("failed to serialize oidc config: %w", err) } return storage.Connector{ ID: bc.ID, Type: "oidc", Name: bc.Name, Config: oidcJSON, }, nil } func (bc *BackendConfig) FromConnector(connector storage.Connector) error { var oidc oidc.Config if connector.Type != "oidc" { return ErrUnsupportedType } if err := json.Unmarshal(connector.Config, &oidc); err != nil { return fmt.Errorf("invalid OIDC config: %w", err) } bc.ID = connector.ID bc.Name = connector.Name bc.ClientID = oidc.ClientID bc.ClientSecret = oidc.ClientSecret bc.Issuer = oidc.Issuer bc.RedirectURI = oidc.RedirectURI return nil } type Service interface { ListBackends() ([]BackendConfig, error) GetBackend(id string) (BackendConfig, error) AddBackend(config BackendConfig) error RemoveBackend(id string) error } type concreteBackendService struct { s storage.Storage } func (cbs *concreteBackendService) ListBackends() ([]BackendConfig, error) { connectors, err := cbs.s.ListConnectors() if err != nil { return nil, fmt.Errorf("failed to get connectors from storage: %w", err) } var res []BackendConfig for _, c := range connectors { // We know that this type is special, we don't want to use it at all here if c.Type == connector.TypeRefuseAll { continue } var b BackendConfig if err := b.FromConnector(c); err != nil { return res, err } res = append(res, b) } return res, nil } func (cbs *concreteBackendService) GetBackend(connectorID string) (BackendConfig, error) { c, err := cbs.s.GetConnector(connectorID) if err != nil { return BackendConfig{}, fmt.Errorf("failed to get connector from storage: %w", err) } var res BackendConfig if err := res.FromConnector(c); err != nil { return BackendConfig{}, err } return res, nil } func (cbs *concreteBackendService) AddBackend(config BackendConfig) error { storageConf, err := config.Storage() if err != nil { return fmt.Errorf("failed to create storage configuration: %w", err) } return cbs.s.CreateConnector(storageConf) } func (cbs *concreteBackendService) RemoveBackend(connectorID string) error { return cbs.s.DeleteConnector(connectorID) } func New(s storage.Storage) Service { return &concreteBackendService{s} }