Giter Site home page Giter Site logo

casbin / pycasbin Goto Github PK

View Code? Open in Web Editor NEW
1.3K 27.0 182.0 514 KB

An authorization library that supports access control models like ACL, RBAC, ABAC in Python

Home Page: https://casbin.org

License: Apache License 2.0

Python 100.00%
casbin python pycasbin access-control authorization rbac abac acl auth authz

pycasbin's People

Contributors

abichinger avatar abingcbc avatar amisadmin avatar asyncee avatar bustdot avatar cs1137195420 avatar divy9881 avatar divyagar avatar elfisworking avatar favipcj avatar ffyuanda avatar hsluoyz avatar huonw avatar jalinwang avatar leeqvip avatar nekotoxin avatar nghnam avatar sallycaoyu avatar semantic-release-bot avatar shblhy avatar sheny1xuan avatar shivansh-yadav13 avatar stuartbeattie84 avatar swagatsbhuyan avatar terry-xuan-gao avatar timabilov avatar tl24 avatar xhy-5000 avatar yyellowsun avatar zxilly avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

pycasbin's Issues

Rule based on foreign key relationship

hi,

I have a series of relationships set up like this:

User
id
customer_id

Customer
id
distributor_id

Distributor
id

I have an endpoint like /user/, and I want to restrict users to only be able to see other users whose user.customer.distributor_id is the same as their user.customer.distributor_id

How would I go about setting up a rule for a scenario like this? Is it even possible to abstract these kinds of relationships into an ABAC schema?

permission is empty for root role user

[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, "role_root") || (g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act)
p, data1_read, data1, read
p, data2_read, data2, read
p, data2_write, data2, write

g, alice, data2_read
g, bob, role_root
import casbin
e = casbin.Enforcer("model.conf", "policy.csv")

sub = "bob"  # the user that wants to access a resource.
obj = "data2"  # the resource that is going to be accessed.
act = "write"  # the operation that the user performs on the resource.

e.enforce(sub, obj, act)

e.get_implicit_permissions_for_user('alice')
e.get_implicit_permissions_for_user('bob')

I expect e.get_implicit_permissions_for_user('bob') to return all permissions defined, but it is empty.

Support for Filtered Adapters

Running PyCasbin in a production environment with a decent size of rules (~30k) pycasbin starts to fall apart. Looping over the policy to find out if each rule matches only to find out that r.obj != s.obj is pretty painful.

Without completely obliterating the internals of casbin to hard code certain checks exist and using things like sets or dictionaries to get the performance up, filtered queries are very much required.

Bug Python3 : Can't iterate on a dict in all_roles.keys

File : rbac/default_role_manager/role_manager.py
Line : 15~16

 def has_role(self, name):
        return name in self.all_roles.keys()

Error : In python3 you can't iterate on a dict

Fix :

-        return name in self.all_roles.keys()
+        return name in list(self.all_roles.keys())

Wrong policy list when add manually

Model config:

[request_definition]
r = sub, obj, act

[policy_definition]
p = sub, obj, act, eft

[role_definition]
g = _, _

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

[matchers]
m = g(r.sub, p.sub) && keyMatch(r.obj, p.obj) && regexMatch(r.act, p.act)

Code:

import casbin

enforcer = casbin.Enforcer("casbin_model.conf")
enforcer.add_named_policy("p", "sub1", "obj1", "read", "deny")
enforcer.add_named_policy("p", "group1", "obj1", "read", "allow")
enforcer.add_named_grouping_policy('g', 'sub1', 'group1')

print('Objects:', enforcer.get_all_objects())
print('Subjects:', enforcer.get_all_subjects())
print('Actions:', enforcer.get_all_actions())

Here is output:

Objects: ['obj1', 'group1']
Subjects: ['sub1', 'group1']
Traceback (most recent call last):
  File "test_casbin.py", line 10, in <module>
    print('Actions:', enforcer.get_all_actions())
  File "/Users/namnh/.venvs/casbin/lib/python3.7/site-packages/casbin/management_enforcer.py", line 27, in get_all_actions
    return self.get_all_named_actions('p')
  File "/Users/namnh/.venvs/casbin/lib/python3.7/site-packages/casbin/management_enforcer.py", line 31, in get_all_named_actions
    return self.model.get_values_for_field_in_policy('p', ptype, 2)
  File "/Users/namnh/.venvs/casbin/lib/python3.7/site-packages/casbin/model/policy.py", line 100, in get_values_for_field_in_policy
    values.append(rule[field_index])
