diff --git a/database/migrations/0045-adapt_users_table_for_gradidoid.ts b/database/migrations/0045-adapt_users_table_for_gradidoid.ts index e33d5af1a..8f3f83f28 100644 --- a/database/migrations/0045-adapt_users_table_for_gradidoid.ts +++ b/database/migrations/0045-adapt_users_table_for_gradidoid.ts @@ -10,99 +10,6 @@ import { v4 as uuidv4 } from 'uuid' export async function upgrade(queryFn: (query: string, values?: any[]) => Promise>) { - /* - await queryFn(` - CREATE FUNCTION uuid_v4s() - RETURNS CHAR(36) - BEGIN - -- 1th and 2nd block are made of 6 random bytes - SET @h1 = HEX(RANDOM_BYTES(4)); - SET @h2 = HEX(RANDOM_BYTES(2)); - - -- 3th block will start with a 4 indicating the version, remaining is random - SET @h3 = SUBSTR(HEX(RANDOM_BYTES(2)), 2, 3); - - -- 4th block first nibble can only be 8, 9 A or B, remaining is random - SET @h4 = CONCAT(HEX(FLOOR(ASCII(RANDOM_BYTES(1)) / 64)+8), - SUBSTR(HEX(RANDOM_BYTES(2)), 2, 3)); - - -- 5th block is made of 6 random bytes - SET @h5 = HEX(RANDOM_BYTES(6)); - - -- Build the complete UUID - RETURN LOWER(CONCAT( - @h1, '-', @h2, '-4', @h3, '-', @h4, '-', @h5 - )); - END`) - - - - SELECT LOWER(CONCAT( - HEX(RANDOM_BYTES(4)), '-', - HEX(RANDOM_BYTES(2)), '-4', - SUBSTR(HEX(RANDOM_BYTES(2)), 2, 3), '-', - CONCAT(HEX(FLOOR(ASCII(RANDOM_BYTES(1)) / 64)+8),SUBSTR(HEX(RANDOM_BYTES(2)), 2, 3)), '-', - HEX(RANDOM_BYTES(6)) - - - await queryFn( - `CREATE FUNCTION UuidToBin(_uuid BINARY(36)) - RETURNS BINARY(16) - LANGUAGE SQL DETERMINISTIC CONTAINS SQL SQL SECURITY INVOKER - RETURN - UNHEX(CONCAT( - SUBSTR(_uuid, 15, 4), - SUBSTR(_uuid, 10, 4), - SUBSTR(_uuid, 1, 8), - SUBSTR(_uuid, 20, 4), - SUBSTR(_uuid, 25) )); - // - CREATE FUNCTION UuidFromBin(_bin BINARY(16)) - RETURNS BINARY(36) - LANGUAGE SQL DETERMINISTIC CONTAINS SQL SQL SECURITY INVOKER - RETURN - LCASE(CONCAT_WS('-', - HEX(SUBSTR(_bin, 5, 4)), - HEX(SUBSTR(_bin, 3, 2)), - HEX(SUBSTR(_bin, 1, 2)), - HEX(SUBSTR(_bin, 9, 2)), - HEX(SUBSTR(_bin, 11)) - )); - - // - DELIMITER ; - - - - CREATE FUNCTION BIN_TO_UUID(b BINARY(16)) - RETURNS CHAR(36) - BEGIN - DECLARE hexStr CHAR(32); - SET hexStr = HEX(b); - RETURN LOWER(CONCAT( - SUBSTR(hexStr, 1, 8), '-', - SUBSTR(hexStr, 9, 4), '-', - SUBSTR(hexStr, 13, 4), '-', - SUBSTR(hexStr, 17, 4), '-', - SUBSTR(hexStr, 21) - )); - END `) - - await queryFn(` DELIMITER ;`) - - await queryFn(`DELIMITER $$ - - CREATE FUNCTION UUID_TO_BIN(uuid CHAR(36)) - RETURNS BINARY(16) - BEGIN - RETURN UNHEX(REPLACE(uuid, '-', '')); - END - - $$ - - DELIMITER ;`) -*/ - await queryFn(` CREATE TABLE IF NOT EXISTS \`user_contacts\` ( \`id\` int(10) unsigned NOT NULL AUTO_INCREMENT, @@ -119,45 +26,35 @@ export async function upgrade(queryFn: (query: string, values?: any[]) => Promis \`deleted_at\` datetime NULL DEFAULT NULL, PRIMARY KEY (\`id\`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;`) - // console.log('user_contacts created...') // First add gradido_id as nullable column without Default await queryFn('ALTER TABLE `users` ADD COLUMN `gradido_id` CHAR(36) NULL AFTER `id`;') - // console.log('users.gradido_id added...\n') // Second update gradido_id with ensured unique uuidv4 - // console.log('search for all users with gradido_id is null...\n') const usersToUpdate = await queryFn('SELECT `id`, `gradido_id` FROM `users`') // WHERE 'u.gradido_id' is null`,) for (const id in usersToUpdate) { const user = usersToUpdate[id] - // console.log('found user: %s\n', user) let gradidoId = null let countIds = null do { gradidoId = uuidv4() - // console.log('uuid: %s\n', gradidoId) countIds = await queryFn( `SELECT COUNT(*) FROM \`users\` WHERE \`gradido_id\` = "${gradidoId}"`, ) - // console.log('found uuids: %d\n', countIds[0]) } while (countIds[0] > 0) await queryFn( `UPDATE \`users\` SET \`gradido_id\` = "${gradidoId}" WHERE \`id\` = "${user.id}"`, ) - // console.log('update user with id=%d and gradidoId=%s\n', user.id, gradidoId) } // third modify gradido_id to not nullable and unique await queryFn('ALTER TABLE `users` MODIFY COLUMN `gradido_id` CHAR(36) NOT NULL UNIQUE;') - // console.log('alter users.gradido_id to NOT NULL and UNIQUE...\n') await queryFn( 'ALTER TABLE `users` ADD COLUMN `alias` varchar(20) NULL UNIQUE AFTER `gradido_id`;', ) - // console.log('users.alias added...\n') await queryFn('ALTER TABLE `users` ADD COLUMN `email_id` int(10) NULL AFTER `email`;') - // console.log('users.email_id added...\n') // merge values from login_email_opt_in table with users.email in new user_contacts table await queryFn(` @@ -179,22 +76,31 @@ export async function upgrade(queryFn: (query: string, values?: any[]) => Promis login_email_opt_in as e WHERE u.id = e.user_id;`) - // console.log('user_contacts inserted...\n') // insert in users table the email_id of the new created email-contacts const contacts = await queryFn(`SELECT c.id, c.user_id FROM user_contacts as c`) for (const id in contacts) { const contact = contacts[id] - // console.log('found contact: %s\n', contact) await queryFn( `UPDATE users as u SET u.email_id = "${contact.id}" WHERE u.id = "${contact.user_id}"`, ) - // console.log('update users with id=%d and email_id=%d\n', contact.user_id, contact.id) } - // console.log('upgrade finished...\n') + // this step comes after verification and test + await queryFn('ALTER TABLE users DROP COLUMN email;') } export async function downgrade(queryFn: (query: string, values?: any[]) => Promise>) { + // reconstruct the previous email back from contacts to users table + await queryFn('ALTER TABLE users ADD COLUMN email varchar(255) NULL AFTER privkey;') + const contacts = await queryFn(`SELECT c.id, c.email, c.user_id FROM user_contacts as c`) + for (const id in contacts) { + const contact = contacts[id] + await queryFn( + `UPDATE users SET email = "${contact.email}" WHERE id = "${contact.user_id}" and email_id = "${contact.id}"`, + ) + } + await queryFn('ALTER TABLE users MODIFY COLUMN email varchar(255) NOT NULL UNIQUE;') + // write downgrade logic as parameter of queryFn await queryFn(`DROP TABLE IF EXISTS user_contacts;`)