node-casbin / sequelize-adapter

Sequelize adapter for Casbin
https://github.com/casbin/node-casbin
Apache License 2.0
64 stars 34 forks source link

Multiple adapter instance based on postgres schema(already opened before) #78

Closed tsoultanopoulos closed 1 year ago

tsoultanopoulos commented 1 year ago

It appears that this issue has already been raised and supposedly, it was solved with this PR, but even after installing the latest version of the adapter(v2.6.1), the problem still persists. In the previous issue (as this) provided three sets of options for connecting to different schemas in the same database. However, when running the code, the last adapter seems to override the other two, preventing you from opening different database connections. The only difference among the options is the schema.

const pgOptions1 = {
  username: 'some_user',
  host: 'some_host',
  port: XXXX,
  password: 'some_password',
  database: 'some_db',
  schema: "tenant1",
  logging: false,
  dialect: 'postgres'
};

const pgOptions2 = {
  username: 'some_user',
  host: 'some_host',
  port: XXXX,
  password: 'some_password',
  database: 'some_db',
  schema: "tenant2",
  logging: false,
  dialect: 'postgres'
};

const pgOptions3 = {
  username: 'some_user',
  host: 'some_host',
  port: XXXX,
  password: 'some_password',
  database: 'some_db',
  schema: "tenant3",
  logging: false,
  dialect: 'postgres'
};

async function run() {
  const casbinAdapter1 = await SequelizeAdapter.newAdapter(pgOptions1);
  const casbinAdapter2 = await SequelizeAdapter.newAdapter(pgOptions2);
  const casbinAdapter3 = await SequelizeAdapter.newAdapter(pgOptions3);

  const enforcer1 = await casbin.newEnforcer('abac_model.conf', casbinAdapter1);
  const enforcer2 = await casbin.newEnforcer('abac_model.conf', casbinAdapter2);
  const enforcer3 = await casbin.newEnforcer('abac_model.conf', casbinAdapter3);

  const p = ['sub', 'obj', 'act'];
 // this add policy at tenant3 
  await enforcer2.addPolicy(...p);

}

run().catch(console.error);

Could you please verify if the problem is resolved?

Thank you in advance

casbin-bot commented 1 year ago

@nodece @Zxilly @Shivansh-yadav13

tsoultanopoulos commented 1 year ago

Hello,

I have noticed that when creating three or more instances of SequelizeAdapter, the options set in the last adapter instance override the options of the previous ones. Upon reviewing the source code, I believe that the root cause of this issue is the updateCasbinRule function in casbinRule.ts module. This function modifies the global state by altering the tableName and schema options of the CasbinRule class, which is shared across all instances of SequelizeAdapter.

Here’s what happens step by step:

  1. When the first SequelizeAdapter instance is created, it sets the tableName and schema options in the CasbinRule class.
  2. Subsequently, when another SequelizeAdapter instance is created, it also modifies the tableName and schema options in the CasbinRule class, effectively overriding the options that were set by the previous instances.

To resolve this issue, I propose ensuring that each instance of SequelizeAdapter has its own separate instance of the CasbinRule model, so they are not shared among different adapters. This might involve refactoring the CasbinRule to be a non-static class member of SequelizeAdapter. Consequently, each time a new adapter is instantiated, it would have its own CasbinRule instance with independent options.

Please let me know if there's any additional information I can provide, or if there's another workaround for this issue.

Thank you! BR