IndexError: list index out of range

It shows wrong object list, right list only has obj1, and does not has group1 . And get_all_actions() is failed.

I found problem is in Assertion class, which has policy attribute. It is class attribute, so it is shared between instances. So when you add policy p, it is also added to g.
Debug:

print(enforcer.model.model['p']['p'].policy)
print(enforcer.model.model['g']['g'].policy)
print(id(enforcer.model.model['p']['p'].policy))
print(id(enforcer.model.model['g']['g'].policy))

Output:

[['sub1', 'obj1', 'read', 'deny'], ['group1', 'obj1', 'read', 'allow'], ['sub1', 'group1']]
[['sub1', 'obj1', 'read', 'deny'], ['group1', 'obj1', 'read', 'allow'], ['sub1', 'group1']]
4411842880
4411842880

Bringing pycasbin in track with casbin-core.

I am sure there must be some features or functionalities which are not in track with casbin-core, why should we not track those features and bring them here and implement it.

pycasbin adapters for django?

I find some supported adapters such as SQLAlchemy Adapter and Peewee Adapter in doc. How about adapters for django web frame?

Running tests and coverage

I tried using py.test but get module not found errors. Can you please let me know how I can run tests and see coverage?

Make enforcer singleton?

Enforcer load policy into memory, if there have multiple instances of enforcer and they modify policy, how can they keep sync?
Make enforcer singleton should solve this problem?
Or can you explain why enforcer shouldn't be singleton?

Tests are install directly to site-packages rather than within the casbin package

I ran into this issue because pycasbin was causing problems with test module discovery using pytest.

Running pip install casbin then pip uninstall casbin illustrates the problem:

