package store import ( "context" "fmt" "strings" "atlas9.dev/c/core" "atlas9.dev/c/core/dbi" "atlas9.dev/c/core/iam" "atlas9.dev/c/demo/lib/access" ) type SqliteGroupGrantStore struct { db dbi.DBI guard access.Guard } var _ iam.GroupGrantStore = (*SqliteGroupGrantStore)(nil) func NewSqliteGroupGrantStore(db dbi.DBI, guard access.Guard) *SqliteGroupGrantStore { return &SqliteGroupGrantStore{db: db, guard: guard} } func (s *SqliteGroupGrantStore) Add(ctx context.Context, g iam.GroupGrant) error { if err := s.guard.Check(ctx, iam.CapGrantsAdd, g.Tenant, ""); err != nil { return err } _, err := s.db.Exec(ctx, ` INSERT INTO group_grants (tenant, group_path, role, path) VALUES ($1, $2, $3, $4) ON CONFLICT (tenant, group_path, role, path) DO NOTHING `, g.Tenant, g.Group, g.Role, g.Path) // The FK to groups rejects a grant for a group that doesn't exist. if err != nil && strings.Contains(err.Error(), "FOREIGN KEY constraint failed") { return fmt.Errorf("group does not exist in this tenant") } return err } func (s *SqliteGroupGrantStore) Remove(ctx context.Context, g iam.GroupGrant) error { if err := s.guard.Check(ctx, iam.CapGrantsRemove, g.Tenant, ""); err != nil { return err } _, err := s.db.Exec(ctx, ` DELETE FROM group_grants WHERE tenant = $1 AND group_path = $2 AND role = $3 AND path = $4 `, g.Tenant, g.Group, g.Role, g.Path) return err } func (s *SqliteGroupGrantStore) ListByTenant(ctx context.Context, tenant core.ID, page core.PageReq) (core.Page[iam.GroupGrant], error) { var out core.Page[iam.GroupGrant] if err := s.guard.Check(ctx, iam.CapGrantsList, tenant, ""); err != nil { return out, err } limit := page.Limit if limit <= 0 { limit = 100 } rows, err := s.db.Query(ctx, ` SELECT tenant, group_path, role, path FROM group_grants WHERE tenant = $1 ORDER BY group_path, role, path LIMIT $2 `, tenant, limit) if err != nil { return out, err } defer rows.Close() for rows.Next() { var g iam.GroupGrant if err := rows.Scan(&g.Tenant, &g.Group, &g.Role, &g.Path); err != nil { return out, err } out.Items = append(out.Items, g) } return out, rows.Err() }