casbin / pycasbin

An authorization library that supports access control models like ACL, RBAC, ABAC in Python
https://casbin.org
Apache License 2.0
1.36k stars 191 forks source link

remove_grouping_policy: link between string and string does not exist #250

Closed wu-clan closed 2 years ago

wu-clan commented 2 years ago

When I use remove_grouping_policy as I use remove_policy, it happend raise: RuntimeError: error: link between string and string does not exist, but g only have two values, so, how i need to do or is this a question?

casbin-bot commented 2 years ago

@ffyuanda @Zxilly @techoner @elfisworking

hsluoyz commented 2 years ago

@wu-clan please show all your code, including the model, policy, request and response.

wu-clan commented 2 years ago

@wu-clan please show all your code, including the model, policy, request and response.

# remove_policy
@casbin.delete('/del_policy', summary='Remove access rights based on role (primary) or user (secondary)')
def delete_policy(p: PolicyDelete):
    enforcer = rbac.get_casbin_enforcer()
    data = enforcer.remove_policy(p.sub, p.path, p.method)
    if data:
        return Response200(data=data)
    else:
        return Response404(msg='Deletion failed, access rights do not exist', data=data)

# remove_grouping_policy
@casbin.delete('/del_group', summary='remove group based access rights')
def delete_group(p: UserRole):
    enforcer = rbac.get_casbin_enforcer()
    data = enforcer.remove_grouping_policy(p.uid, p.role)
    if data:
        return Response200(data=data)
    else:
        return Response404(msg='Deletion failed, access rights do not exist', data=data)

my db text: image

This should be a classic RBAC

when i send request delete_policy api, when the parameter does not exist, it can return False

but when i send request delete_group api like delete_policy, it happend:

