package store import ( "context" "atlas9.dev/c/core" "atlas9.dev/c/core/dbi" "atlas9.dev/c/demo/lib" "atlas9.dev/c/demo/lib/sso" ) type SqliteSsoStore struct { db dbi.DBI guard lib.Guard } // GetByDomain implements [sso.Store]. func (s *SqliteSsoStore) GetByDomain(ctx context.Context, tenant, domain core.ID) (*sso.Config, error) { // TODO guard var c sso.Config err := dbi.Get(ctx, s.db, &c, ` SELECT id, c.tenant as tenant, name, client_id, client_secret, issuer_url, jwks_url, auth_url, device_auth_url, token_url FROM sso_configs c JOIN sso_domain_owners o ON c.id = o.config AND c.tenant = o.tenant WHERE o.tenant = $1 AND o.domain = $2 `, tenant, domain) return &c, err } // SetDomainOwner implements [sso.Store]. func (s *SqliteSsoStore) SetDomainOwner(ctx context.Context, tenant core.ID, domain core.ID, config core.ID) error { // TODO guard _, err := s.db.Exec(ctx, ` INSERT INTO sso_domain_owners (tenant, domain, config) VALUES ($1, $2, $3) `, tenant, domain, config) return err } var _ sso.Store = (*SqliteSsoStore)(nil) func NewSqliteSsoStore(db dbi.DBI, guard lib.Guard) *SqliteSsoStore { return &SqliteSsoStore{db: db, guard: guard} } func (s *SqliteSsoStore) Save(ctx context.Context, c *sso.Config) error { if err := s.guard.Check(ctx, sso.Cap_Sso_Write, c.Tenant, ""); err != nil { return err } _, err := s.db.Exec(ctx, ` INSERT INTO sso_configs (id, tenant, name, client_id, client_secret, issuer_url, jwks_url, auth_url, device_auth_url, token_url) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10) ON CONFLICT (id) DO UPDATE SET tenant = excluded.tenant, name = excluded.name, client_id = excluded.client_id, client_secret = excluded.client_secret, issuer_url = excluded.issuer_url, jwks_url = excluded.jwks_url, auth_url = excluded.auth_url, device_auth_url = excluded.device_auth_url, token_url = excluded.token_url `, c.ID, c.Tenant, c.Name, c.ClientID, c.ClientSecret, c.IssuerUrl, c.JwksUrl, c.AuthUrl, c.DeviceAuthUrl, c.TokenUrl) return err } func (s *SqliteSsoStore) Get(ctx context.Context, tenant core.ID, id core.ID) (*sso.Config, error) { if err := s.guard.Check(ctx, sso.Cap_Sso_Read, tenant, ""); err != nil { return nil, err } var c sso.Config err := dbi.Get(ctx, s.db, &c, ` SELECT id, tenant, name, client_id, client_secret, issuer_url, jwks_url, auth_url, device_auth_url, token_url FROM sso_configs WHERE id = $1 AND tenant = $2 `, id, tenant) return &c, err } func (s *SqliteSsoStore) List(ctx context.Context, tenant core.ID) (*core.Page[sso.Config], error) { if err := s.guard.Check(ctx, sso.Cap_Sso_Read, tenant, ""); err != nil { return nil, err } // TODO var pageReq core.PageReq var page core.Page[sso.Config] err := dbi.Paginate(ctx, s.db, pageReq, &page, func(c sso.Config) string { return c.ID.String() }, `SELECT id, tenant, name, client_id, client_secret, issuer_url, jwks_url, auth_url, device_auth_url, token_url FROM sso_configs WHERE tenant = $1 AND id > $cursor ORDER BY id LIMIT $limit`, tenant, ) return &page, err } func (s *SqliteSsoStore) Delete(ctx context.Context, tenant core.ID, id core.ID) (*sso.Config, error) { if err := s.guard.Check(ctx, sso.Cap_Sso_Write, tenant, ""); err != nil { return nil, err } var c sso.Config err := dbi.Get(ctx, s.db, &c, ` SELECT id, tenant, name, client_id, client_secret, issuer_url, jwks_url, auth_url, device_auth_url, token_url FROM sso_configs WHERE id = $1 AND tenant = $2 `, id, tenant) if err != nil { return nil, err } _, err = s.db.Exec(ctx, `DELETE FROM sso_configs WHERE id = $1 AND tenant = $2`, id, tenant) if err != nil { return nil, err } return &c, nil }