Skip to content

Commit

Permalink
feat: Add migration for UUID mapping
Browse files Browse the repository at this point in the history
  • Loading branch information
hperl committed Jan 21, 2022
1 parent bd9b2e0 commit fb7af04
Show file tree
Hide file tree
Showing 3 changed files with 142 additions and 1 deletion.
2 changes: 1 addition & 1 deletion internal/persistence/sql/migrations/single_table_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ func TestToSingleTableMigrator_HasLegacyTable(t *testing.T) {

ln, err := m.LegacyNamespaces(ctx)
require.NoError(t, err)
assert.Equal(t, nspaces, ln)
assert.ElementsMatch(t, nspaces, ln)
})
})
}
Expand Down
56 changes: 56 additions & 0 deletions internal/persistence/sql/migrations/uuid_mapping.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package migrations

import (
"context"

"github.com/gobuffalo/pop/v6"
"github.com/gofrs/uuid"

"github.com/ory/keto/internal/persistence/sql"
)

type (
toUUIDMappingMigrator struct {
d dependencies
}
)

// NewToUUIDMappingMigrator creates a new UUID mapping migrator.
func NewToUUIDMappingMigrator(d dependencies) *toUUIDMappingMigrator {
return &toUUIDMappingMigrator{d: d}
}

// MigrateUUIDMappings migrates to UUID-mapped subject IDs for all relation
// tuples in the database.
func (m *toUUIDMappingMigrator) MigrateUUIDMappings(ctx context.Context) error {
p, ok := m.d.Persister().(*sql.Persister)
if !ok {
panic("got unexpected persister")
}

return p.Transaction(ctx, func(ctx context.Context, c *pop.Connection) error {
var relationTuples []*sql.RelationTuple

if err := p.Connection(ctx).All(&relationTuples); err != nil {
return err
}

for _, rt := range relationTuples {
_, err := uuid.FromString(rt.SubjectID.String)
if err == nil || !rt.SubjectID.Valid || rt.SubjectID.String == "" {
continue
}

id := uuid.Must(uuid.NewV4())
if err := p.AddUUIDMapping(ctx, id, rt.SubjectID.String); err != nil {
return err
}

rt.SubjectID.String = id.String()
if err := c.Update(rt); err != nil {
return err
}
}
return nil
})
}
85 changes: 85 additions & 0 deletions internal/persistence/sql/migrations/uuid_mapping_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package migrations

import (
"context"
dbsql "database/sql"
"testing"
"time"

"github.com/gofrs/uuid"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/ory/keto/internal/driver"
"github.com/ory/keto/internal/persistence/sql"
"github.com/ory/keto/internal/x/dbx"
)

func TestToUUIDMappingMigrator(t *testing.T) {
const debugOnDisk = false

for _, dsn := range dbx.GetDSNs(t, debugOnDisk) {
t.Run("db="+dsn.Name, func(t *testing.T) {
ctx := context.Background()
r := driver.NewTestRegistry(t, dsn)
m := NewToUUIDMappingMigrator(r)
p := m.d.Persister().(*sql.Persister)
conn := p.Connection(ctx)

testCases := []struct {
name string
rt *sql.RelationTuple
expectMapping bool
}{{
name: "with string subject",
rt: &sql.RelationTuple{
ID: uuid.Must(uuid.NewV4()),
SubjectID: dbsql.NullString{String: "a", Valid: true},
CommitTime: time.Now(),
},
expectMapping: true,
}, {
name: "with null subject",
rt: &sql.RelationTuple{
ID: uuid.Must(uuid.NewV4()),
SubjectID: dbsql.NullString{String: "", Valid: false},
SubjectSetNamespaceID: dbsql.NullInt32{Int32: 0, Valid: true},
SubjectSetObject: dbsql.NullString{String: "obj", Valid: true},
SubjectSetRelation: dbsql.NullString{String: "rel", Valid: true},
CommitTime: time.Now(),
},
expectMapping: false,
}, {
name: "with UUID subject",
rt: &sql.RelationTuple{
ID: uuid.Must(uuid.NewV4()),
SubjectID: dbsql.NullString{String: uuid.Must(uuid.NewV4()).String(), Valid: true},
CommitTime: time.Now(),
},
expectMapping: false,
}}

for _, tc := range testCases {
t.Run("case="+tc.name, func(t *testing.T) {
require.NoError(t, conn.Create(tc.rt))
require.NoError(t, m.MigrateUUIDMappings(ctx))

newRt := &sql.RelationTuple{}
require.NoError(t, conn.Find(newRt, tc.rt.ID))

if tc.expectMapping {
// Check that a mapping was created
mapping := &sql.UUIDMapping{}
require.NoError(t, conn.Find(mapping, newRt.SubjectID))
assert.NotEqual(t, tc.rt.SubjectID, newRt.SubjectID)
assert.Equal(t, tc.rt.SubjectID.String, mapping.StringRepresentation)
} else {
// Nothing should have changed (ignoring commit time)
newRt.CommitTime = tc.rt.CommitTime
assert.Equal(t, tc.rt, newRt)
}
})
}
})
}
}

0 comments on commit fb7af04

Please sign in to comment.