Skip to content

Commit c3e4614

Browse files
authored
Fix created users permission and skip db test in CI (#32)
1 parent a82566f commit c3e4614

File tree

4 files changed

+122
-4
lines changed

4 files changed

+122
-4
lines changed

README.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,21 @@ The project includes end-to-end tests for the backend API using Cypress. These t
117117
```
118118
*(Note: Ensure the `CYPRESS_BASE_URL` in `compose.test.yml` or your local Cypress config points to the correct backend URL for testing, typically `http://backend:8080` when run via compose, or `http://localhost:8080` if backend is run directly on host for local Cypress development).*
119119
120+
### Backend Go Tests
121+
122+
To run the backend's Go tests, you can use the `backend-tests` profile in the `compose.test.yml` file. This will run the tests in a containerized environment.
123+
124+
```bash
125+
docker compose -f compose.test.yml --profile backend-tests up --build
126+
```
127+
128+
Alternatively, you can run the tests directly on your host machine if you have Go installed:
129+
130+
```bash
131+
cd backend
132+
PG_ADMIN_DSN="postgres://test_admin:test_password@localhost:5432/test_admin_db?sslmode=disable" go test ./...
133+
```
134+
120135
## 7. Project Structure
121136

122137
```

backend/dbutils/provision.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -296,11 +296,11 @@ func CreatePostgresDatabase(pgAdminDSN, dbName string) error {
296296
}
297297

298298
// Set default CREATE and USAGE privileges for future schemas for write role
299-
_, err = newDB.Exec(fmt.Sprintf("ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT CREATE ON TABLES TO %s", writeRole))
299+
_, err = newDB.Exec(fmt.Sprintf("ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON TABLES TO %s", writeRole))
300300
if err != nil {
301301
return fmt.Errorf("failed to alter default CREATE privileges for public schema to write role %s: %w", writeRole, err)
302302
}
303-
_, err = newDB.Exec(fmt.Sprintf("ALTER DEFAULT PRIVILEGES IN SCHEMA %s GRANT CREATE ON TABLES TO %s", safeDBName, writeRole))
303+
_, err = newDB.Exec(fmt.Sprintf("ALTER DEFAULT PRIVILEGES IN SCHEMA %s GRANT ALL ON TABLES TO %s", safeDBName, writeRole))
304304
if err != nil {
305305
return fmt.Errorf("failed to alter default CREATE privileges for database schema to write role %s: %w", writeRole, err)
306306
}

backend/dbutils/provision_test.go

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,18 @@ func TestUserPermissionsAndIsolation(t *testing.T) {
252252
t.Fatalf("Write user failed to delete data: %v", err)
253253
}
254254

255+
// Verify CREATE INDEX is allowed
256+
_, err = writeDB.Exec("CREATE INDEX idx_write_test ON write_test_table(id)")
257+
if err != nil {
258+
t.Fatalf("Write user failed to create index: %v", err)
259+
}
260+
261+
// Verify DROP INDEX is allowed
262+
_, err = writeDB.Exec("DROP INDEX idx_write_test")
263+
if err != nil {
264+
t.Fatalf("Write user failed to drop index: %v", err)
265+
}
266+
255267
// Clean up table
256268
_, err = writeDB.Exec("DROP TABLE write_test_table")
257269
if err != nil {
@@ -325,3 +337,93 @@ func TestUserPermissionsAndIsolation(t *testing.T) {
325337
t.Errorf("Failed to drop second test database %s: %v", testDBName2, err)
326338
}
327339
}
340+
341+
// TestUserCannotCreateOrDropDB verifies that a user with 'write' permissions cannot create or drop databases.
342+
func TestUserCannotCreateOrDropDB(t *testing.T) {
343+
adminDSN := os.Getenv("PG_ADMIN_DSN")
344+
if adminDSN == "" {
345+
t.Skip("PG_ADMIN_DSN not set, skipping test")
346+
}
347+
348+
// 1. Create a user with 'write' permissions
349+
password, err := CreatePostgresUser(adminDSN, testDBName, testUser, "write")
350+
if err != nil {
351+
t.Fatalf("Failed to create postgres user: %v", err)
352+
}
353+
354+
userDSN := getUserDSN(t, testUser, password, testDBName)
355+
356+
userDB, err := connectToDB(userDSN)
357+
if err != nil {
358+
t.Fatalf("Failed to connect to test DB as new user: %v", err)
359+
}
360+
defer userDB.Close()
361+
362+
// 2. Attempt to create a database (should fail)
363+
_, err = userDB.Exec("CREATE DATABASE should_not_be_created_db")
364+
if err == nil {
365+
t.Fatal("User should not be able to create a database")
366+
}
367+
if !strings.Contains(err.Error(), "permission denied") {
368+
t.Errorf("Expected 'permission denied' error, got: %v", err)
369+
}
370+
371+
// 3. Attempt to drop a database (should fail)
372+
_, err = userDB.Exec(fmt.Sprintf("DROP DATABASE %s", testDBName))
373+
if err == nil {
374+
t.Fatal("User should not be able to drop a database")
375+
}
376+
if !strings.Contains(err.Error(), "must be owner of database") {
377+
t.Errorf("Expected 'must be owner of database' error, got: %v", err)
378+
}
379+
380+
// 4. Cleanup the user
381+
err = DeletePostgresUser(adminDSN, testDBName, testUser)
382+
if err != nil {
383+
t.Fatalf("Failed to delete postgres user: %v", err)
384+
}
385+
}
386+
387+
// TestUserCanCreateTable verifies a user with 'write' permissions can create and delete tables.
388+
func TestUserCanCreateTable(t *testing.T) {
389+
adminDSN := os.Getenv("PG_ADMIN_DSN")
390+
if adminDSN == "" {
391+
t.Skip("PG_ADMIN_DSN not set, skipping test")
392+
}
393+
394+
// 1. Create a user with 'write' permissions
395+
testUser := "writeuser_createtable_" + uuid.New().String()[:8]
396+
password, err := CreatePostgresUser(adminDSN, testDBName, testUser, "write")
397+
if err != nil {
398+
t.Fatalf("Failed to create postgres user: %v", err)
399+
}
400+
401+
// Defer user deletion
402+
defer func() {
403+
err := DeletePostgresUser(adminDSN, testDBName, testUser)
404+
if err != nil {
405+
t.Errorf("Failed to delete postgres user %s: %v", testUser, err)
406+
}
407+
}()
408+
409+
userDSN := getUserDSN(t, testUser, password, testDBName)
410+
411+
userDB, err := connectToDB(userDSN)
412+
if err != nil {
413+
t.Fatalf("Failed to connect to test DB as new user: %v", err)
414+
}
415+
defer userDB.Close()
416+
417+
// 2. Create a table
418+
tableName := "test_table_creation"
419+
_, err = userDB.Exec(fmt.Sprintf("CREATE TABLE %s (id INT)", tableName))
420+
if err != nil {
421+
t.Fatalf("User failed to create table: %v", err)
422+
}
423+
424+
// 3. Drop the table
425+
_, err = userDB.Exec(fmt.Sprintf("DROP TABLE %s", tableName))
426+
if err != nil {
427+
t.Fatalf("User failed to drop table: %v", err)
428+
}
429+
}

compose.test.yml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ services:
6262
- frontend
6363

6464
backend-tests:
65+
profiles:
66+
- backend-tests
6567
container_name: pgweb_test_backend_tests
6668
build:
6769
context: ./backend
@@ -70,8 +72,7 @@ services:
7072
PG_ADMIN_DSN: "postgres://test_admin:test_password@postgres:5432/test_admin_db?sslmode=disable"
7173
PG_HOST: "postgres"
7274
depends_on:
73-
cypress:
74-
condition: service_completed_successfully
75+
- backend
7576

7677
cypress:
7778
image: cypress/included:12.17.0

0 commit comments

Comments
 (0)