-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathintegration_test.go
More file actions
195 lines (167 loc) · 6.63 KB
/
Copy pathintegration_test.go
File metadata and controls
195 lines (167 loc) · 6.63 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
package dbstrap
import (
"context"
"fmt"
"os"
"testing"
"time"
"github.com/jackc/pgx/v5"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
// TestIntegration runs integration tests against a real PostgreSQL database
// To run these tests, make sure PostgreSQL is running (e.g., via docker-compose)
// and set the DATABASE_URL environment variable
func TestIntegration(t *testing.T) {
// Skip if not in integration test mode
if os.Getenv("INTEGRATION_TEST") != "true" {
t.Skip("Skipping integration test; set INTEGRATION_TEST=true to run")
}
// Get database URL from environment
dbURL, cleanup := setupTestDatabase(t)
defer cleanup()
// Set test password
os.Setenv("TEST_USER_PASSWORD", "testpass123")
defer os.Unsetenv("TEST_USER_PASSWORD")
// Connect to create the role first
ctx := context.Background()
setupConn, err := pgx.Connect(ctx, dbURL)
require.NoError(t, err)
// Use a timestamp suffix to create unique role names for this test run
timeStamp := time.Now().UnixNano()
roleName := fmt.Sprintf("dbstrap_readonly_role_%d", timeStamp)
// Create the readonly role (since bootstrap doesn't handle roles yet)
_, err = setupConn.Exec(ctx, fmt.Sprintf("CREATE ROLE %s", roleName))
require.NoError(t, err)
setupConn.Close(ctx)
// Format the YAML with the role name
yamlStr := fmt.Sprintf(`
users:
- name: dbstrap_test_user
password_env: TEST_USER_PASSWORD
can_login: true
owns_schemas:
- public
- test_schema
roles: []
- name: dbstrap_readonly_user
password_env: TEST_USER_PASSWORD
can_login: true
owns_schemas: []
roles: [%s]
databases:
- name: dbstrap_test_db
owner: dbstrap_test_user
encoding: UTF8
lc_collate: en_US.UTF-8
lc_ctype: en_US.UTF-8
template: template0
extensions:
- "uuid-ossp"
grants:
- user: dbstrap_test_user
privileges: [CONNECT]
- user: dbstrap_readonly_user
privileges: [CONNECT]
schemas:
- name: public
owner: dbstrap_test_user
grants:
- user: dbstrap_test_user
privileges: [USAGE, CREATE]
table_privileges: [SELECT, INSERT, UPDATE, DELETE]
sequence_privileges: [USAGE, SELECT, UPDATE]
function_privileges: [EXECUTE]
default_privileges: [SELECT, INSERT, UPDATE, DELETE]
- role: %s
privileges: [USAGE]
table_privileges: [SELECT]
sequence_privileges: [USAGE, SELECT]
function_privileges: [EXECUTE]
default_privileges: [SELECT]
- name: test_schema
owner: dbstrap_test_user
grants:
- user: dbstrap_test_user
privileges: [USAGE, CREATE]
table_privileges: [SELECT, INSERT, UPDATE, DELETE]
sequence_privileges: [USAGE, SELECT, UPDATE]
function_privileges: [EXECUTE]
default_privileges: [SELECT, INSERT, UPDATE, DELETE]
- role: %s
privileges: [USAGE]
table_privileges: [SELECT]
sequence_privileges: [USAGE, SELECT]
function_privileges: [EXECUTE]
default_privileges: [SELECT]
`, roleName, roleName, roleName)
// Now run bootstrap
err = BootstrapDatabase([]byte(yamlStr))
require.NoError(t, err)
// Connect to the test database
// First connect to the default database to verify the test database was created
conn, err := pgx.Connect(ctx, dbURL)
require.NoError(t, err)
defer conn.Close(ctx)
// Verify test database exists
var dbExists bool
err = conn.QueryRow(ctx, "SELECT EXISTS(SELECT 1 FROM pg_database WHERE datname = $1)", "dbstrap_test_db").Scan(&dbExists)
require.NoError(t, err)
assert.True(t, dbExists, "Test database should exist")
// Verify users exist
var userExists bool
err = conn.QueryRow(ctx, "SELECT EXISTS(SELECT 1 FROM pg_roles WHERE rolname = $1)", "dbstrap_test_user").Scan(&userExists)
require.NoError(t, err)
assert.True(t, userExists, "Test user should exist")
var readonlyUserExists bool
err = conn.QueryRow(ctx, "SELECT EXISTS(SELECT 1 FROM pg_roles WHERE rolname = $1)", "dbstrap_readonly_user").Scan(&readonlyUserExists)
require.NoError(t, err)
assert.True(t, readonlyUserExists, "Readonly user should exist")
// Connect to the test database to verify schemas and grants
testDbConfig, err := pgx.ParseConfig(dbURL)
require.NoError(t, err)
testDbConfig.Database = "dbstrap_test_db"
testConn, err := pgx.ConnectConfig(ctx, testDbConfig)
require.NoError(t, err)
defer testConn.Close(ctx)
// Verify test_schema exists
var schemaExists bool
err = testConn.QueryRow(ctx, "SELECT EXISTS(SELECT 1 FROM information_schema.schemata WHERE schema_name = $1)", "test_schema").Scan(&schemaExists)
require.NoError(t, err)
assert.True(t, schemaExists, "Test schema should exist")
// Verify extension was created
var extensionExists bool
err = testConn.QueryRow(ctx, "SELECT EXISTS(SELECT 1 FROM pg_extension WHERE extname = $1)", "uuid-ossp").Scan(&extensionExists)
require.NoError(t, err)
assert.True(t, extensionExists, "UUID extension should exist")
// Create a test table to verify default privileges
_, err = testConn.Exec(ctx, "CREATE TABLE test_schema.test_table (id serial PRIMARY KEY, name text)")
require.NoError(t, err)
// Explicitly grant SELECT permission to the readonly role (since default privileges might not apply retroactively)
_, err = testConn.Exec(ctx, fmt.Sprintf("GRANT SELECT ON test_schema.test_table TO %s", roleName))
require.NoError(t, err)
// Insert some test data
_, err = testConn.Exec(ctx, "INSERT INTO test_schema.test_table (name) VALUES ('test1'), ('test2')")
require.NoError(t, err)
// Verify grants by connecting as the readonly user
readonlyDbConfig, err := pgx.ParseConfig(dbURL)
require.NoError(t, err)
readonlyDbConfig.Database = "dbstrap_test_db"
readonlyDbConfig.User = "dbstrap_readonly_user"
readonlyDbConfig.Password = "testpass123"
readonlyConn, err := pgx.ConnectConfig(ctx, readonlyDbConfig)
require.NoError(t, err)
defer readonlyConn.Close(ctx)
// Verify readonly user can SELECT but not INSERT
var count int
err = readonlyConn.QueryRow(ctx, "SELECT COUNT(*) FROM test_schema.test_table").Scan(&count)
assert.NoError(t, err, "Readonly user should be able to SELECT")
_, err = readonlyConn.Exec(ctx, "INSERT INTO test_schema.test_table (name) VALUES ('test')")
assert.Error(t, err, "Readonly user should not be able to INSERT")
// Clean up
testConn.Exec(ctx, "DROP TABLE test_schema.test_table")
conn.Exec(ctx, "DROP DATABASE dbstrap_test_db")
conn.Exec(ctx, "DROP ROLE dbstrap_test_user")
conn.Exec(ctx, "DROP ROLE dbstrap_readonly_user")
conn.Exec(ctx, fmt.Sprintf("DROP ROLE IF EXISTS %s", roleName))
}