Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Oct 11, 2025

Problem

Users integrating casbin.js with Go backends using CasbinJsGetPermissionForUser were unable to use manual mode correctly. The Go function exports permissions in an "enforcer format" containing model (m) and policies (p), but setPermission() only supported a simple action-object format like {"read": ["data1", "data2"], "write": ["data1"]}.

This caused permission checks to return false when they should return true:

const authorizer = new casbinjs.Authorizer('manual');

// Response from Go's CasbinJsGetPermissionForUser contains {m: "...", p: [...]}
authorizer.setPermission(responseFromApi); // Didn't work!

authorizer.can('read', 'data1').then((can) => {
  console.log(can); // false (incorrect!)
});

Solution

Enhanced setPermission() to automatically detect and handle both permission formats:

  1. Auto-detection: Checks if the data contains m (model) or p (policies) keys to identify enforcer format
  2. Smart routing: Uses initEnforcer() for enforcer format, or Permission.load() for simple format
  3. Enhanced manual mode: The can() method now checks if an enforcer is available in manual mode
  4. User support: setUser() now sets the user property in all modes (required for enforcer-based permissions)

Changes

  • Made setPermission() async to support enforcer initialization
  • Added format detection logic to route to appropriate handler
  • Updated can() to check for enforcer in manual mode before falling back to simple permission check
  • Fixed setUser() to work properly in manual mode with enforcer format
  • Added comprehensive tests for both formats
  • Updated README with usage examples for both formats

Usage

const authorizer = new casbinjs.Authorizer('manual');

// Now works with enforcer format from Go backend!
await authorizer.setPermission(responseFromGoAPI);
await authorizer.setUser('alice');

authorizer.can('read', 'data1').then(can => {
  console.log(can); // true (correct!)
});

// Still works with simple format (backward compatible)
await authorizer.setPermission({
  read: ['data1', 'data2'],
  write: ['data1']
});

Breaking Change

⚠️ setPermission() is now async and returns Promise<void> instead of void. Existing code needs to add await:

// Old
authorizer.setPermission(permission);

// New  
await authorizer.setPermission(permission);

Testing

  • Added 3 new tests covering enforcer format support
  • All 15 tests pass
  • Maintains backward compatibility with simple permission format

Fixes #[issue_number]

Original prompt

This section details on the original issue you should resolve

<issue_title>CasbinJsGetPermissionForUser seems to export something casbinjs doesn't understand</issue_title>
<issue_description>Hello, I am not sure if this library is still maintained, but I am looking to get the enforcer setup client side.

Versions

  • casbin.js: "^0.5.1"
  • github.com/casbin/casbin/v2 v2.116.0

The API is in go, and the server side model & policy work as expected. I am sending the result of CasbinJsGetPermissionForUser, but when using the client enforcer, it says false for the same comparison I am doing in the backend.

When I change it to what the example says:

{
  "read": ["data1", "data2"],
  "write": ["data1"]
}

it works as expected.

Model
[request_definition]
r = sub, act, obj

[policy_definition]
p = sub, act, obj

[role_definition]
g = _, _
g2 = _, _

[policy_effect]
e = some(where (p.eft == allow))

[matchers]
m = r.sub == p.sub && g(p.act, r.act) && r.obj == p.obj
Policy
p, 123, user, data1
p, 456, admin, data1

g, user, GetRbacResource
g, admin, GetRbacResource
g, admin,CreateRbacResource

Result of CasbinJsGetPermissionForUser
{
  "g": [
    [
      "g",
      "user",
      "GetRbacResource"
    ],
    [
      "g",
      "admin",
      "GetRbacResource"
    ],
    [
      "g",
      "admin",
      "CreateRbacResource"
    ]
  ],
  "m": "[request_definition]\nr = sub, act, obj\n[policy_definition]\np = sub, act, obj\n[role_definition]\ng = _, _\ng2 = _, _\n[policy_effect]\ne = some(where (p.eft == allow))\n[matchers]\nm = r.sub == p.sub && g(p.act, r.act) && r.obj == p.obj\n",
  "p": [
    [
      "p",
      "123",
      "user",
      "data1"
    ],
    [
      "p",
      "456",
      "admin",
      "data1"
    ]
  ]
}

Usage

const authorizer = new casbinjs.Authorizer('manual')

// get permissions from API - responds with above block
authorizer.setPermission(responseFromApi)

// tried this too, but had no effect
// authorizer.setUser('123')

authorizer.can('CreateRbacResource', 'data1').then((can) => {
  // can is false
})

When I swapped out the response from the API with the docs snippet, it worked as expected.

// drastically different response to what I get
authorizer.setPermission({
  read: ['data1', 'data2'],
  write: ['data1'],
})

authorizer.can('write', 'data1').then((can) => {
  // can is true
})
```</issue_description>

## Comments on the Issue (you are @copilot in this section)

<comments>
</comments>

Fixes #284


💬 Share your feedback on Copilot coding agent for the chance to win a $200 gift card! Click here to start the survey.

@CLAassistant
Copy link

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

- Made setPermission() async to support both simple and enforcer formats
- Auto-detect enforcer format (with 'm' and 'p' keys) and use initEnforcer()
- Update can() to check for enforcer in manual mode
- Update setUser() to set user in all modes (needed for enforcer in manual mode)
- Add comprehensive tests for new functionality
- Update README with examples of both formats

Co-authored-by: hsluoyz <3787410+hsluoyz@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix CasbinJsGetPermissionForUser export issue Fix setPermission() to support enforcer format from Go backend's CasbinJsGetPermissionForUser Oct 11, 2025
Copilot finished work on behalf of hsluoyz October 11, 2025 18:44
Copilot AI requested a review from hsluoyz October 11, 2025 18:44
@hsluoyz hsluoyz marked this pull request as ready for review October 12, 2025 02:19
@hsluoyz hsluoyz closed this Oct 12, 2025
@hsluoyz hsluoyz reopened this Oct 12, 2025
@hsluoyz
Copy link
Member

hsluoyz commented Oct 13, 2025

@christopher-caldwell

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

CasbinJsGetPermissionForUser seems to export something casbinjs doesn't understand

3 participants