snapshot of https://github.com/mattermost/mattermost.git (master, 2026-09-16; blobs > 131072B omitted)
Some checks failed
Server CI / Postgres (shard 0) (push) Has been skipped
Server CI / Postgres (shard 3) (push) Has been skipped
BuildEnv Docker Image / build-image (push) Failing after 4s
BuildEnv Docker Image / build-image-fips (push) Failing after 4s
Migration Review & Release Notes / Generate migration review & release notes (push) Failing after 3s
Server CI / Build Environment (push) Failing after 3s
Server CI / Postgres (shard 1) (push) Has been skipped
Tools CI / check-style (mattermost-govet) (push) Failing after 4s
Server CI / Postgres (shard 2) (push) Has been skipped
Tools CI / check-style (mmgotool) (push) Failing after 3s
Server CI / Elasticsearch v8 Compatibility (push) Has been skipped
Server CI / OpenSearch v2 Compatibility (push) Has been skipped
Server CI / Postgres FIPS (shard 0) (push) Has been skipped
Tools CI / Test (mattermost-govet) (push) Failing after 3s
Server CI / Postgres FIPS (shard 1) (push) Has been skipped
Server CI / Postgres FIPS (shard 2) (push) Has been skipped
Tools CI / Test (mmgotool) (push) Failing after 3s
Server CI / Postgres FIPS (shard 3) (push) Has been skipped
Server CI / Run mmctl tests (push) Has been skipped
Server CI / Run mmctl tests (FIPS) (push) Has been skipped
Server CI / Merge Postgres Test Results (push) Has been skipped
Server CI / Merge Postgres FIPS Test Results (push) Has been skipped
Server CI / Check backport migrations (push) Has been skipped
Server CI / Check generated files (push) Has been skipped
Server CI / check-style (push) Has been skipped
Server CI / Vet API (push) Has been skipped
Server CI / Build mattermost server app (push) Has been skipped
Server CI / Server CI Complete (push) Failing after 2s
Server CI / Server CI Artifacts (push) Has been skipped
Server CI / Sentry Upload (push) Has been skipped
Server CI / Server CI Report (push) Failing after 5m1s
Server CI Nightly Race / Race Detector (push) Has been skipped
CodeQL / Analyze (go) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
Webapp CI Cache Warm / Warm Webapp node_modules Cache (push) Has been cancelled
E2E CI Cache Warm / Warm E2E npm Registry Cache (push) Has been cancelled
API / build (push) Has been cancelled
Web App CI / check-types (push) Has been cancelled
Web App CI / check-lint (push) Has been cancelled
Web App CI / check-i18n (push) Has been cancelled
Web App CI / check-external-links (push) Has been cancelled
Web App CI / test (platform) (push) Has been cancelled
Web App CI / test (mattermost-redux) (push) Has been cancelled
Web App CI / test (channels shard 1/4) (push) Has been cancelled
Web App CI / test (channels shard 2/4) (push) Has been cancelled
Web App CI / test (channels shard 3/4) (push) Has been cancelled
Web App CI / test (channels shard 4/4) (push) Has been cancelled
Web App CI / upload-coverage (push) Has been cancelled
Web App CI / build (push) Has been cancelled
YAML Lint / yamllint (push) Has been cancelled
Push mirrored docker images / cd/Push mirrored docker images (push) Has been cancelled
docs-cd / Build and deploy docs (push) Has been cancelled
Docs CI / build (push) Has been cancelled
E2E Cache Warm: Cypress deps / Warm Cypress deps cache (push) Has been cancelled
Scorecards supply-chain security / Scorecard analysis (push) Has been cancelled
Server CI Weekly / Postgres FIPS (push) Has been skipped
Server CI Weekly / Run mmctl tests (FIPS) (push) Has been skipped
Server CI Weekly / Postgres with binary parameters (push) Has been skipped
Server CI Weekly / Build Environment (push) Failing after 1s
Server CI Cache Warm / Warm Go Module and Build Cache (push) Failing after 2s
Server CI Nightly Race / Build Environment (push) Failing after 1s
Some checks failed
Server CI / Postgres (shard 0) (push) Has been skipped
Server CI / Postgres (shard 3) (push) Has been skipped
BuildEnv Docker Image / build-image (push) Failing after 4s
BuildEnv Docker Image / build-image-fips (push) Failing after 4s
Migration Review & Release Notes / Generate migration review & release notes (push) Failing after 3s
Server CI / Build Environment (push) Failing after 3s
Server CI / Postgres (shard 1) (push) Has been skipped
Tools CI / check-style (mattermost-govet) (push) Failing after 4s
Server CI / Postgres (shard 2) (push) Has been skipped
Tools CI / check-style (mmgotool) (push) Failing after 3s
Server CI / Elasticsearch v8 Compatibility (push) Has been skipped
Server CI / OpenSearch v2 Compatibility (push) Has been skipped
Server CI / Postgres FIPS (shard 0) (push) Has been skipped
Tools CI / Test (mattermost-govet) (push) Failing after 3s
Server CI / Postgres FIPS (shard 1) (push) Has been skipped
Server CI / Postgres FIPS (shard 2) (push) Has been skipped
Tools CI / Test (mmgotool) (push) Failing after 3s
Server CI / Postgres FIPS (shard 3) (push) Has been skipped
Server CI / Run mmctl tests (push) Has been skipped
Server CI / Run mmctl tests (FIPS) (push) Has been skipped
Server CI / Merge Postgres Test Results (push) Has been skipped
Server CI / Merge Postgres FIPS Test Results (push) Has been skipped
Server CI / Check backport migrations (push) Has been skipped
Server CI / Check generated files (push) Has been skipped
Server CI / check-style (push) Has been skipped
Server CI / Vet API (push) Has been skipped
Server CI / Build mattermost server app (push) Has been skipped
Server CI / Server CI Complete (push) Failing after 2s
Server CI / Server CI Artifacts (push) Has been skipped
Server CI / Sentry Upload (push) Has been skipped
Server CI / Server CI Report (push) Failing after 5m1s
Server CI Nightly Race / Race Detector (push) Has been skipped
CodeQL / Analyze (go) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
Webapp CI Cache Warm / Warm Webapp node_modules Cache (push) Has been cancelled
E2E CI Cache Warm / Warm E2E npm Registry Cache (push) Has been cancelled
API / build (push) Has been cancelled
Web App CI / check-types (push) Has been cancelled
Web App CI / check-lint (push) Has been cancelled
Web App CI / check-i18n (push) Has been cancelled
Web App CI / check-external-links (push) Has been cancelled
Web App CI / test (platform) (push) Has been cancelled
Web App CI / test (mattermost-redux) (push) Has been cancelled
Web App CI / test (channels shard 1/4) (push) Has been cancelled
Web App CI / test (channels shard 2/4) (push) Has been cancelled
Web App CI / test (channels shard 3/4) (push) Has been cancelled
Web App CI / test (channels shard 4/4) (push) Has been cancelled
Web App CI / upload-coverage (push) Has been cancelled
Web App CI / build (push) Has been cancelled
YAML Lint / yamllint (push) Has been cancelled
Push mirrored docker images / cd/Push mirrored docker images (push) Has been cancelled
docs-cd / Build and deploy docs (push) Has been cancelled
Docs CI / build (push) Has been cancelled
E2E Cache Warm: Cypress deps / Warm Cypress deps cache (push) Has been cancelled
Scorecards supply-chain security / Scorecard analysis (push) Has been cancelled
Server CI Weekly / Postgres FIPS (push) Has been skipped
Server CI Weekly / Run mmctl tests (FIPS) (push) Has been skipped
Server CI Weekly / Postgres with binary parameters (push) Has been skipped
Server CI Weekly / Build Environment (push) Failing after 1s
Server CI Cache Warm / Warm Go Module and Build Cache (push) Failing after 2s
Server CI Nightly Race / Build Environment (push) Failing after 1s
This commit is contained in:
336
server/channels/store/sqlstore/migration_000185_test.go
Normal file
336
server/channels/store/sqlstore/migration_000185_test.go
Normal file
@@ -0,0 +1,336 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package sqlstore
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/mattermost/mattermost/server/public/model"
|
||||
"github.com/mattermost/mattermost/server/public/shared/mlog"
|
||||
"github.com/mattermost/mattermost/server/v8/channels/db"
|
||||
)
|
||||
|
||||
func readMigrationSQL(t *testing.T, filename string) string {
|
||||
t.Helper()
|
||||
data, err := db.Assets().ReadFile("migrations/postgres/" + filename)
|
||||
require.NoError(t, err, "failed to read migration file %s", filename)
|
||||
return string(data)
|
||||
}
|
||||
|
||||
func TestMigration000185(t *testing.T) {
|
||||
logger := mlog.CreateTestLogger(t)
|
||||
|
||||
settings, err := makeSqlSettings(model.DatabaseDriverPostgres)
|
||||
if err != nil {
|
||||
t.Skip(err)
|
||||
}
|
||||
|
||||
store, err := New(*settings, logger, nil)
|
||||
require.NoError(t, err)
|
||||
defer store.Close()
|
||||
|
||||
master := store.GetMaster()
|
||||
|
||||
upSQL := readMigrationSQL(t, "000176_migrate_cpa_to_access_control.up.sql")
|
||||
downSQL := readMigrationSQL(t, "000176_migrate_cpa_to_access_control.down.sql")
|
||||
|
||||
// Insert a group simulating pre-migration CPA state.
|
||||
groupID := model.NewId()
|
||||
_, err = master.Exec("INSERT INTO PropertyGroups (ID, Name) VALUES (?, ?)", groupID, "custom_profile_attributes")
|
||||
require.NoError(t, err)
|
||||
|
||||
t.Cleanup(func() {
|
||||
master.Exec("DELETE FROM PropertyValues WHERE GroupID = ?", groupID) //nolint:errcheck
|
||||
master.Exec("DELETE FROM PropertyFields WHERE GroupID = ?", groupID) //nolint:errcheck
|
||||
master.Exec("DELETE FROM PropertyGroups WHERE ID = ?", groupID) //nolint:errcheck
|
||||
})
|
||||
|
||||
now := model.GetMillis()
|
||||
|
||||
// Insert active fields with old format (no ObjectType, no permissions).
|
||||
// fieldID1 and fieldID2 are non-managed; fieldID3 is admin-managed.
|
||||
fieldID1 := model.NewId()
|
||||
fieldID2 := model.NewId()
|
||||
fieldID3 := model.NewId()
|
||||
for _, f := range []struct {
|
||||
id string
|
||||
name string
|
||||
ftype string
|
||||
attrs string
|
||||
}{
|
||||
{fieldID1, "Text Field", "text", `{"visibility":"always","sort_order":1}`},
|
||||
{fieldID2, "Select Field", "select", `{"options":[{"id":"opt1","name":"Option 1"}]}`},
|
||||
{fieldID3, "Admin Managed Field", "text", `{"visibility":"always","sort_order":3,"managed":"admin"}`},
|
||||
} {
|
||||
_, err = master.Exec(
|
||||
`INSERT INTO PropertyFields
|
||||
(ID, GroupID, Name, Type, Attrs, TargetID, TargetType, ObjectType, CreateAt, UpdateAt, DeleteAt, Protected)
|
||||
VALUES (?, ?, ?, ?, ?::jsonb, '', '', '', ?, ?, 0, false)`,
|
||||
f.id, groupID, f.name, f.ftype, f.attrs, now, now,
|
||||
)
|
||||
require.NoError(t, err, "inserting field %s", f.name)
|
||||
}
|
||||
|
||||
// Insert a soft-deleted field to verify all fields are migrated.
|
||||
deletedFieldID := model.NewId()
|
||||
_, err = master.Exec(
|
||||
`INSERT INTO PropertyFields
|
||||
(ID, GroupID, Name, Type, Attrs, TargetID, TargetType, ObjectType, CreateAt, UpdateAt, DeleteAt, Protected)
|
||||
VALUES (?, ?, 'Deleted Field', 'text', '{}'::jsonb, '', '', '', ?, ?, ?, false)`,
|
||||
deletedFieldID, groupID, now, now, now,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Insert a property value.
|
||||
valueID := model.NewId()
|
||||
targetUserID := model.NewId()
|
||||
_, err = master.Exec(
|
||||
`INSERT INTO PropertyValues
|
||||
(ID, TargetID, TargetType, GroupID, FieldID, Value, CreateAt, UpdateAt, DeleteAt)
|
||||
VALUES (?, ?, 'user', ?, ?, '"hello"'::jsonb, ?, ?, 0)`,
|
||||
valueID, targetUserID, groupID, fieldID1, now, now,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
// ---- Run UP migration ----
|
||||
_, err = master.ExecNoTimeout(upSQL)
|
||||
require.NoError(t, err, "up migration should succeed")
|
||||
|
||||
// Verify: group renamed.
|
||||
var groupName string
|
||||
require.NoError(t, master.Get(&groupName, "SELECT Name FROM PropertyGroups WHERE ID = ?", groupID))
|
||||
assert.Equal(t, "access_control", groupName)
|
||||
|
||||
// Verify: all fields (including soft-deleted) have new metadata.
|
||||
// Non-managed fields get PermissionValues = 'member'.
|
||||
// Admin-managed fields get PermissionValues = 'sysadmin'.
|
||||
for _, tc := range []struct {
|
||||
id string
|
||||
label string
|
||||
expectedPermissionValues string
|
||||
}{
|
||||
{fieldID1, "non-managed text field", "member"},
|
||||
{fieldID2, "non-managed select field", "member"},
|
||||
{fieldID3, "admin-managed field", "sysadmin"},
|
||||
{deletedFieldID, "soft-deleted non-managed field", "member"},
|
||||
} {
|
||||
var f struct {
|
||||
ObjectType string `db:"objecttype"`
|
||||
TargetType string `db:"targettype"`
|
||||
PermissionField sql.NullString `db:"permissionfield"`
|
||||
PermissionValues sql.NullString `db:"permissionvalues"`
|
||||
PermissionOptions sql.NullString `db:"permissionoptions"`
|
||||
}
|
||||
require.NoError(t, master.Get(&f, "SELECT ObjectType, TargetType, PermissionField, PermissionValues, PermissionOptions FROM PropertyFields WHERE ID = ?", tc.id))
|
||||
assert.Equal(t, "user", f.ObjectType, "%s ObjectType", tc.label)
|
||||
assert.Equal(t, "system", f.TargetType, "%s TargetType", tc.label)
|
||||
assert.True(t, f.PermissionField.Valid, "%s PermissionField should be set", tc.label)
|
||||
assert.Equal(t, "sysadmin", f.PermissionField.String, "%s PermissionField", tc.label)
|
||||
assert.True(t, f.PermissionValues.Valid, "%s PermissionValues should be set", tc.label)
|
||||
assert.Equal(t, tc.expectedPermissionValues, f.PermissionValues.String, "%s PermissionValues", tc.label)
|
||||
assert.True(t, f.PermissionOptions.Valid, "%s PermissionOptions should be set", tc.label)
|
||||
assert.Equal(t, "sysadmin", f.PermissionOptions.String, "%s PermissionOptions", tc.label)
|
||||
}
|
||||
|
||||
// Verify: property value is unchanged (GroupID still references the same ID).
|
||||
var val struct {
|
||||
GroupID string `db:"groupid"`
|
||||
TargetID string `db:"targetid"`
|
||||
TargetType string `db:"targettype"`
|
||||
}
|
||||
require.NoError(t, master.Get(&val, "SELECT GroupID, TargetID, TargetType FROM PropertyValues WHERE ID = ?", valueID))
|
||||
assert.Equal(t, groupID, val.GroupID, "value GroupID should be unchanged")
|
||||
assert.Equal(t, targetUserID, val.TargetID, "value TargetID should be unchanged")
|
||||
assert.Equal(t, "user", val.TargetType, "value TargetType should be unchanged")
|
||||
|
||||
// Verify: the user attribute matview exists and includes the ObjectType
|
||||
// filter (user-type fields only). Since migration 000216 the single
|
||||
// AttributeView is split per object type; the user row lives in UserAttributeView.
|
||||
var viewDef string
|
||||
err = master.Get(&viewDef, "SELECT definition FROM pg_matviews WHERE matviewname = 'userattributeview'")
|
||||
require.NoError(t, err, "UserAttributeView should exist")
|
||||
assert.Contains(t, viewDef, "pf.objecttype", "view definition should filter by pf.ObjectType")
|
||||
|
||||
// Verify: materialized view contains expected data after refresh.
|
||||
_, err = master.ExecNoTimeout("REFRESH MATERIALIZED VIEW UserAttributeView")
|
||||
require.NoError(t, err, "refreshing UserAttributeView should succeed")
|
||||
|
||||
var viewRow struct {
|
||||
GroupID string `db:"groupid"`
|
||||
TargetID string `db:"targetid"`
|
||||
TargetType string `db:"targettype"`
|
||||
Attributes []byte `db:"attributes"`
|
||||
}
|
||||
err = master.Get(&viewRow, "SELECT GroupID, TargetID, TargetType, Attributes FROM UserAttributeView WHERE TargetID = ?", targetUserID)
|
||||
require.NoError(t, err, "UserAttributeView should contain a row for the target user")
|
||||
assert.Equal(t, groupID, viewRow.GroupID)
|
||||
assert.Equal(t, targetUserID, viewRow.TargetID)
|
||||
assert.Equal(t, "user", viewRow.TargetType)
|
||||
|
||||
// The text field value "hello" should appear under the field name "Text Field".
|
||||
var attrs map[string]json.RawMessage
|
||||
require.NoError(t, json.Unmarshal(viewRow.Attributes, &attrs))
|
||||
assert.JSONEq(t, `"hello"`, string(attrs["Text Field"]), "text field value should be materialized")
|
||||
|
||||
// ---- Run DOWN migration ----
|
||||
_, err = master.ExecNoTimeout(downSQL)
|
||||
require.NoError(t, err, "down migration should succeed")
|
||||
|
||||
// Verify: group name reverted.
|
||||
require.NoError(t, master.Get(&groupName, "SELECT Name FROM PropertyGroups WHERE ID = ?", groupID))
|
||||
assert.Equal(t, "custom_profile_attributes", groupName)
|
||||
|
||||
// Verify: fields reverted.
|
||||
for _, fid := range []string{fieldID1, fieldID2, fieldID3, deletedFieldID} {
|
||||
var f struct {
|
||||
ObjectType string `db:"objecttype"`
|
||||
TargetType string `db:"targettype"`
|
||||
PermissionField sql.NullString `db:"permissionfield"`
|
||||
PermissionValues sql.NullString `db:"permissionvalues"`
|
||||
PermissionOptions sql.NullString `db:"permissionoptions"`
|
||||
}
|
||||
require.NoError(t, master.Get(&f, "SELECT ObjectType, TargetType, PermissionField, PermissionValues, PermissionOptions FROM PropertyFields WHERE ID = ?", fid))
|
||||
assert.Equal(t, "", f.ObjectType, "field %s ObjectType should revert", fid)
|
||||
assert.Equal(t, "", f.TargetType, "field %s TargetType should revert", fid)
|
||||
assert.False(t, f.PermissionField.Valid, "field %s PermissionField should be NULL", fid)
|
||||
assert.False(t, f.PermissionValues.Valid, "field %s PermissionValues should be NULL", fid)
|
||||
assert.False(t, f.PermissionOptions.Valid, "field %s PermissionOptions should be NULL", fid)
|
||||
}
|
||||
|
||||
// Verify: value still unchanged after down migration.
|
||||
require.NoError(t, master.Get(&val, "SELECT GroupID, TargetID, TargetType FROM PropertyValues WHERE ID = ?", valueID))
|
||||
assert.Equal(t, groupID, val.GroupID, "value GroupID should remain unchanged after down")
|
||||
}
|
||||
|
||||
func TestMigration000185DownPreservesNonUserFields(t *testing.T) {
|
||||
logger := mlog.CreateTestLogger(t)
|
||||
|
||||
settings, err := makeSqlSettings(model.DatabaseDriverPostgres)
|
||||
if err != nil {
|
||||
t.Skip(err)
|
||||
}
|
||||
|
||||
store, err := New(*settings, logger, nil)
|
||||
require.NoError(t, err)
|
||||
defer store.Close()
|
||||
|
||||
master := store.GetMaster()
|
||||
|
||||
upSQL := readMigrationSQL(t, "000176_migrate_cpa_to_access_control.up.sql")
|
||||
downSQL := readMigrationSQL(t, "000176_migrate_cpa_to_access_control.down.sql")
|
||||
|
||||
groupID := model.NewId()
|
||||
_, err = master.Exec("INSERT INTO PropertyGroups (ID, Name) VALUES (?, ?)", groupID, "custom_profile_attributes")
|
||||
require.NoError(t, err)
|
||||
|
||||
t.Cleanup(func() {
|
||||
master.Exec("DELETE FROM PropertyFields WHERE GroupID = ?", groupID) //nolint:errcheck
|
||||
master.Exec("DELETE FROM PropertyGroups WHERE ID = ?", groupID) //nolint:errcheck
|
||||
})
|
||||
|
||||
now := model.GetMillis()
|
||||
|
||||
// Insert a legacy user field that the up migration will touch.
|
||||
userFieldID := model.NewId()
|
||||
_, err = master.Exec(
|
||||
`INSERT INTO PropertyFields
|
||||
(ID, GroupID, Name, Type, Attrs, TargetID, TargetType, ObjectType, CreateAt, UpdateAt, DeleteAt, Protected)
|
||||
VALUES (?, ?, 'Legacy User Field', 'text', '{}'::jsonb, '', '', '', ?, ?, 0, false)`,
|
||||
userFieldID, groupID, now, now,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Run UP migration — legacy user field gets ObjectType='user', TargetType='system'.
|
||||
_, err = master.ExecNoTimeout(upSQL)
|
||||
require.NoError(t, err, "up migration should succeed")
|
||||
|
||||
// Simulate a post-migration channel-scoped field created via the
|
||||
// generic property API against the (now renamed) access_control
|
||||
// group.
|
||||
channelFieldID := model.NewId()
|
||||
channelTargetID := model.NewId()
|
||||
_, err = master.Exec(
|
||||
`INSERT INTO PropertyFields
|
||||
(ID, GroupID, Name, Type, Attrs, TargetID, TargetType, ObjectType, PermissionField, PermissionValues, PermissionOptions, CreateAt, UpdateAt, DeleteAt, Protected)
|
||||
VALUES (?, ?, 'Channel Classification', 'select', '{}'::jsonb, ?, 'channel', 'channel', 'sysadmin', 'member', 'sysadmin', ?, ?, 0, false)`,
|
||||
channelFieldID, groupID, channelTargetID, now, now,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Run DOWN migration — must revert only user/system fields, not the channel one.
|
||||
_, err = master.ExecNoTimeout(downSQL)
|
||||
require.NoError(t, err, "down migration should succeed")
|
||||
|
||||
// The original user field reverts to legacy metadata.
|
||||
var userField struct {
|
||||
ObjectType string `db:"objecttype"`
|
||||
TargetType string `db:"targettype"`
|
||||
PermissionField sql.NullString `db:"permissionfield"`
|
||||
PermissionValues sql.NullString `db:"permissionvalues"`
|
||||
PermissionOptions sql.NullString `db:"permissionoptions"`
|
||||
}
|
||||
require.NoError(t, master.Get(&userField, "SELECT ObjectType, TargetType, PermissionField, PermissionValues, PermissionOptions FROM PropertyFields WHERE ID = ?", userFieldID))
|
||||
assert.Equal(t, "", userField.ObjectType, "user field ObjectType should revert")
|
||||
assert.Equal(t, "", userField.TargetType, "user field TargetType should revert")
|
||||
assert.False(t, userField.PermissionField.Valid, "user field PermissionField should be NULL")
|
||||
|
||||
// The post-migration channel field keeps its PSAv2 metadata intact.
|
||||
var channelField struct {
|
||||
ObjectType string `db:"objecttype"`
|
||||
TargetType string `db:"targettype"`
|
||||
TargetID string `db:"targetid"`
|
||||
PermissionField sql.NullString `db:"permissionfield"`
|
||||
PermissionValues sql.NullString `db:"permissionvalues"`
|
||||
PermissionOptions sql.NullString `db:"permissionoptions"`
|
||||
}
|
||||
require.NoError(t, master.Get(&channelField, "SELECT ObjectType, TargetType, TargetID, PermissionField, PermissionValues, PermissionOptions FROM PropertyFields WHERE ID = ?", channelFieldID))
|
||||
assert.Equal(t, "channel", channelField.ObjectType, "channel field ObjectType must survive rollback")
|
||||
assert.Equal(t, "channel", channelField.TargetType, "channel field TargetType must survive rollback")
|
||||
assert.Equal(t, channelTargetID, channelField.TargetID, "channel field TargetID must survive rollback")
|
||||
assert.True(t, channelField.PermissionField.Valid, "channel field PermissionField must survive rollback")
|
||||
assert.Equal(t, "sysadmin", channelField.PermissionField.String)
|
||||
assert.True(t, channelField.PermissionValues.Valid)
|
||||
assert.Equal(t, "member", channelField.PermissionValues.String)
|
||||
assert.True(t, channelField.PermissionOptions.Valid)
|
||||
assert.Equal(t, "sysadmin", channelField.PermissionOptions.String)
|
||||
}
|
||||
|
||||
func TestMigration000185NoOpOnFreshDB(t *testing.T) {
|
||||
logger := mlog.CreateTestLogger(t)
|
||||
|
||||
settings, err := makeSqlSettings(model.DatabaseDriverPostgres)
|
||||
if err != nil {
|
||||
t.Skip(err)
|
||||
}
|
||||
|
||||
store, err := New(*settings, logger, nil)
|
||||
require.NoError(t, err)
|
||||
defer store.Close()
|
||||
|
||||
master := store.GetMaster()
|
||||
|
||||
upSQL := readMigrationSQL(t, "000176_migrate_cpa_to_access_control.up.sql")
|
||||
downSQL := readMigrationSQL(t, "000176_migrate_cpa_to_access_control.down.sql")
|
||||
|
||||
// On a fresh database with no CPA group, both up and down should be
|
||||
// safe no-ops (the UPDATE statements match zero rows).
|
||||
_, err = master.ExecNoTimeout(upSQL)
|
||||
assert.NoError(t, err, "up migration should be a safe no-op on fresh DB")
|
||||
|
||||
// The attribute matviews exist in the final schema. Since migration 000216
|
||||
// the single AttributeView is split into per-object-type views.
|
||||
for _, view := range []string{"userattributeview", "channelattributeview"} {
|
||||
var viewExists bool
|
||||
require.NoError(t, master.Get(&viewExists, "SELECT EXISTS (SELECT 1 FROM pg_matviews WHERE matviewname = $1)", view))
|
||||
assert.True(t, viewExists, "%s should exist after up migration on fresh DB", view)
|
||||
}
|
||||
|
||||
_, err = master.ExecNoTimeout(downSQL)
|
||||
assert.NoError(t, err, "down migration should be a safe no-op on fresh DB")
|
||||
}
|
||||
Reference in New Issue
Block a user