Skip to content

Commit

Permalink
Add organizations and teams migration (#9)
Browse files Browse the repository at this point in the history
* feat(db): pre/post migration

* feat(db): add create orgs/teams migration
  • Loading branch information
aymanbagabas authored Nov 8, 2023
1 parent f7f521e commit a222f24
Show file tree
Hide file tree
Showing 11 changed files with 254 additions and 76 deletions.
1 change: 1 addition & 0 deletions pkg/db/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (

// Handler is a database handler.
type Handler interface {
DriverName() string
Rebind(string) string

Select(interface{}, string, ...interface{}) error
Expand Down
64 changes: 32 additions & 32 deletions pkg/db/migrate/0001_create_tables.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,71 +20,71 @@ const (
var createTables = Migration{
Version: createTablesVersion,
Name: createTablesName,
Migrate: func(ctx context.Context, tx *db.Tx) error {
Migrate: func(ctx context.Context, h db.Handler) error {
cfg := config.FromContext(ctx)

insert := "INSERT "

// Alter old tables (if exist)
// This is to support prior versions of Soft Serve v0.6
switch tx.DriverName() {
switch h.DriverName() {
case "sqlite3", "sqlite":
insert += "OR IGNORE "

hasUserTable := hasTable(tx, "user")
hasUserTable := hasTable(h, "user")
if hasUserTable {
if _, err := tx.ExecContext(ctx, "ALTER TABLE user RENAME TO user_old"); err != nil {
if _, err := h.ExecContext(ctx, "ALTER TABLE user RENAME TO user_old"); err != nil {
return err
}
}

if hasTable(tx, "public_key") {
if _, err := tx.ExecContext(ctx, "ALTER TABLE public_key RENAME TO public_key_old"); err != nil {
if hasTable(h, "public_key") {
if _, err := h.ExecContext(ctx, "ALTER TABLE public_key RENAME TO public_key_old"); err != nil {
return err
}
}

if hasTable(tx, "collab") {
if _, err := tx.ExecContext(ctx, "ALTER TABLE collab RENAME TO collab_old"); err != nil {
if hasTable(h, "collab") {
if _, err := h.ExecContext(ctx, "ALTER TABLE collab RENAME TO collab_old"); err != nil {
return err
}
}

if hasTable(tx, "repo") {
if _, err := tx.ExecContext(ctx, "ALTER TABLE repo RENAME TO repo_old"); err != nil {
if hasTable(h, "repo") {
if _, err := h.ExecContext(ctx, "ALTER TABLE repo RENAME TO repo_old"); err != nil {
return err
}
}
}

if err := migrateUp(ctx, tx, createTablesVersion, createTablesName); err != nil {
if err := migrateUp(ctx, h, createTablesVersion, createTablesName); err != nil {
return err
}

switch tx.DriverName() {
switch h.DriverName() {
case "sqlite3", "sqlite":

if _, err := tx.ExecContext(ctx, "PRAGMA foreign_keys = OFF"); err != nil {
if _, err := h.ExecContext(ctx, "PRAGMA foreign_keys = OFF"); err != nil {
return err
}

if hasTable(tx, "user_old") {
if hasTable(h, "user_old") {
sqlm := `
INSERT INTO users (id, username, admin, updated_at)
SELECT id, username, admin, updated_at FROM user_old;
`
if _, err := tx.ExecContext(ctx, sqlm); err != nil {
if _, err := h.ExecContext(ctx, sqlm); err != nil {
return err
}
}

if hasTable(tx, "public_key_old") {
if hasTable(h, "public_key_old") {
// Check duplicate keys
pks := []struct {
ID string `db:"id"`
PublicKey string `db:"public_key"`
}{}
if err := tx.SelectContext(ctx, &pks, "SELECT id, public_key FROM public_key_old"); err != nil {
if err := h.SelectContext(ctx, &pks, "SELECT id, public_key FROM public_key_old"); err != nil {
return err
}

Expand All @@ -100,53 +100,53 @@ var createTables = Migration{
INSERT INTO public_keys (id, user_id, public_key, created_at, updated_at)
SELECT id, user_id, public_key, created_at, updated_at FROM public_key_old;
`
if _, err := tx.ExecContext(ctx, sqlm); err != nil {
if _, err := h.ExecContext(ctx, sqlm); err != nil {
return err
}
}

if hasTable(tx, "repo_old") {
if hasTable(h, "repo_old") {
sqlm := `
INSERT INTO repos (id, name, project_name, description, private,mirror, hidden, created_at, updated_at, user_id)
SELECT id, name, project_name, description, private, mirror, hidden, created_at, updated_at, (
SELECT id FROM users WHERE admin = true ORDER BY id LIMIT 1
) FROM repo_old;
`
if _, err := tx.ExecContext(ctx, sqlm); err != nil {
if _, err := h.ExecContext(ctx, sqlm); err != nil {
return err
}
}

if hasTable(tx, "collab_old") {
if hasTable(h, "collab_old") {
sqlm := `
INSERT INTO collabs (id, user_id, repo_id, access_level, created_at, updated_at)
SELECT id, user_id, repo_id, ` + strconv.Itoa(int(access.ReadWriteAccess)) + `, created_at, updated_at FROM collab_old;
`
if _, err := tx.ExecContext(ctx, sqlm); err != nil {
if _, err := h.ExecContext(ctx, sqlm); err != nil {
return err
}
}

if _, err := tx.ExecContext(ctx, "PRAGMA foreign_keys = ON"); err != nil {
if _, err := h.ExecContext(ctx, "PRAGMA foreign_keys = ON"); err != nil {
return err
}
}

// Insert default user
insertUser := tx.Rebind(insert + "INTO users (username, admin, updated_at) VALUES (?, ?, CURRENT_TIMESTAMP)")
if _, err := tx.ExecContext(ctx, insertUser, "admin", true); err != nil {
insertUser := h.Rebind(insert + "INTO users (username, admin, updated_at) VALUES (?, ?, CURRENT_TIMESTAMP)")
if _, err := h.ExecContext(ctx, insertUser, "admin", true); err != nil {
return err
}

for _, k := range cfg.AdminKeys() {
query := insert + "INTO public_keys (user_id, public_key, updated_at) VALUES (?, ?, CURRENT_TIMESTAMP)"
if tx.DriverName() == "postgres" {
if h.DriverName() == "postgres" {
query += " ON CONFLICT DO NOTHING"
}

query = tx.Rebind(query)
query = h.Rebind(query)
ak := sshutils.MarshalAuthorizedKey(k)
if _, err := tx.ExecContext(ctx, query, 1, ak); err != nil {
if _, err := h.ExecContext(ctx, query, 1, ak); err != nil {
if errors.Is(db.WrapError(err), db.ErrDuplicateKey) {
continue
}
Expand All @@ -156,7 +156,7 @@ var createTables = Migration{

// Insert default settings
insertSettings := insert + "INTO settings (key, value, updated_at) VALUES (?, ?, CURRENT_TIMESTAMP)"
insertSettings = tx.Rebind(insertSettings)
insertSettings = h.Rebind(insertSettings)
settings := []struct {
Key string
Value string
Expand All @@ -167,14 +167,14 @@ var createTables = Migration{
}

for _, s := range settings {
if _, err := tx.ExecContext(ctx, insertSettings, s.Key, s.Value); err != nil {
if _, err := h.ExecContext(ctx, insertSettings, s.Key, s.Value); err != nil {
return fmt.Errorf("inserting default settings %q: %w", s.Key, err)
}
}

return nil
},
Rollback: func(ctx context.Context, tx *db.Tx) error {
return migrateDown(ctx, tx, createTablesVersion, createTablesName)
Rollback: func(ctx context.Context, h db.Handler) error {
return migrateDown(ctx, h, createTablesVersion, createTablesName)
},
}
8 changes: 4 additions & 4 deletions pkg/db/migrate/0002_webhooks.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ const (
var webhooks = Migration{
Name: webhooksName,
Version: webhooksVersion,
Migrate: func(ctx context.Context, tx *db.Tx) error {
return migrateUp(ctx, tx, webhooksVersion, webhooksName)
Migrate: func(ctx context.Context, h db.Handler) error {
return migrateUp(ctx, h, webhooksVersion, webhooksName)
},
Rollback: func(ctx context.Context, tx *db.Tx) error {
return migrateDown(ctx, tx, webhooksVersion, webhooksName)
Rollback: func(ctx context.Context, h db.Handler) error {
return migrateDown(ctx, h, webhooksVersion, webhooksName)
},
}
8 changes: 4 additions & 4 deletions pkg/db/migrate/0003_migrate_lfs_objects.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,17 @@ const (
var migrateLfsObjects = Migration{
Name: migrateLfsObjectsName,
Version: migrateLfsObjectsVersion,
Migrate: func(ctx context.Context, tx *db.Tx) error {
Migrate: func(ctx context.Context, h db.Handler) error {
cfg := config.FromContext(ctx)
logger := log.FromContext(ctx).WithPrefix("migrate_lfs_objects")

var repoIds []int64
if err := tx.Select(&repoIds, "SELECT id FROM repos"); err != nil {
if err := h.Select(&repoIds, "SELECT id FROM repos"); err != nil {
return err
}
for _, r := range repoIds {
var objs []models.LFSObject
if err := tx.Select(&objs, "SELECT * FROM lfs_objects WHERE repo_id = ?", r); err != nil {
if err := h.Select(&objs, "SELECT * FROM lfs_objects WHERE repo_id = ?", r); err != nil {
return err
}
objsp := filepath.Join(cfg.DataPath, "lfs", strconv.FormatInt(r, 10), "objects")
Expand All @@ -50,7 +50,7 @@ var migrateLfsObjects = Migration{
}
return nil
},
Rollback: func(ctx context.Context, tx *db.Tx) error {
Rollback: func(ctx context.Context, h db.Handler) error {
return nil
},
}
Expand Down
31 changes: 27 additions & 4 deletions pkg/db/migrate/0004_create_orgs_teams.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package migrate

import (
"context"
"strings"

"github.com/charmbracelet/soft-serve/pkg/db"
)
Expand All @@ -14,10 +15,32 @@ const (
var createOrgsTeams = Migration{
Name: createOrgsTeamsName,
Version: createOrgsTeamsVersion,
Migrate: func(ctx context.Context, tx *db.Tx) error {
return migrateUp(ctx, tx, createOrgsTeamsVersion, createOrgsTeamsName)
PreMigrate: func(ctx context.Context, h db.Handler) error {
if strings.HasPrefix(h.DriverName(), "sqlite") {
if _, err := h.ExecContext(ctx, "PRAGMA foreign_keys = OFF;"); err != nil {
return err
}
if _, err := h.ExecContext(ctx, "PRAGMA legacy_alter_table = ON;"); err != nil {
return err
}
}
return nil
},
Rollback: func(ctx context.Context, tx *db.Tx) error {
return migrateDown(ctx, tx, createOrgsTeamsVersion, createOrgsTeamsName)
PostMigrate: func(ctx context.Context, h db.Handler) error {
if strings.HasPrefix(h.DriverName(), "sqlite") {
if _, err := h.ExecContext(ctx, "PRAGMA foreign_keys = ON;"); err != nil {
return err
}
if _, err := h.ExecContext(ctx, "PRAGMA legacy_alter_table = OFF;"); err != nil {
return err
}
}
return nil
},
Migrate: func(ctx context.Context, h db.Handler) error {
return migrateUp(ctx, h, createOrgsTeamsVersion, createOrgsTeamsName)
},
Rollback: func(ctx context.Context, h db.Handler) error {
return migrateDown(ctx, h, createOrgsTeamsVersion, createOrgsTeamsName)
},
}
4 changes: 4 additions & 0 deletions pkg/db/migrate/0004_create_orgs_teams_postgres.up.sql
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,10 @@ ALTER TABLE users DROP COLUMN username;

-- Add org_id to repos table
ALTER TABLE repos ADD COLUMN org_id INTEGER;
ALTER TABLE repos ADD CONSTRAINT org_id_fk
FOREIGN KEY(org_id) REFERENCES organizations(id)
ON DELETE CASCADE
ON UPDATE CASCADE;

-- Alter user_id nullness in repos table
ALTER TABLE repos ALTER COLUMN user_id DROP NOT NULL;
Expand Down
Empty file.
Loading

0 comments on commit a222f24

Please sign in to comment.