From af3208b9650b2f49b124b1bfb63496e0751a443d Mon Sep 17 00:00:00 2001 From: Alexander Borg Date: Mon, 22 Sep 2025 05:39:31 +0200 Subject: [PATCH] Fix jwt-token --- .../20250820000001-create-initial-tables.js | 8 ++ ...0922000001-add-heartbeat-tenant-support.js | 78 +++++++++++++++++++ 2 files changed, 86 insertions(+) create mode 100644 server/migrations/20250922000001-add-heartbeat-tenant-support.js diff --git a/server/migrations/20250820000001-create-initial-tables.js b/server/migrations/20250820000001-create-initial-tables.js index b42d91b..1e9f91c 100644 --- a/server/migrations/20250820000001-create-initial-tables.js +++ b/server/migrations/20250820000001-create-initial-tables.js @@ -310,6 +310,14 @@ module.exports = { }, comment: 'ID of the device sending heartbeat' }, + tenant_id: { + type: Sequelize.UUID, + allowNull: true, // Nullable for backward compatibility + references: { + model: 'tenants', + key: 'id' + }, + }, device_key: { type: Sequelize.STRING, allowNull: true, diff --git a/server/migrations/20250922000001-add-heartbeat-tenant-support.js b/server/migrations/20250922000001-add-heartbeat-tenant-support.js new file mode 100644 index 0000000..b24d232 --- /dev/null +++ b/server/migrations/20250922000001-add-heartbeat-tenant-support.js @@ -0,0 +1,78 @@ +/** + * Migration: Add tenant_id to heartbeats table + * This migration adds tenant_id field to heartbeats for multi-tenant support + */ + +'use strict'; + +module.exports = { + async up(queryInterface, Sequelize) { + try { + // Check if heartbeats table exists first + const tables = await queryInterface.showAllTables(); + if (!tables.includes('heartbeats')) { + console.log('⚠️ Heartbeats table does not exist yet, skipping heartbeat tenant support migration...'); + return; + } + + // Check if tenant_id column already exists + const tableDescription = await queryInterface.describeTable('heartbeats'); + + if (!tableDescription.tenant_id) { + // Add index for tenant_id for better query performance + try { + await queryInterface.addIndex('heartbeats', ['tenant_id'], { + name: 'heartbeats_tenant_id_idx' + }); + console.log('✅ Added index on heartbeats.tenant_id'); + } catch (error) { + if (error.parent?.code === '42P07') { // Index already exists + console.log('⚠️ Index heartbeats_tenant_id already exists, skipping...'); + } else { + throw error; + } + } + + // Associate existing heartbeats with default tenant (backward compatibility) + const defaultTenant = await queryInterface.sequelize.query( + 'SELECT id FROM tenants WHERE slug = :slug', + { + replacements: { slug: 'default' }, + type: Sequelize.QueryTypes.SELECT + } + ); + + if (defaultTenant.length > 0) { + await queryInterface.sequelize.query( + 'UPDATE heartbeats SET tenant_id = :tenantId WHERE tenant_id IS NULL', + { + replacements: { tenantId: defaultTenant[0].id }, + type: Sequelize.QueryTypes.UPDATE + } + ); + console.log('✅ Associated existing heartbeats with default tenant'); + } + + console.log('✅ Added tenant_id field to heartbeats table'); + } else { + console.log('⚠️ Column tenant_id already exists in heartbeats table, skipping...'); + } + } catch (error) { + console.log('⚠️ Migration skipped - tables may not exist yet:', error.message); + // Don't throw error, just skip this migration if tables don't exist + } + }, + + async down(queryInterface, Sequelize) { + // Remove index + try { + await queryInterface.removeIndex('heartbeats', 'heartbeats_tenant_id_idx'); + } catch (error) { + console.log('⚠️ Index heartbeats_tenant_id_idx does not exist, skipping...'); + } + + // Remove column + await queryInterface.removeColumn('heartbeats', 'tenant_id'); + console.log('✅ Removed tenant_id field from heartbeats table'); + } +}; \ No newline at end of file