Uninstalling casbin-0.8.2:
  Would remove:
    ~/.virtualenvs/casbin/README.md
    ~/.virtualenvs/casbin/lib/python3.7/site-packages/casbin-0.8.2.dist-info/*
    ~/.virtualenvs/casbin/lib/python3.7/site-packages/casbin/*
    ~/.virtualenvs/casbin/lib/python3.7/site-packages/tests/*

That last line indicates that the tests are being placed directly into site-packages, which is incorrect and causes errors in test discovery.

advice on performance

We've been growing our test data set to about 2.5k rules in the policy set, which is making calls to the enforcer quite slow. Is there something that can be done to speed things up, or did I just pick a terrible model for performance?

model:

[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) && keyMatch(r.obj, p.obj) && r.act == p.act

example policy:

g,act.io/org:acmecorp/group:admins,act.io/org:acmecorp/group:members
p,act.io/org:acmecorp/group:admins,act.io/org:acmecorp/info,edit
p,act.io/org:acmecorp/group:admins,act.io/org:acmecorp/group:members,manage
p,act.io/org:acmecorp/group:members,act.io/org:acmecorp,view
p,act.io/org:acmecorp/group:members,act.io/org:acmecorp/plan:*,view
p,act.io/org:acmecorp/group:members,act.io/org:acmecorp/plan:*,create

g,act.io/user:cde7860e-5459-413c-969a-9536edbb1980,act.io/org:acmecorp/group:admins
g,act.io/user:554a09e6-2d6a-406d-aef0-2ea0e09a0e9f,act.io/org:acmecorp/group:members

g,act.io/org:acmecorp/campaign:1/group:admins,act.io/org:acmecorp/campaign:1/group:members
p,act.io/org:acmecorp/campaign:1/group:admins,act.io/org:acmecorp/campaign:1/info,edit
p,act.io/org:acmecorp/campaign:1/group:admins,act.io/org:acmecorp/campaign:1/group:members,manage
p,act.io/org:acmecorp/campaign:1/group:members,act.io/org:acmecorp/campaign:1,view
p,act.io/org:acmecorp/campaign:1/group:members,act.io/org:acmecorp/campaign:1/submission:*,approve
p,act.io/org:acmecorp/campaign:1/group:members,act.io/org:acmecorp/campaign:1/version:*,create
p,act.io/org:acmecorp/campaign:1/group:members,act.io/org:acmecorp/campaign:1/version:*,read
p,act.io/org:acmecorp/campaign:1/group:members,act.io/org:acmecorp/campaign:1/version:*,update

g,act.io/user:cde7860e-5459-413c-969a-9536edbb1980,act.io/org:acmecorp/campaign:1/group:admins
g,act.io/user:3ae34b92-a0f8-4b3f-a7bd-877c9ba303a4,act.io/org:acmecorp/campaign:1/group:members

g,act.io/org:acmecorp/campaign:2/group:admins,act.io/org:acmecorp/campaign:2/group:members
p,act.io/org:acmecorp/campaign:2/group:admins,act.io/org:acmecorp/campaign:2/info,edit
p,act.io/org:acmecorp/campaign:2/group:admins,act.io/org:acmecorp/campaign:2/group:members,manage
p,act.io/org:acmecorp/campaign:2/group:members,act.io/org:acmecorp/campaign:2,view
p,act.io/org:acmecorp/campaign:2/group:members,act.io/org:acmecorp/campaign:2/submission:*,approve
p,act.io/org:acmecorp/campaign:2/group:members,act.io/org:acmecorp/campaign:2/version:*,create
p,act.io/org:acmecorp/campaign:2/group:members,act.io/org:acmecorp/campaign:2/version:*,read
p,act.io/org:acmecorp/campaign:2/group:members,act.io/org:acmecorp/campaign:2/version:*,update

g,act.io/user:925d614b-12f4-4048-91c5-adf9f278dcb9,act.io/org:acmecorp/campaign:2/group:admins
g,act.io/user:6e48501a-eff8-4ec7-8215-638c7726e163,act.io/org:acmecorp/campaign:2/group:members

keyMatch2(r.obj, p.obj) Breaking the rules on homepage when the url is /

when I use allow-and-deny model in my project , fllow is my define :
[request_definition]
r = sub, obj, act

[policy_definition]
p = sub, obj, act, eft

[role_definition]
g = _, _

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

[matchers]
m = g(r.sub, p.sub) && (r.obj == p.obj || p.obj == "" || keyMatch(r.obj, p.obj) || keyMatch2(r.obj, p.obj)) && (r.act == p.act || p.act == "")

I want to use keyMatch2 func to match the “:” expression ,but when I use the '/' to represent the home page, the authority management loses control, and all the URLs under the same user can be accessed

Here is my definition of police:
p, anonymous, /users/index/, *, allow
p, alice, /, *, allow

alice can access any url! But it seems to work in the editor!

Restful(Keymatch2) in v0.8.4 get wrong result

My model.conf is

[request_definition]
r = sub, obj, act

[policy_definition]
p = sub, obj, act

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

[matchers]
m = r.sub == p.sub && keyMatch2(r.obj, p.obj) && regexMatch(r.act, p.act)

Policy is

p, ops, /process/cancel, POST
p, ops, /process, POST

and Request is
ops, /process/approve, POST

the result should False, but in fact it is:
2020-07-20 13:53:23,985 - INFO - Request: ops, /process/approve, POST ---> True

Did I code something wrong?

Custom RoleManager

Hello. In this doc page, the maintainers of Casbin seem to imply that you can choose/write your own RoleManager class. However, this seems to be hardcoded in. Is there a way to supply a custom class? Can one be made with relative ease?

def _initialize(self):
self.rm = default_role_manager.RoleManager(10)
self.eft = DefaultEffector()
self.watcher = None
self.enabled = True
self.auto_save = True
self.auto_build_role_links = True

Before and after login, the debug log printed by caspin shows that the users accessed are anonymous

Before and after login, the debug log printed by caspin shows that the users accessed are anonymous. In theory, after the authentication is successful, the authenticated user information should be displayed. How should this inform the user to obtain the setting of caspin and identify the authenticated user normally

[2020-03-27 17:34:42,218] INFO in views: 登出成功
127.0.0.1 - - [27/Mar/2020 17:34:42] "GET /auth/logout/ HTTP/1.1" 302 -
2020-03-27 17:34:42,230 - INFO - Request: anonymous, /auth/, GET ---> True
127.0.0.1 - - [27/Mar/2020 17:34:42] "GET /auth/ HTTP/1.1" 200 -
2020-03-27 17:34:44,792 - INFO - Request: anonymous, /auth/login/, GET ---> True
127.0.0.1 - - [27/Mar/2020 17:34:44] "GET /auth/login/ HTTP/1.1" 200 -
2020-03-27 17:34:52,642 - INFO - Request: anonymous, /auth/login/, POST ---> True
[2020-03-27 17:34:52,680] INFO in views: test login sucess

save_policy() unavailable on built-in file adapter

question

I am using the model file default rbac_with_domains_model.conf and policy file rbac_with_domains_policy.csv

loading it as

import casbin
x = casbin.Enforcer('<model file>','<conf file>')

I am assigning a new role for the user to it as

y.add_role_for_user_in_domain('prashant','admin', 'domain1')

now I want to save this policy, so I am doing

x.save_policy()

but this is not saving my new added policy in a file.

when I see the save_policy code in codebase no procedure to save is written ie

 def save_policy(self):
       pass

my question is, shouldn't it be a new method to save all the policy in the file be there? or I am doing something wrong with my approach. if I am doing wrong please help me to correct it.

Queries become very slow after I added 30000+ policies

I'm using pycasbin, with sqlalchemy-adapter as adapter. Policies are stored in mysql.
When I'm testing, with about 20 policies. everything is perfect.
After I stored 30000+ policies in mysql, queries become very slow, about 3-4 seconds per query.

Here is the example code.

import casbin
from casbin import persist
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from casbin.model import Model

Base = declarative_base()

MYSQL_CONF = "mysql+pymysql://.........." 
TABLE_NAME = 'auth_rule' 

DOM = 'test'
LOG_ENABLED = False

class CasbinRule(Base):
    __tablename__ = TABLE_NAME

    id = Column(Integer, primary_key=True)
    ptype = Column(String(255))
    v0 = Column(String(255))
    v1 = Column(String(255))
    v2 = Column(String(255))
    v3 = Column(String(255))
    v4 = Column(String(255))
    v5 = Column(String(255))

class Adapter(persist.Adapter):
    """the interface for Casbin adapters."""

    def __init__(self, dsn):
        self._engine = create_engine(dsn)
        session = sessionmaker(bind=self._engine)
        self._session = session()

        Base.metadata.create_all(self._engine)

    def load_policy(self, model):
        """loads all policy rules from the storage."""
        lines = self._session.query(CasbinRule).all()
        for line in lines:
            text = line.ptype

            if line.v0:
                text = text + ', ' + line.v0
            if line.v1:
                text = text + ', ' + line.v1
            if line.v2:
                text = text + ', ' + line.v2
            if line.v3:
                text = text + ', ' + line.v3
            if line.v4:
                text = text + ', ' + line.v4
            if line.v5:
                text = text + ', ' + line.v5

            persist.load_policy_line(text, model)

    def _save_policy_line(self, ptype, rule):
        line = CasbinRule(ptype=ptype)
        if len(rule) > 0:
            line.v0 = rule[0]
        if len(rule) > 1:
            line.v1 = rule[1]
        if len(rule) > 2:
            line.v2 = rule[2]
        if len(rule) > 3:
            line.v3 = rule[3]
        if len(rule) > 4:
            line.v4 = rule[4]
        if len(rule) > 5:
            line.v5 = rule[5]
        self._session.add(line)
        self._session.commit()

    def save_policy(self, model):
        """saves all policy rules to the storage."""
        for sec in ["p", "g"]:
            if sec not in model.model.keys():
                continue
            for ptype, ast in model.model[sec].items():
                for rule in ast.policy:
                    self._save_policy_line(ptype, rule)
        return True

    def __del__(self):
        self._session.close()

class Auth:

    mysql_conf = MYSQL_CONF

    def __init__(self):
        self.adapter = Adapter(self.mysql_conf)
        self.new_model_conf = Model()
        self.new_model_conf.add_def("r","r","sub, obj, act, dom") #
        self.new_model_conf.add_def("p","p","sub, obj, act, dom") #
        self.new_model_conf.add_def("g","g","_, _")
        self.new_model_conf.add_def("g","g2","_, _, _") #
        self.new_model_conf.add_def("g","g3","_, _, _") #
        self.new_model_conf.add_def("e","e","some(where (p.eft == allow))")
        self.new_model_conf.add_def("m","m",'g(r.sub, p.sub) && (g2(r.obj, p.obj, r.dom) || p.obj == "*") && (g3(r.act, p.act, r.dom) || p.act == "*") && r.dom == p.dom')
        self.e = casbin.Enforcer(self.new_model_conf, self.adapter, LOG_ENABLED)

    def check_auth(self, sub, obj, act, dom=DOM):
        sub = str(sub)
        obj = str(obj)
        act = str(act)
        dom = str(dom)
        return self.e.enforce(sub, obj, act, dom):



######CasbinRule and Adapter are from github project: 
######pycasbin/sqlalchemy-adapter/casbin_sqlalchemy_adapter/adapter.py

auth = Auth()
result = auth.e.enforce('1234','2345','read', 'test')

About GSoC

Hi metors, sorry for late. Right now is there any chances about taking part in GSoC in pycasbin project ?

Best practice

Hi,

I'm wondering about best practice in pycasbin.

Example 1

Say I have a DB table of stores:

# id name description
1 1 Store 1 Store 1
2 2 Store 2 Store 2
3 3 Store 3 Store 3
4 4 Store 4 Store 4
5 5 Store 5 Store 5

A DB table of policies:

# id ptype v0 v1 v2 v3 v4 v5
1 1 p alice Store 1 read NULL NULL NULL
2 2 p alice Store 2 write NULL NULL NULL
3 3 p alice Store 3 write NULL NULL NULL
4 4 p alice Store 4 read NULL NULL NULL

Would this be the best way to get a list of stores that Alice has access to?:

permissions = e.get_implicit_permissions_for_user("alice")

for permission in permissions:
    result = session.query(Store).filter(Store.name == permission[1]).first()
    print(f"Store Name: {result.name} - Store Description: {result.description}")

Example 2

As another example; if I wanted to use DB table ID's instead of Store names, would I use the table name as a domain?

# id ptype v0 v1 v2 v3 v4 v5
2 3 p Store Manager Store 1 write NULL NULL
3 4 p Store Manager Store 2 write NULL NULL
4 5 p Store Manager Store 3 write NULL NULL
5 6 p Store Manager Store 4 write NULL NULL
14 16 g alice Store Manager Store NULL NULL NULL
permissions = e.get_implicit_permissions_for_user("Alice", "Store")

for permission in permissions:
    result = session.query(Store).filter(Store.id == permission[2]).first()
    print(f"Store Name: {result.name} - Store Description: {result.description}")

One last question: I am using the casbin_sqlalchemy_adapter, what are all of the v0-v5 columns for?

Thanks for any feedback :-)

pip cannot find casbin

There's an issue with the pypi repository.

$ virtualenv --python=python3 venv && source ./venv/bin/activate && pip install casbin
Already using interpreter /usr/bin/python3
Using base prefix '/usr'
New python executable in /repos/agosto/gcp/project_template/venv/bin/python3
Also creating executable in /repos/agosto/gcp/project_template/venv/bin/python
Installing setuptools, pkg_resources, pip, wheel...done.
Collecting casbin
  Could not find a version that satisfies the requirement casbin (from versions: )
No matching distribution found for casbin

roles = e.get_roles("alice") is wrong!

https://github.com/casbin/pycasbin

In the following introduction:

Besides the static policy file, Casbin also provides API for permission management at run-time. For example, You can get all the roles assigned to a user as below:
roles = e.get_roles("alice")

There is no such method like get_roles("alice")! use get_roles_for_user("alice") instead!

Returning a value of the policy rule as effect

Let's say that in a policy, instead of providing a boolean kind of right, it grants some amount of a resource. For instance

p, sub, act, obj, amount

Is it possible to define a model so I get that amount as a result of calling Enforce instead of a true/false effect?

Is really production ready?

Hello, I have read the sources and have few questions.

  1. Is this project really production ready? I have found hard coded effect expressions in different parts of source code. I thought that it is implemented using some dsl interpretation but there are at most 4 cases that can be used as effects (see effectors module). That looks very strange to me.

  2. The official paper https://arxiv.org/pdf/1903.09756.pdf states that casbin is implemented in lua and used in interpreter-in-interpreter way. In fact all casbin implementations are just straightforward ports from golang version. Can we trust this paper? Also the benchmarks section of this paper has nothing in common with actual implementation of pycasbin.

  3. Some parts of code look not optimized and not pythonic, for example a function that removes duplicates from a string array.

Wrapping up: casbin is great on paper but i’m a bit worried if I really can use it in production due to questions above.

P.S.: I appreciate the work been done on this project and thank you for making it open sourced.

New Release (0.9.0?)

With filtered policy support available it would be awesome to have this available in a general release rather than needing to us git repos.

AttributeError: 'Model' object has no attribute 'add_policy'

import casbin


def test():
    enforcer = casbin.Enforcer('path/to/model.conf',
                               'path/to/policy.csv')

    added = enforcer.add_policy('alice', 'data1', 'read')

    result = enforcer.enforce('alice', 'data1', 'read')

    print('result: {}'.format(result))


if __name__ == "__main__":
    test()

output:

Traceback (most recent call last):
  File "C:/Users/Ken/PycharmProjects/casbin_test/app1/test.py", line 22, in <module>
    test()
  File "C:/Users/Ken/PycharmProjects/casbin_test/app1/test.py", line 14, in test
    added = enforcer.add_policy('alice', 'data1', 'read')
  File "C:\Users\Ken\PycharmProjects\casbin_test\venv\lib\site-packages\casbin\management_api.py", line 92, in add_policy
    return self.add_named_policy('p', *params)
  File "C:\Users\Ken\PycharmProjects\casbin_test\venv\lib\site-packages\casbin\management_api.py", line 110, in add_named_policy
    rule_added = self._add_policy('p', ptype, policy)
  File "C:\Users\Ken\PycharmProjects\casbin_test\venv\lib\site-packages\casbin\internal_api.py", line 5, in _add_policy
    rule_added = self.model.add_policy(sec, ptype, rule)
AttributeError: 'Model' object has no attribute 'add_policy'

Issue with pycasbin logging

PyCasbin currently sets up its own logger:
https://github.com/casbin/pycasbin/tree/master/casbin/log

Since pycasbin is a supporting module to an application it should differ the logging setup to the application that would leverage the module. This is done by the module class setting self.logger = logging.getLogger() to get the root logger.
Then when calls are made with self.logger.[method]([message]) it will either log as expected or if no logger is gotten then it just wont log as expected. Currently there is no way to override the default pycasbin log level because it is statically set and if you disable the logger you disable all log messages. There is also no good way to override the enforcer class logger since it is not class property.

https://github.com/casbin/pycasbin/blob/master/casbin/log/default_logger.py#L11
https://github.com/casbin/pycasbin/blob/master/casbin/core_enforcer.py#L1
https://github.com/casbin/pycasbin/blob/master/casbin/core_enforcer.py#L25
https://github.com/casbin/pycasbin/blob/master/casbin/core_enforcer.py#L289

The current behavior of pycasbin results in duplicate logs when the application sets up a logger of its own.

2020-10-13 15:54:01,688 - INFO - Request: isadmin, /api/v1/applications, GET ---> True
[2020-10-13 15:54:01,688] INFO in default_logger: Request: isadmin, /api/endpoint, GET ---> True

I will open a PR for these changes when I can unless someones gets to it before me.

Performance of pycasbin vs go casbin

(Please note I had submitted this issue on casbin, and was told to move it to pycasbin, which I am doing verbatim).

We have profiled a simple Casbin enforcement call over an (admittedly abnormally large) policy set. We did this with a go and a python script. The python version takes about 30x the time per enforcement call (1.5 seconds on an i5).

2 things I would like to ask the authors (who suggested I opened this issue):

  1. does it check out that the Python implementation would take so much more than the go one?
  2. even in go, Enforce takes a time that grows linearly with the number of policies, even when the actual policy being asked is laid out explicitly in the policy file (naively, I'd say a lookup shouldn't take linear time, but then we're using a model with deny). Is this normal?
    I am attaching a zipfile with the go script, the python script, the model, and the policy file.

perf.zip

Assigning custom Role Manager changes enforcement result

    m = casbin.model.Model()
    a = casbin.persist.Adapter()
    e = casbin.Enforcer(m, a)
    e.set_role_manager(casbin.rbac.default_role_manager.RoleManager(10))
    m.add_def("r", "r", "sub, obj, act")
    m.add_def("p", "p", "sub, obj, act")
    m.add_def("g", "g", "_, _")
    m.add_def("e", "e", "some(where (p.eft == allow))")
    m.add_def("m", "m", "g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act")
    a.add_policy("p", "p", ["alice", "data1", "read"])
    a.add_policy("p", "p", ["bob", "data2", "write"])

    assert e.enforce("alice", "data1", "read")
    assert not e.enforce("alice", "data1", "write")

    assert e.enforce("bob", "data2", "write")
    assert not e.enforce("bob", "data1", "write")

Fails at assert e.enforce("alice", "data1", "read").

Is there a way to pass the RoleManager to a custom matcher function

Is there any way to pass a Role Manager to a custom matcher function so inherited roles could be tested using a matcher function?

The alternative would be to pass a matcher function to a g function.

An example showing the need for this is:

g, permission::read, permission_group::admin
g, permission::write, permission_group::admin
g, permission::execute, permission_group::admin
g, permission::read, permission_group::readwrite
g, permission::write, permission_group::readwrite
g, permission::read, permission_group::readonly

g, /resource_1, resource_group::engineering
g, /resource_2, resource_group::engineering
g, /resource_3/*, resource_group::engineering

p, user::[email protected], resource_group::engineering, permission_group::admin, allow

In the above example, I can match enforcement requests for /resource_1 and /resource_2 with a g function. However, there is no way I can think of to match to /resource_3/foo and /resource_3/bar using a matcher function such as the built in keyMatch.

Is there an alternative way to approach this problem?

It`s wrong in keyMatch2!

in builtin_operators.py

def regex_match(key1, key2):
    """determines whether key1 matches the pattern of key2 in regular expression."""

    res = re.match(key2, key1)
    if res:
        return True
    else:
        return False

when url is / that can match any url

eval function - ABAC with policy

HiI am struggling with using eval functions for ABAC with policy in pycasbin
Model-taken from example

[request_definition]
r = sub, obj, act

[policy_definition]
p = sub_rule, obj, act

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

[matchers]
m = eval(p.sub_rule) && r.obj == p.obj && r.act == p.act

Policy - taken from example

p, r.sub.Age > 18 && r.sub.Age < 60, /data1, read
Data{ Age: 40}, /data1, read
ErrorTraceback (most recent call last):
  File "/home/tomer/.local/lib/python3.8/site-packages/simpleeval.py", line 406, in _eval_call
    func = self.functions[node.func.id]
KeyError: 'eval'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "Test.py", line 8, in <module>
    print (e.enforce(sub, obj, act))
  File "/usr/local/lib/python3.8/dist-packages/casbin-0.8.4-py3.8.egg/casbin/core_enforcer.py", line 237, in enforce
    result = expression.eval(parameters)
  File "/usr/local/lib/python3.8/dist-packages/casbin-0.8.4-py3.8.egg/casbin/util/expression.py", line 29, in eval
    return self._eval(self.expr_parsed_value)
  File "/home/tomer/.local/lib/python3.8/site-packages/simpleeval.py", line 343, in _eval
    return handler(node)
  File "/home/tomer/.local/lib/python3.8/site-packages/simpleeval.py", line 375, in _eval_boolop
    vout = self._eval(value)
  File "/home/tomer/.local/lib/python3.8/site-packages/simpleeval.py", line 343, in _eval
    return handler(node)
  File "/home/tomer/.local/lib/python3.8/site-packages/simpleeval.py", line 408, in _eval_call
    raise FunctionNotDefined(node.func.id, self.expr)
simpleeval.FunctionNotDefined: Function 'eval' not defined, for expression 'eval(p_sub_rule) and r_obj == p_obj and r_act == p_act'.

also i see this function is not registered: https://github.com/casbin/pycasbin/blob/master/casbin/model/function.py

Appreciate any help  

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.