103 lines
3.4 KiB
Go
103 lines
3.4 KiB
Go
package db
|
|
|
|
import (
|
|
"database/sql"
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
)
|
|
|
|
func TestAuthorizerBlocksSensitiveTables(t *testing.T) {
|
|
// Create temporary database
|
|
tmpDir := t.TempDir()
|
|
dbPath := filepath.Join(tmpDir, "test.db")
|
|
|
|
// Set environment for database path
|
|
if err := os.Setenv("ATCR_UI_DATABASE_PATH", dbPath); err != nil {
|
|
t.Fatalf("Failed to set environment variable: %v", err)
|
|
}
|
|
defer os.Unsetenv("ATCR_UI_DATABASE_PATH")
|
|
|
|
// Initialize database (creates schema)
|
|
database, err := InitDB(dbPath, true)
|
|
if err != nil {
|
|
t.Fatalf("Failed to initialize database: %v", err)
|
|
}
|
|
defer database.Close()
|
|
|
|
// Create some test data in sensitive tables
|
|
_, err = database.Exec(`
|
|
INSERT INTO oauth_sessions (session_key, account_did, session_id, session_data, created_at, updated_at)
|
|
VALUES ('test-key', 'did:plc:test', 'test-session', 'secret-token-data', datetime('now'), datetime('now'))
|
|
`)
|
|
if err != nil {
|
|
t.Fatalf("Failed to insert test data: %v", err)
|
|
}
|
|
|
|
_, err = database.Exec(`
|
|
INSERT INTO users (did, handle, pds_endpoint, avatar, last_seen)
|
|
VALUES ('did:plc:test', 'test.user', 'https://pds.example.com', '', datetime('now'))
|
|
`)
|
|
if err != nil {
|
|
t.Fatalf("Failed to insert test user: %v", err)
|
|
}
|
|
|
|
// Open read-only connection with authorizer (using our custom driver)
|
|
readOnlyDB, err := sql.Open(ReadOnlyDriverName, "file:"+dbPath+"?mode=ro")
|
|
if err != nil {
|
|
t.Fatalf("Failed to open read-only database: %v", err)
|
|
}
|
|
defer readOnlyDB.Close()
|
|
|
|
// Test 1: Should be able to read from public tables (users)
|
|
t.Run("AllowPublicTableRead", func(t *testing.T) {
|
|
var handle string
|
|
err := readOnlyDB.QueryRow("SELECT handle FROM users WHERE did = ?", "did:plc:test").Scan(&handle)
|
|
if err != nil {
|
|
t.Errorf("Should be able to read from public table 'users': %v", err)
|
|
}
|
|
if handle != "test.user" {
|
|
t.Errorf("Expected handle 'test.user', got '%s'", handle)
|
|
}
|
|
})
|
|
|
|
// Test 2: Should NOT be able to read from sensitive tables (oauth_sessions)
|
|
t.Run("BlockSensitiveTableRead", func(t *testing.T) {
|
|
var sessionData string
|
|
err := readOnlyDB.QueryRow("SELECT session_data FROM oauth_sessions WHERE session_key = ?", "test-key").Scan(&sessionData)
|
|
if err == nil {
|
|
t.Errorf("Should NOT be able to read from sensitive table 'oauth_sessions', but got data: %s", sessionData)
|
|
}
|
|
// SQLite returns "not authorized" error when authorizer denies access
|
|
if err != nil && err.Error() != "not authorized" {
|
|
t.Logf("Got expected error (but different message): %v", err)
|
|
}
|
|
})
|
|
|
|
// Test 3: Should NOT be able to read from ui_sessions
|
|
t.Run("BlockUISessionsTableRead", func(t *testing.T) {
|
|
rows, err := readOnlyDB.Query("SELECT * FROM ui_sessions LIMIT 1")
|
|
if err == nil {
|
|
rows.Close()
|
|
t.Error("Should NOT be able to read from sensitive table 'ui_sessions'")
|
|
}
|
|
})
|
|
|
|
// Test 4: Should NOT be able to read from devices
|
|
t.Run("BlockDevicesTableRead", func(t *testing.T) {
|
|
rows, err := readOnlyDB.Query("SELECT * FROM devices LIMIT 1")
|
|
if err == nil {
|
|
rows.Close()
|
|
t.Error("Should NOT be able to read from sensitive table 'devices'")
|
|
}
|
|
})
|
|
|
|
// Test 5: Should NOT be able to write to any table (read-only mode + authorizer)
|
|
t.Run("BlockAllWrites", func(t *testing.T) {
|
|
_, err := readOnlyDB.Exec("INSERT INTO users (did, handle, pds_endpoint, avatar, last_seen) VALUES ('did:plc:test2', 'test2', 'https://pds.example.com', '', datetime('now'))")
|
|
if err == nil {
|
|
t.Error("Should NOT be able to write to any table in read-only mode")
|
|
}
|
|
})
|
|
}
|