Skip to content

Support CasbinJsGetPermissionForUser format in manual mode#303

Open
Copilot wants to merge 4 commits intomasterfrom
copilot/fix-casbinjs-permission-export
Open

Support CasbinJsGetPermissionForUser format in manual mode#303
Copilot wants to merge 4 commits intomasterfrom
copilot/fix-casbinjs-permission-export

Conversation

Copy link
Contributor

Copilot AI commented Feb 1, 2026

Manual mode only accepted simple permission format {"read": ["data1"]}. Go backends using CasbinJsGetPermissionForUser return enforcer format {"m": "...", "p": [[...]], "g": [[...]]}, which was incompatible.

Changes

  • Auto-detect permission format in setPermission(): Checks for 'm' and 'p' keys to distinguish enforcer format from simple format, initializes enforcer when detected
  • Process grouping policies in initEnforcer(): Added handling for separate 'g' key containing role inheritance rules
  • Use enforcer in manual mode: Modified can() to use enforcer when initialized, enabling RBAC support in manual mode
  • Allow setUser() in manual mode: Sets subject for enforcer-based permission checks
  • Fix array iteration bug: Changed for...in to for...of in Permission.load() (was iterating indices instead of values)

Usage

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

// Both formats now work:

// Simple format (existing)
authorizer.setPermission({
  "read": ['data1', 'data2'],
  "write": ['data1']
});

// Enforcer format from Go backend (new)
await authorizer.setPermission({
  "m": "[request_definition]\nr = sub, obj, act\n...",
  "p": [["p", "alice", "data1", "read"], ...],
  "g": [["g", "alice", "admin"], ...]
});
await authorizer.setUser('alice');
await authorizer.can('read', 'data1'); // true

No breaking changes. Simple format continues to work as before.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • https://api.github.com/search/code
    • Triggering command: /usr/bin/curl curl -s REDACTED (http block)

If you need me to access, download, or install something from one of these locations, you can either:

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>

✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

@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.

@nomeguy nomeguy marked this pull request as ready for review February 1, 2026 09:48
Copilot AI and others added 3 commits February 1, 2026 09:53
Co-authored-by: nomeguy <85475922+nomeguy@users.noreply.github.com>
Co-authored-by: nomeguy <85475922+nomeguy@users.noreply.github.com>
Co-authored-by: nomeguy <85475922+nomeguy@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix CasbinJsGetPermissionForUser export issue Support CasbinJsGetPermissionForUser format in manual mode Feb 1, 2026
Copilot AI requested a review from nomeguy February 1, 2026 09:58
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