Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,77 +3,59 @@
/** @type {import('sequelize-cli').Migration} */
module.exports = {
async up(queryInterface, Sequelize) {
// Add foreign key constraint for feature_code
await queryInterface.addConstraint('feature_role_mapping', {
fields: ['feature_code'],
type: 'foreign key',
name: 'fk_feature_role_mapping_feature_code',
references: {
table: 'features',
field: 'code',
},
onUpdate: 'CASCADE',
onDelete: 'CASCADE',
})

// Add foreign key constraint for tenant_code
await queryInterface.addConstraint('feature_role_mapping', {
fields: ['tenant_code'],
type: 'foreign key',
name: 'fk_feature_role_mapping_tenant_code',
references: {
table: 'tenants',
field: 'code',
},
onUpdate: 'CASCADE',
onDelete: 'CASCADE',
})

// Add composite foreign key for organization_code (organization_code, tenant_code) -> organizations (code, tenant_code)
await queryInterface.sequelize.query(`
ALTER TABLE feature_role_mapping
ADD CONSTRAINT fk_feature_role_mapping_organization_code
FOREIGN KEY (organization_code, tenant_code)
REFERENCES organizations (code, tenant_code)
ON UPDATE CASCADE
ON DELETE CASCADE;
`)

// Add composite foreign key for role_title (tenant_code, role_title) -> user_roles (tenant_code, title)
//commenting this as of now because of issue in user_roles table which is using the organization_id as foreign key
// await queryInterface.sequelize.query(`
// ALTER TABLE feature_role_mapping
// ADD CONSTRAINT fk_feature_role_mapping_role_title
// FOREIGN KEY (tenant_code, role_title)
// REFERENCES user_roles (tenant_code, title)
// ON UPDATE CASCADE
// ON DELETE NO ACTION;
// `)

// Unique constraint for feature_code, role_title, organization_code, tenant_code
await queryInterface.sequelize.query(`
CREATE UNIQUE INDEX feature_role_org_tenant_unique
ON feature_role_mapping (feature_code, role_title, organization_code, tenant_code)
WHERE deleted_at IS NULL;
`)

await queryInterface.sequelize.query(`
ALTER TABLE feature_role_mapping
ADD CONSTRAINT fk_org_feature_role_mapping_organization_code
FOREIGN KEY (feature_code, tenant_code, organization_code)
REFERENCES organization_features (feature_code, tenant_code, organization_code)
ON UPDATE CASCADE
ON DELETE CASCADE;
`)
try {
await queryInterface.addConstraint('feature_role_mapping', {
fields: ['feature_code'],
type: 'foreign key',
name: 'fk_feature_role_mapping_feature_code',
references: { table: 'features', field: 'code' },
onUpdate: 'NO ACTION',
onDelete: 'NO ACTION',
})
// Composite FK: (organization_code, tenant_code) → organizations(code, tenant_code)
await queryInterface.sequelize.query(`
ALTER TABLE feature_role_mapping
ADD CONSTRAINT fk_feature_role_mapping_organization_code
FOREIGN KEY (organization_code, tenant_code)
REFERENCES organizations (code, tenant_code)
ON UPDATE CASCADE
ON DELETE CASCADE;
`)

// Unique index ignoring soft-deleted rows
await queryInterface.sequelize.query(`
CREATE UNIQUE INDEX feature_role_org_tenant_unique
ON feature_role_mapping (feature_code, role_title, organization_code, tenant_code)
WHERE deleted_at IS NULL;
`)

// Composite FK: (feature_code, tenant_code, organization_code) → organization_features(...)
await queryInterface.sequelize.query(`
ALTER TABLE feature_role_mapping
ADD CONSTRAINT fk_org_feature_role_mapping_organization_code
FOREIGN KEY (feature_code, tenant_code, organization_code)
REFERENCES organization_features (feature_code, tenant_code, organization_code)
ON UPDATE CASCADE
ON DELETE CASCADE;
`)
} catch (error) {
console.error('Migration failed:', error)
throw error // important so sequelize knows migration failed
}
},

async down(queryInterface, Sequelize) {
// Drop foreign key constraints
await queryInterface.removeConstraint('feature_role_mapping', 'fk_feature_role_mapping_tenant_code')
await queryInterface.removeConstraint('feature_role_mapping', 'fk_feature_role_mapping_organization_code')
// Remove constraints safely
await queryInterface
.removeConstraint('feature_role_mapping', 'fk_feature_role_mapping_organization_code')
.catch(() => {})
// await queryInterface.removeConstraint('feature_role_mapping', 'fk_feature_role_mapping_role_title')
await queryInterface.removeConstraint('feature_role_mapping', 'fk_feature_role_mapping_feature_code')
await queryInterface.removeConstraint('feature_role_mapping', 'fk_org_feature_role_mapping_organization_code')
await queryInterface
.removeConstraint('feature_role_mapping', 'fk_feature_role_mapping_feature_code')
.catch(() => {})
await queryInterface
.removeConstraint('feature_role_mapping', 'fk_org_feature_role_mapping_organization_code')
.catch(() => {})

await queryInterface.sequelize.query('DROP INDEX IF EXISTS feature_role_org_tenant_unique;')
},
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
'use strict'

/** @type {import('sequelize-cli').Migration} */
module.exports = {
async up(queryInterface) {
try {
console.log('Removing existing foreign key constraints...')

// Remove the existing FK constraint: feature_code → features(code)
// This constraint is incompatible with Citus distributed database and is being permanently removed
await queryInterface.sequelize
.query(
`
ALTER TABLE feature_role_mapping
DROP CONSTRAINT IF EXISTS fk_feature_role_mapping_feature_code;
`
)
.catch(() => {
console.warn(
'Warning: fk_feature_role_mapping_feature_code constraint not found or already removed'
)
})

// Remove the existing composite FK: (organization_code, tenant_code) → organizations
await queryInterface.sequelize
.query(
`
ALTER TABLE feature_role_mapping
DROP CONSTRAINT IF EXISTS fk_feature_role_mapping_organization_code;
`
)
.catch(() => {
console.warn(
'Warning: fk_feature_role_mapping_organization_code constraint not found or already removed'
)
})

// Remove the existing composite FK: (feature_code, tenant_code, organization_code) → organization_features
await queryInterface.sequelize
.query(
`
ALTER TABLE feature_role_mapping
DROP CONSTRAINT IF EXISTS fk_org_feature_role_mapping_organization_code;
`
)
.catch(() => {
console.warn(
'Warning: fk_org_feature_role_mapping_organization_code constraint not found or already removed'
)
})

console.log('Creating new foreign key constraints with NO ACTION...')

// Recreate composite FK: (organization_code, tenant_code) → organizations with NO ACTION
await queryInterface.sequelize.query(`
ALTER TABLE feature_role_mapping
ADD CONSTRAINT fk_feature_role_mapping_organization_code
FOREIGN KEY (organization_code, tenant_code)
REFERENCES organizations (code, tenant_code)
ON UPDATE NO ACTION
ON DELETE NO ACTION;
`)

// Recreate composite FK: (feature_code, tenant_code, organization_code) → organization_features with NO ACTION
await queryInterface.sequelize.query(`
ALTER TABLE feature_role_mapping
ADD CONSTRAINT fk_org_feature_role_mapping_organization_code
FOREIGN KEY (feature_code, tenant_code, organization_code)
REFERENCES organization_features (feature_code, tenant_code, organization_code)
ON UPDATE NO ACTION
ON DELETE NO ACTION;
`)

console.log('Foreign key constraints successfully modified to NO ACTION')
} catch (error) {
console.error('Migration failed:', error)
throw error
}
},

async down(queryInterface) {
try {
console.log('Removing NO ACTION constraints (manual recreation of CASCADE constraints may be needed)...')

// Remove NO ACTION constraints
await queryInterface.sequelize
.query(
`
ALTER TABLE feature_role_mapping
DROP CONSTRAINT IF EXISTS fk_feature_role_mapping_feature_code;
`
)
.catch(() => {})

await queryInterface.sequelize
.query(
`
ALTER TABLE feature_role_mapping
DROP CONSTRAINT IF EXISTS fk_feature_role_mapping_organization_code;
`
)
.catch(() => {})

await queryInterface.sequelize
.query(
`
ALTER TABLE feature_role_mapping
DROP CONSTRAINT IF EXISTS fk_org_feature_role_mapping_organization_code;
`
)
.catch(() => {})

console.log('Constraints removed. Run previous migration to restore CASCADE constraints.')
} catch (error) {
console.error('Rollback failed:', error)
throw error
}
},
}
5 changes: 0 additions & 5 deletions src/database/models/Feature.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,6 @@ module.exports = (sequelize, DataTypes) => {
foreignKey: 'feature_code',
as: 'organization_features',
})
Feature.hasMany(models.FeatureRoleMapping, {
foreignKey: 'feature_code',
sourceKey: 'code',
as: 'featureRoleMappings',
})
}

return Feature
Expand Down
3 changes: 1 addition & 2 deletions src/services/account.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ module.exports = class AccountHelper {
* @param {Object} deviceInfo - Device information
* @returns {JSON} - returns account creation details.
*/

static async create(bodyData, deviceInfo, domain) {
const projection = ['password']
let isInvitedUserId = false
Expand Down Expand Up @@ -1048,7 +1047,7 @@ module.exports = class AccountHelper {
responseCode: 'CLIENT_ERROR',
})
}
const user = await userQueries.findUserWithOrganization(query, {}, tenantDomain.tenant_code)
const user = await userQueries.findUserWithOrganization(query, {}, true)

if (!user) {
return responses.failureResponse({
Expand Down