From 689d560eb17da613d057097545b8d205e32c22e4 Mon Sep 17 00:00:00 2001
From: Sumner Evans <me@sumnerevans.com>
Date: Mon, 7 Mar 2022 21:03:24 -0700
Subject: [PATCH] move script: update for new contacts table

---
 cmd/signaldctl/cmd/db/migrate.go  | 67 +++++++++++++++++++++++++++++--
 cmd/signaldctl/cmd/db/postgres.go | 12 ++++++
 2 files changed, 75 insertions(+), 4 deletions(-)

diff --git a/cmd/signaldctl/cmd/db/migrate.go b/cmd/signaldctl/cmd/db/migrate.go
index 0bb6c9b..8aa5c43 100644
--- a/cmd/signaldctl/cmd/db/migrate.go
+++ b/cmd/signaldctl/cmd/db/migrate.go
@@ -148,6 +148,12 @@ var (
 			}
 			log.Println("moved group credentials table")
 
+			if err := moveContacts(source, dest); err != nil {
+				log.Println("error migrating group credentials table")
+				return err
+			}
+			log.Println("moved contacts table")
+
 			if err := os.Remove(sqlitePath); err != nil {
 				log.Println("error deleting sqlite file")
 				return err
@@ -159,14 +165,26 @@ var (
 )
 
 func verifyMigration(source *sql.DB) error {
-	rows, err := source.Query("SELECT * FROM flyway_schema_history WHERE version = 11")
+	// Lower bound of the database state.
+	rows, err := source.Query("SELECT * FROM flyway_schema_history WHERE version = 12")
 	if err != nil {
 		return err
 	}
 	defer rows.Close()
 
 	if !rows.Next() {
-		return errors.New("source database is not up to date! Please update to signald 0.17.0-16-5101c6ef and start it to move the sqlite database to an acceptable format")
+		return errors.New("source database is not up to date! Please update signald and start it to move the sqlite database to an acceptable format")
+	}
+
+	// Upper bound of the database state
+	rows, err = source.Query("SELECT * FROM flyway_schema_history WHERE version = 13")
+	if err != nil {
+		return err
+	}
+	defer rows.Close()
+
+	if rows.Next() {
+		return errors.New("source database is too new! Please update signaldctl to the latest version")
 	}
 	return nil
 }
@@ -177,8 +195,16 @@ func createSchema(dest *sql.DB) error {
 		return err
 	}
 
-	_, err = dest.Exec("INSERT INTO flyway_schema_history (installed_rank, version, description, type, script, checksum, installed_by, execution_time, success) VALUES ($1, $2, $3, $4, $5, $6, current_user, $7, $8)",
-		1, 1, "create tables", "SQL", "V1__create_tables.sql", -1247750968, 0, true)
+	_, err = dest.Exec(`
+        INSERT INTO flyway_schema_history
+               (installed_rank, version, description, type, script, checksum, installed_by, execution_time, success)
+        VALUES ($1, $2, $3, $4, $5, $6, current_user, $7, $8),
+               ($9, $10, $11, $12, $13, $14, current_user, $15, $16)
+        `,
+		// Row 1
+		1, 1, "create tables", "SQL", "V1__create_tables.sql", -1247750968, 0, true,
+		// Row 2
+		2, 12, "create contacts table", "SQL", "V12__create_contacts_table.sql", -852729911, 0, true)
 	return err
 }
 
@@ -541,3 +567,36 @@ func moveGroupCredentials(source *sql.DB, dest *sql.DB) error {
 	}
 	return nil
 }
+
+func moveContacts(source *sql.DB, dest *sql.DB) error {
+	rows, err := source.Query("SELECT account_uuid, recipient, name, color, profile_key, message_expiration_time, inbox_position FROM contacts")
+	if err != nil {
+		return err
+	}
+	defer rows.Close()
+
+	for rows.Next() {
+		var (
+			accountUUID             uuid.UUID
+			recipient               int64
+			name                    sql.NullString
+			color                   sql.NullString
+			profile_key             []byte
+			message_expiration_time sql.NullInt64
+			inbox_position          sql.NullInt64
+		)
+		err = rows.Scan(&accountUUID, &recipient, &name, &color, &profile_key, &message_expiration_time, &inbox_position)
+		if err != nil {
+			return err
+		}
+		_, err = dest.Exec(`
+            INSERT INTO signald_contacts
+                        (account_uuid, recipient, name, color, profile_key, message_expiration_time, inbox_position)
+                 VALUES ($1, $2, $3, $4, $5, $6, $7)
+        `, accountUUID, recipient, name, color, profile_key, message_expiration_time, inbox_position)
+		if err != nil {
+			return err
+		}
+	}
+	return nil
+}
diff --git a/cmd/signaldctl/cmd/db/postgres.go b/cmd/signaldctl/cmd/db/postgres.go
index af2776a..47f7388 100644
--- a/cmd/signaldctl/cmd/db/postgres.go
+++ b/cmd/signaldctl/cmd/db/postgres.go
@@ -215,5 +215,17 @@ var (
 		execution_time integer NOT NULL,
 		success boolean NOT NULL
 	);
+
+    CREATE TABLE signald_contacts (
+        account_uuid            UUID        NOT NULL    REFERENCES signald_accounts(uuid) ON DELETE CASCADE,
+        recipient               INTEGER     NOT NULL    REFERENCES signald_recipients(rowid) ON DELETE CASCADE,
+        name                    TEXT,
+        color                   TEXT,
+        profile_key             BYTEA,
+        message_expiration_time INTEGER,
+        inbox_position          INTEGER,
+
+        PRIMARY KEY (account_uuid, recipient)
+    );
 `
 )