- users.permissions and users.last_seen as additive columns - golem15_user_frontend_permissions (code, label, tab, comment) - User gains LastSeen, read-only CreatedAt and UpdatedAt and the filterByGroup list scope; none of them is serialized - migration tests roll back by position past the three new steps
110 lines
3.9 KiB
Go
110 lines
3.9 KiB
Go
package updates
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"git.golem15.com/golem15/summercms/modules/lagoon"
|
|
"github.com/go-gormigrate/gormigrate/v2"
|
|
)
|
|
|
|
// TestAdminColumnsMigrations applies the three admin migrations on a real
|
|
// Postgres, checks what each one adds, rolls each one back on its own and
|
|
// applies them again.
|
|
func TestAdminColumnsMigrations(t *testing.T) {
|
|
sqlDB := dedicatedDB(t, "user_admin_columns")
|
|
gdb, err := lagoon.Use(t.Context(), sqlDB)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
m := gormigrate.New(gdb, &gormigrate.Options{
|
|
TableName: "summer_migrations_golem15_user",
|
|
UseTransaction: true,
|
|
}, All())
|
|
if err := m.Migrate(); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
columnType := func(table, column string) (string, string) {
|
|
t.Helper()
|
|
var row struct {
|
|
DataType string
|
|
IsNullable string
|
|
}
|
|
if err := gdb.Raw(`SELECT data_type, is_nullable FROM information_schema.columns WHERE table_name = ? AND column_name = ?`, table, column).Scan(&row).Error; err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
return row.DataType, row.IsNullable
|
|
}
|
|
if typ, null := columnType("users", "permissions"); typ != "text" || null != "YES" {
|
|
t.Fatalf("users.permissions = %q nullable %q", typ, null)
|
|
}
|
|
if typ, null := columnType("users", "last_seen"); typ != "timestamp with time zone" || null != "YES" {
|
|
t.Fatalf("users.last_seen = %q nullable %q", typ, null)
|
|
}
|
|
const table = "golem15_user_frontend_permissions"
|
|
want := map[string][2]string{
|
|
"id": {"integer", "NO"},
|
|
"code": {"character varying", "NO"},
|
|
"label": {"character varying", "NO"},
|
|
"tab": {"character varying", "NO"},
|
|
"comment": {"character varying", "YES"},
|
|
"created_at": {"timestamp with time zone", "YES"},
|
|
"updated_at": {"timestamp with time zone", "YES"},
|
|
}
|
|
for column, shape := range want {
|
|
if typ, null := columnType(table, column); typ != shape[0] || null != shape[1] {
|
|
t.Fatalf("%s.%s = %q nullable %q", table, column, typ, null)
|
|
}
|
|
}
|
|
insert := `INSERT INTO golem15_user_frontend_permissions (code, label, tab) VALUES (?, ?, ?)`
|
|
if err := gdb.Exec(insert, "blog.post", "Post", "Blog").Error; err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := gdb.Exec(insert, "blog.post", "Post again", "Blog").Error; err == nil {
|
|
t.Fatal("a duplicate permission code was accepted")
|
|
}
|
|
// An existing user keeps working with both columns empty.
|
|
if err := gdb.Exec(`INSERT INTO users (email) VALUES ('columns@example.test')`).Error; err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
var empty int64
|
|
if err := gdb.Raw(`SELECT COUNT(*) FROM users WHERE permissions IS NULL AND last_seen IS NULL`).Scan(&empty).Error; err != nil || empty != 1 {
|
|
t.Fatalf("users with empty admin columns = %d err = %v", empty, err)
|
|
}
|
|
|
|
if err := m.RollbackMigration(frontendPermissionsMigrations[0]); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if gdb.Migrator().HasTable(table) {
|
|
t.Fatalf("%s survived rollback", table)
|
|
}
|
|
if err := m.RollbackMigration(usersLastSeenMigrations[0]); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if gdb.Migrator().HasColumn("users", "last_seen") || !gdb.Migrator().HasColumn("users", "permissions") {
|
|
t.Fatal("last_seen rollback touched the wrong column")
|
|
}
|
|
if err := m.RollbackMigration(usersPermissionsMigrations[0]); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if gdb.Migrator().HasColumn("users", "permissions") {
|
|
t.Fatal("users.permissions survived rollback")
|
|
}
|
|
for _, kept := range []string{"users", "user_groups", "user_throttle", "user_api_tokens"} {
|
|
if !gdb.Migrator().HasTable(kept) {
|
|
t.Fatalf("rollback dropped %s", kept)
|
|
}
|
|
}
|
|
var users int64
|
|
if err := gdb.Raw(`SELECT COUNT(*) FROM users`).Scan(&users).Error; err != nil || users != 1 {
|
|
t.Fatalf("users after rollback = %d err = %v", users, err)
|
|
}
|
|
|
|
if err := m.Migrate(); err != nil {
|
|
t.Fatalf("re-up: %v", err)
|
|
}
|
|
if !gdb.Migrator().HasTable(table) || !gdb.Migrator().HasColumn("users", "permissions") || !gdb.Migrator().HasColumn("users", "last_seen") {
|
|
t.Fatal("re-up did not restore the admin columns")
|
|
}
|
|
}
|