diff --git a/plugins/auth-backend/migrations/20250707164600_user_created_at.js b/plugins/auth-backend/migrations/20250707164600_user_created_at.js index 214c70f858..f33ee02531 100644 --- a/plugins/auth-backend/migrations/20250707164600_user_created_at.js +++ b/plugins/auth-backend/migrations/20250707164600_user_created_at.js @@ -22,12 +22,25 @@ exports.up = async function up(knex) { await knex.schema.alterTable('user_info', table => { table.renameColumn('exp', 'updated_at'); + }); + // Sqlite doesn't support adding a column with non-constant default when table has data + // so we need to add it as nullable first, then set the value to the updated_at value + await knex.schema.alterTable('user_info', table => { + table.timestamp('created_at').nullable(); + }); + + await knex('user_info').update({ + created_at: knex.ref('updated_at'), + }); + + // Then alter to non-nullable and set the default to now() + await knex.schema.alterTable('user_info', table => { table .timestamp('created_at') .notNullable() .defaultTo(knex.fn.now()) - .comment('The creation time of the user info'); + .alter(); }); }; @@ -36,7 +49,7 @@ exports.up = async function up(knex) { */ exports.down = async function down(knex) { await knex.schema.alterTable('user_info', table => { - table.renameColumn('updated_at', 'exp'); table.dropColumn('created_at'); + table.renameColumn('updated_at', 'exp'); }); }; diff --git a/plugins/auth-backend/src/database/UserInfoDatabase.ts b/plugins/auth-backend/src/database/UserInfoDatabase.ts index a6c6f760d0..e183ef6af9 100644 --- a/plugins/auth-backend/src/database/UserInfoDatabase.ts +++ b/plugins/auth-backend/src/database/UserInfoDatabase.ts @@ -40,7 +40,7 @@ export class UserInfoDatabase { .insert({ user_entity_ref: userInfo.claims.sub as string, user_info: JSON.stringify(userInfo), - updated_at: DateTime.now().toSQL({ includeOffset: false }), + updated_at: DateTime.utc().toSQL(), }) .onConflict('user_entity_ref') .merge(); diff --git a/plugins/auth-backend/src/migrations.test.ts b/plugins/auth-backend/src/migrations.test.ts index df04a48de2..959239a872 100644 --- a/plugins/auth-backend/src/migrations.test.ts +++ b/plugins/auth-backend/src/migrations.test.ts @@ -136,8 +136,41 @@ describe('migrations', () => { const { created_at, updated_at } = await knex('user_info').first(); expect(updated_at).toBe(exp); - expect(created_at).toBeDefined(); + + await knex + .insert({ + user_entity_ref: 'user:default/backstage-user', + user_info, + updated_at: knex.fn.now(), + }) + .into('user_info') + .onConflict(['user_entity_ref']) + .merge(); + + await knex + .insert({ + user_entity_ref: 'user:default/backstage-user-2', + user_info, + updated_at: knex.fn.now(), + }) + .into('user_info'); + + await expect( + knex('user_info').select('created_at', 'updated_at'), + ).resolves.toEqual([ + { created_at: expect.any(String), updated_at: expect.any(String) }, + { created_at: expect.any(String), updated_at: expect.any(String) }, + ]); + + await migrateDownOnce(knex); + + await expect(knex('user_info').select('exp')).resolves.toEqual([ + { exp: expect.any(String) }, + { exp: expect.any(String) }, + ]); + + await knex.destroy(); }, ); });