NFO:     127.0.0.1:52401 - "DELETE /v1/rbac/del_group HTTP/1.1" 500 Internal Server Error
ERROR:    Exception in ASGI application
Traceback (most recent call last):
  File "C:\ProgramData\Anaconda3\lib\site-packages\uvicorn\protocols\http\httptools_impl.py", line 398, in run_asgi
    result = await app(self.scope, self.receive, self.send)
  File "C:\ProgramData\Anaconda3\lib\site-packages\uvicorn\middleware\proxy_headers.py", line 45, in __call__
    return await self.app(scope, receive, send)
  File "C:\Users\wu\AppData\Roaming\Python\Python38\site-packages\fastapi\applications.py", line 208, in __call__
    await super().__call__(scope, receive, send)
  File "C:\ProgramData\Anaconda3\lib\site-packages\starlette\applications.py", line 112, in __call__
    await self.middleware_stack(scope, receive, send)
  File "C:\ProgramData\Anaconda3\lib\site-packages\starlette\middleware\errors.py", line 181, in __call__
    raise exc from None
  File "C:\ProgramData\Anaconda3\lib\site-packages\starlette\middleware\errors.py", line 159, in __call__
    await self.app(scope, receive, _send)
  File "C:\ProgramData\Anaconda3\lib\site-packages\starlette\middleware\base.py", line 25, in __call__
    response = await self.dispatch_func(request, self.call_next)
  File "D:\gitproject\fastapi_mysql_demo\backend\app\middleware\access_middle.py", line 17, in dispatch
    response = await call_next(request)
  File "C:\ProgramData\Anaconda3\lib\site-packages\starlette\middleware\base.py", line 45, in call_next
    task.result()
  File "C:\ProgramData\Anaconda3\lib\site-packages\starlette\middleware\base.py", line 38, in coro
    await self.app(scope, receive, send)
  File "C:\ProgramData\Anaconda3\lib\site-packages\starlette\middleware\gzip.py", line 18, in __call__
    await responder(scope, receive, send)
  File "C:\ProgramData\Anaconda3\lib\site-packages\starlette\middleware\gzip.py", line 35, in __call__
    await self.app(scope, receive, self.send_with_gzip)
  File "C:\ProgramData\Anaconda3\lib\site-packages\starlette\middleware\cors.py", line 86, in __call__
    await self.simple_response(scope, receive, send, request_headers=headers)
  File "C:\ProgramData\Anaconda3\lib\site-packages\starlette\middleware\cors.py", line 142, in simple_response
    await self.app(scope, receive, send)
  File "C:\ProgramData\Anaconda3\lib\site-packages\starlette\exceptions.py", line 82, in __call__
    raise exc from None
  File "C:\ProgramData\Anaconda3\lib\site-packages\starlette\exceptions.py", line 71, in __call__
    await self.app(scope, receive, sender)
  File "C:\ProgramData\Anaconda3\lib\site-packages\starlette\routing.py", line 580, in __call__
    await route.handle(scope, receive, send)
  File "C:\ProgramData\Anaconda3\lib\site-packages\starlette\routing.py", line 241, in handle
    await self.app(scope, receive, send)
  File "C:\ProgramData\Anaconda3\lib\site-packages\starlette\routing.py", line 52, in app
    response = await func(request)
  File "C:\Users\wu\AppData\Roaming\Python\Python38\site-packages\fastapi\routing.py", line 226, in app
    raw_response = await run_endpoint_function(
  File "C:\Users\wu\AppData\Roaming\Python\Python38\site-packages\fastapi\routing.py", line 161, in run_endpoint_function
    return await run_in_threadpool(dependant.call, **values)
  File "C:\ProgramData\Anaconda3\lib\site-packages\starlette\concurrency.py", line 40, in run_in_threadpool
    return await loop.run_in_executor(None, func, *args)
  File "C:\ProgramData\Anaconda3\lib\concurrent\futures\thread.py", line 57, in run
    result = self.fn(*self.args, **self.kwargs)
  File "D:\gitproject\fastapi_mysql_demo\backend\app\api\v1\v1_casbin.py", line 68, in delete_group
    data = enforcer.remove_grouping_policy(p.uid, p.role)
  File "C:\ProgramData\Anaconda3\lib\site-packages\casbin\management_enforcer.py", line 252, in remove_grouping_policy
    return self.remove_named_grouping_policy("g", *params)
  File "C:\ProgramData\Anaconda3\lib\site-packages\casbin\management_enforcer.py", line 277, in remove_named_grouping_policy
    self.model.build_incremental_role_links(
  File "C:\ProgramData\Anaconda3\lib\site-packages\casbin\model\policy.py", line 52, in build_incremental_role_links
    self[sec].get(ptype).build_incremental_role_links(rm, op, rules)
  File "C:\ProgramData\Anaconda3\lib\site-packages\casbin\model\assertion.py", line 66, in build_incremental_role_links
    rm.delete_link(rule[0], rule[1], *rule[2:])
  File "C:\ProgramData\Anaconda3\lib\site-packages\casbin\rbac\default_role_manager\role_manager.py", line 156, in delete_link
    raise RuntimeError(
RuntimeError: error: link between string and string does not exist

Is there a mistake in my method of use?

wu-clan commented 2 years ago

The model is here:

[request_definition]
r = sub, obj, act

[policy_definition]
p = sub, obj, act

[role_definition]
g = _, _

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

[matchers]
m = g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act
hsluoyz commented 2 years ago

@leeqvip

leeqvip commented 2 years ago

@wu-clan Try get_policy() and get_grouping_policy() to see if the policy is loaded successfully.

wu-clan commented 2 years ago

@leeqvip it's OK

@casbin.get('/get_policy', summary='get p policy')
def get_policy():
    enforcer = rbac.get_casbin_enforcer()
    data = enforcer.get_policy()
    if data:
        return Response200(data=data)

@casbin.get('/get_group', summary='get g policy')
def get_group():
    enforcer = rbac.get_casbin_enforcer()
    data = enforcer.get_grouping_policy()
    if data:
        return Response200(data=data)

INFO: 127.0.0.1:50624 - "GET /v1/rbac/get_policy HTTP/1.1" 200 OK INFO: 127.0.0.1:50625 - "GET /v1/rbac/get_group HTTP/1.1" 200 OK

Shivansh-yadav13 commented 2 years ago

@wu-clan can you cross-verify that the arguments you are passing are correct according to the grouping policy you have because I guess the error raised should show the grouping terms you are trying to remove rather than "string" eg RuntimeError: error: link between data2_admin and alice does not exist

wu-clan commented 2 years ago

@Shivansh-yadav13 Yes, string is just the parameter I passed, if the parameter are 'data2_admin' and 'alice', it raise:

RuntimeError: error: link between data2_admin and alice does not exist

but, when params are not in db, is it should be return False like remove_policy()? Not throwing an exception, and g have only two params, why need link between params? Or am I used it the wrong way?

Shivansh-yadav13 commented 2 years ago

not sure if we should be returning False for it like remove_policy() but links between params mean group-based access rights only. I guess nothing is wrong here maybe we can think about if we want to return false or raise an exception for it.

wu-clan commented 2 years ago

It seems that there is no problem. Based on this situation, g is complex. If you add a parameter to specify the situation, for example: use_policy=Ture, or create a new func?