feat: connection search by name/hostname/tag with json_each filtering
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
995e81de3b
commit
ab5a5c7ae2
40
internal/connections/search.go
Normal file
40
internal/connections/search.go
Normal file
@ -0,0 +1,40 @@
|
||||
package connections
|
||||
|
||||
import "fmt"
|
||||
|
||||
func (s *ConnectionService) Search(query string) ([]Connection, error) {
|
||||
like := "%" + query + "%"
|
||||
rows, err := s.db.Query(
|
||||
`SELECT id, name, hostname, port, protocol, group_id, credential_id,
|
||||
COALESCE(color,''), tags, COALESCE(notes,''), COALESCE(options,'{}'),
|
||||
sort_order, last_connected, created_at, updated_at
|
||||
FROM connections
|
||||
WHERE name LIKE ? COLLATE NOCASE
|
||||
OR hostname LIKE ? COLLATE NOCASE
|
||||
OR tags LIKE ? COLLATE NOCASE
|
||||
OR notes LIKE ? COLLATE NOCASE
|
||||
ORDER BY last_connected DESC NULLS LAST, name`,
|
||||
like, like, like, like,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("search connections: %w", err)
|
||||
}
|
||||
defer rows.Close()
|
||||
return scanConnections(rows)
|
||||
}
|
||||
|
||||
func (s *ConnectionService) FilterByTag(tag string) ([]Connection, error) {
|
||||
rows, err := s.db.Query(
|
||||
`SELECT c.id, c.name, c.hostname, c.port, c.protocol, c.group_id, c.credential_id,
|
||||
COALESCE(c.color,''), c.tags, COALESCE(c.notes,''), COALESCE(c.options,'{}'),
|
||||
c.sort_order, c.last_connected, c.created_at, c.updated_at
|
||||
FROM connections c, json_each(c.tags) AS t
|
||||
WHERE t.value = ?
|
||||
ORDER BY c.name`, tag,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("filter by tag: %w", err)
|
||||
}
|
||||
defer rows.Close()
|
||||
return scanConnections(rows)
|
||||
}
|
||||
53
internal/connections/search_test.go
Normal file
53
internal/connections/search_test.go
Normal file
@ -0,0 +1,53 @@
|
||||
package connections
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestSearchByName(t *testing.T) {
|
||||
svc := setupTestService(t)
|
||||
svc.CreateConnection(CreateConnectionInput{Name: "Asgard", Hostname: "192.168.1.4", Port: 22, Protocol: "ssh"})
|
||||
svc.CreateConnection(CreateConnectionInput{Name: "Docker", Hostname: "155.254.29.221", Port: 22, Protocol: "ssh"})
|
||||
|
||||
results, err := svc.Search("asg")
|
||||
if err != nil {
|
||||
t.Fatalf("Search() error: %v", err)
|
||||
}
|
||||
if len(results) != 1 {
|
||||
t.Fatalf("len(results) = %d, want 1", len(results))
|
||||
}
|
||||
if results[0].Name != "Asgard" {
|
||||
t.Errorf("Name = %q, want %q", results[0].Name, "Asgard")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSearchByHostname(t *testing.T) {
|
||||
svc := setupTestService(t)
|
||||
svc.CreateConnection(CreateConnectionInput{Name: "Asgard", Hostname: "192.168.1.4", Port: 22, Protocol: "ssh"})
|
||||
|
||||
results, _ := svc.Search("192.168")
|
||||
if len(results) != 1 {
|
||||
t.Errorf("len(results) = %d, want 1", len(results))
|
||||
}
|
||||
}
|
||||
|
||||
func TestSearchByTag(t *testing.T) {
|
||||
svc := setupTestService(t)
|
||||
svc.CreateConnection(CreateConnectionInput{Name: "ProdServer", Hostname: "10.0.0.1", Port: 22, Protocol: "ssh", Tags: []string{"Prod", "Linux"}})
|
||||
svc.CreateConnection(CreateConnectionInput{Name: "DevServer", Hostname: "10.0.0.2", Port: 22, Protocol: "ssh", Tags: []string{"Dev", "Linux"}})
|
||||
|
||||
results, _ := svc.Search("Prod")
|
||||
if len(results) != 1 {
|
||||
t.Errorf("len(results) = %d, want 1", len(results))
|
||||
}
|
||||
}
|
||||
|
||||
func TestFilterByTag(t *testing.T) {
|
||||
svc := setupTestService(t)
|
||||
svc.CreateConnection(CreateConnectionInput{Name: "A", Hostname: "10.0.0.1", Port: 22, Protocol: "ssh", Tags: []string{"Prod"}})
|
||||
svc.CreateConnection(CreateConnectionInput{Name: "B", Hostname: "10.0.0.2", Port: 22, Protocol: "ssh", Tags: []string{"Dev"}})
|
||||
svc.CreateConnection(CreateConnectionInput{Name: "C", Hostname: "10.0.0.3", Port: 22, Protocol: "ssh", Tags: []string{"Prod", "Linux"}})
|
||||
|
||||
results, _ := svc.FilterByTag("Prod")
|
||||
if len(results) != 2 {
|
||||
t.Errorf("len(results) = %d, want 2", len(results))
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user