Code Monkey home page Code Monkey logo

sqlalchemy-adapter's People

Contributors

ffyuanda avatar garyd203 avatar hsluoyz avatar huonw avatar ifdotpy avatar jimmyyyeh avatar leeqvip avatar sean-donoghue avatar semantic-release-bot avatar shivansh-yadav13 avatar sunhs avatar tripledogdare avatar wakemaster39 avatar yihuilu 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

Watchers

 avatar  avatar  avatar  avatar  avatar

sqlalchemy-adapter's Issues

How to use postgresql db?

I see the example and the issue about mysql db, but still confused. Can you give me any clue how I can connect to my postgresql db?

AttributeError: entity

  • FastAPI
  • SQLAlchemy1.13 / MySQL8.0.18

code:

adapter = Adapter(engine=engine)
ENFORCER = casbin.Enforcer(config.CASBIN_MODEL_CONF, adapter, True)

traceback:

INFO:     Started reloader process [1]
2020-05-04 12:38:38,201 - INFO - Model:
INFO:     Model:
2020-05-04 12:38:38,201 - INFO - r.r: sub, obj, act
INFO:     r.r: sub, obj, act
2020-05-04 12:38:38,201 - INFO - p.p: sub, obj, act
INFO:     p.p: sub, obj, act
2020-05-04 12:38:38,201 - INFO - e.e: some(where (p_eft == allow))
INFO:     e.e: some(where (p_eft == allow))
2020-05-04 12:38:38,201 - INFO - m.m: g(r_sub, p_sub) && r_obj == p_obj && r_act == p_act
INFO:     m.m: g(r_sub, p_sub) && r_obj == p_obj && r_act == p_act
2020-05-04 12:38:38,201 - INFO - g.g: _, _
INFO:     g.g: _, _
Process SpawnProcess-1:
Traceback (most recent call last):
  File "/usr/local/lib/python3.7/multiprocessing/process.py", line 297, in _bootstrap
    self.run()
  File "/usr/local/lib/python3.7/multiprocessing/process.py", line 99, in run
    self._target(*self._args, **self._kwargs)
  File "/usr/local/lib/python3.7/site-packages/uvicorn/subprocess.py", line 61, in subprocess_started
    target(sockets=sockets)
  File "/usr/local/lib/python3.7/site-packages/uvicorn/main.py", line 382, in run
    loop.run_until_complete(self.serve(sockets=sockets))
  File "uvloop/loop.pyx", line 1456, in uvloop.loop.Loop.run_until_complete
  File "/usr/local/lib/python3.7/site-packages/uvicorn/main.py", line 389, in serve
    config.load()
  File "/usr/local/lib/python3.7/site-packages/uvicorn/config.py", line 288, in load
    self.loaded_app = import_from_string(self.app)
  File "/usr/local/lib/python3.7/site-packages/uvicorn/importer.py", line 20, in import_from_string
    module = importlib.import_module(module_str)
  File "/usr/local/lib/python3.7/importlib/__init__.py", line 127, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 1006, in _gcd_import
  File "<frozen importlib._bootstrap>", line 983, in _find_and_load
  File "<frozen importlib._bootstrap>", line 967, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 677, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 728, in exec_module
  File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
  File "./main.py", line 12, in <module>
    from interfaces.router import api_router
  File "./interfaces/router.py", line 6, in <module>
    from .endpoints import identity, authentication, permission
  File "./interfaces/endpoints/identity.py", line 11, in <module>
    from application.services.security import get_current_active_user, get_current_admin_user
  File "./application/services/security.py", line 11, in <module>
    from domain.permission.entity import Policy, verify_permission
  File "./domain/permission/entity.py", line 19, in <module>
    ENFORCER = casbin.Enforcer(config.CASBIN_MODEL_CONF, adapter, True)
  File "/usr/local/lib/python3.7/site-packages/casbin/core_enforcer.py", line 31, in __init__
    self.init_with_adapter(model, adapter)
  File "/usr/local/lib/python3.7/site-packages/casbin/core_enforcer.py", line 47, in init_with_adapter
    self.init_with_model_and_adapter(m, adapter)
  File "/usr/local/lib/python3.7/site-packages/casbin/core_enforcer.py", line 63, in init_with_model_and_adapter
    self.load_policy()
  File "/usr/local/lib/python3.7/site-packages/casbin/core_enforcer.py", line 142, in load_policy
    self.adapter.load_policy(self.model)
  File "/usr/local/lib/python3.7/site-packages/casbin_sqlalchemy_adapter/adapter.py", line 50, in load_policy
    lines = self._session.query(CasbinRule).all()
  File "/usr/local/lib/python3.7/site-packages/sqlalchemy/orm/session.py", line 1558, in query
    return self._query_cls(entities, self, **kwargs)
  File "/usr/local/lib/python3.7/site-packages/sqlalchemy/orm/query.py", line 191, in __init__
    self._set_entities(entities)
  File "/usr/local/lib/python3.7/site-packages/sqlalchemy/orm/query.py", line 219, in _set_entities
    self._set_entity_selectables(self._entities)
  File "/usr/local/lib/python3.7/site-packages/sqlalchemy/orm/query.py", line 250, in _set_entity_selectables
    ent.setup_entity(*d[entity])
  File "/usr/local/lib/python3.7/site-packages/sqlalchemy/orm/query.py", line 4185, in setup_entity
    self._with_polymorphic = ext_info.with_polymorphic_mappers
  File "/usr/local/lib/python3.7/site-packages/sqlalchemy/util/langhelpers.py", line 883, in __get__
    obj.__dict__[self.__name__] = result = self.fget(obj)
  File "/usr/local/lib/python3.7/site-packages/sqlalchemy/orm/mapper.py", line 2141, in _with_polymorphic_mappers
    configure_mappers()
  File "/usr/local/lib/python3.7/site-packages/sqlalchemy/orm/mapper.py", line 3255, in configure_mappers
    mapper._post_configure_properties()
  File "/usr/local/lib/python3.7/site-packages/sqlalchemy/orm/mapper.py", line 1950, in _post_configure_properties
    prop.init()
  File "/usr/local/lib/python3.7/site-packages/sqlalchemy/orm/interfaces.py", line 196, in init
    self.do_init()
  File "/usr/local/lib/python3.7/site-packages/sqlalchemy/orm/relationships.py", line 1935, in do_init
    self._process_dependent_arguments()
  File "/usr/local/lib/python3.7/site-packages/sqlalchemy/orm/relationships.py", line 1997, in _process_dependent_arguments
    self.target = self.entity.persist_selectable
  File "/usr/local/lib/python3.7/site-packages/sqlalchemy/util/langhelpers.py", line 977, in __getattr__
    return self._fallback_getattr(key)
  File "/usr/local/lib/python3.7/site-packages/sqlalchemy/util/langhelpers.py", line 951, in _fallback_getattr
    raise AttributeError(key)
AttributeError: entity

Adding existing policy and/or group

Adding new policies. groups which already exist now inserts a duplicate is there any way to avoid that also will be nice if we can give out a warning in that case or maybe something like an ignore_duplicate flag

btw, Pycasbin has been really helpful in my projects, Cheers ✌️

RBAC with domain does not work with SQL Alchemy Adapter

Hey team 👋 happy new year 🎉

I have been debugging and testing different GitHub issues that were opened in the past, and looking through the documentation but I was not able to make work Py Casbin with RBAC with the domains model

I have the same conf that in the official documentation https://casbin.org/docs/rbac-with-domains. The only difference is that instead of using a CSV file I am using the SQL Alchemy Adapter

Looking through the unit test, I only found coverage for simple RBAC with sub, obj, and action and I believe that is the main reason the Enforcer is not returning True when it should because it is not implemented in the Adapter. Can you confirm this?

I have tested my configuration in the casbin online editor and the enforcer returns True

image

I saw that Pycasbin used to have an issue related RBAC with domain but was fixed here casbin/pycasbin#92

I found in the issue that I shared that the domain matching func should be added like this

  enforcer = Enforcer("rbac-tenant.conf", Adapter(engine=settings.DATABASE_URL, db_class=RBAC))
  enforcer.add_named_domain_matching_func("g", key_match2)
  result = enforcer.enforce(user_id, organization_id, self.obj, self.action)

Also tried without adding it and many others but the Enforcer always return false

By the way, the connection with the Adapter is working perfectly because when I create an Organization Owner user, I am adding the policies and the group, and works totally fine

enforcer = Enforcer("rbac-tenant.conf", Adapter(engine=settings.DATABASE_URL, db_class=RBAC))
enforcer.add_role_for_user_in_domain(str(user_id), "ORGANIZATION_OWNER", str(organization_id))
enforcer.add_policy("ORGANIZATION_OWNER", str(organization_id), "organizations", "update")
enforcer.add_policy("ORGANIZATION_OWNER", str(organization_id), "organizations", "delete")
enforcer.add_policy("ORGANIZATION_OWNER", str(organization_id), "organizations", "read")

Thanks for the help

Need ability to not use internally constructed session

#36 while looking innocent enough is a breaking change and should have rolled minor versions at least and not been v0.3.1. Deleting the _commit() functionality and reworking the internals so all inheritance exploded was definitely not something I was expecting for a patch roll.

I agree with the intent of the change, it is correct sessions are short lived so having this in theory is a correct change.

The issue comes from when session management is handled outside of the scope of casbin. I am a pretty big proponent of sessions should be explicitly managed and not hidden away in the library. I also must absolutely have the ability to force my casbin session and my other DB changes to be executed as part of a single operation.

The way I was previously able to do this was hijacking the _session variable as part of the adapter and the self._commit() function. I have an inherited adapter that just made sure _commit was a noop and I could adjust the _session variable to my upstream session and things would work out ok.

This change also explodes things like autocommit out of postgresql if that is how the engine is bound because session.commit() will always explode because no background implicit session is created to be committed like this. Fortunately I hadn't upgraded that project code base yet.

Based on this change, I feel like two adapters being exposed from this library might make the most sense. the first being the core adapter which is basically this class minus the definition of the constructor and the _session_scope(self) function. This basically says "go ahead and role your extensions, we will guarantee to keep this interface" and a second one that extends the core with the default implementation so people will more basic needs still have a working out of the box experience.

Support Customization of CasbinRule class

Right now, CasbinRule has its own declarative_base that is hard coded down in all levels of the code.

Situations come up in use where you want to have your own class for various reasons such as a single declarative base. Rather than forcing a copy and pasting of the entire adapter and making your own. Allow setting the class yourself and all other logic renames usable.

[BUG] Missing guard clause?

def save_policy(self, model):
"""saves all policy rules to the storage."""
query = self._session.query(self._db_class)
query.delete()
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)
self._commit()
return True

Policy Subset Loading mention that SavePolicy should disable while apply subset loading.

Implement has_policy() method to check whether the policy exists before adding the policy

Hi,

Currently, there is no function to verify whether a policy already exists in the database. Hence, the adapter is allowing to create duplicate entries in the table whenever you re-run the script.
image

def add_policy(self, sec, ptype, rule):
        """adds a policy rule to the storage."""
        self._save_policy_line(ptype, rule)

I guess, the above method didn't check for existing entries in the table, hence the issue might be occuring.

Code to reproduce:
Run the below code snippet for 5-6 times and in database you found those many entries of same policy.

import casbin_sqlalchemy_adapter
import casbin

adapter = casbin_sqlalchemy_adapter.Adapter('sqlite:///test.db')

e = casbin.Enforcer('path/to/model.conf', adapter, True)
e.add_policy('admin', 'domain1', 'data1', 'read')
print(e.get_policy())

SQLAlchemy adapter object has no attribute update_policy

Source code:

import casbin
import casbin_sqlalchemy_adapter


model = casbin.Model()
model.add_def("r", "r", "sub, obj, act")
model.add_def("p", "p", "sub, obj, act")
model.add_def("g", "g", "_, _")
model.add_def("e", "e", "some(where (p.eft == allow))")
model.add_def("m", "m", "g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act")

adapter = casbin_sqlalchemy_adapter.Adapter('mysql+pymysql://db_account:[email protected]:3306/demo')

e = casbin.Enforcer(model, adapter)

e.add_policy('admin', 'r')
e.update_policy(['admin', 'r'], ['admin', 'w'])

Running results:

Traceback (most recent call last):
  File "/Users/zhangyi/Documents/vianet/vnet.service.lib/casbinLib/casbinLib/__init__.py", line 106, in <module>
    e.update_policy(['admin', 'r'], ['admin', 'w'])
  File "/Users/zhangyi/.virtualenvs/vnet.service.lib/lib/python3.8/site-packages/casbin/management_enforcer.py", line 125, in update_policy
    return self.update_named_policy("p", old_rule, new_rule)
  File "/Users/zhangyi/.virtualenvs/vnet.service.lib/lib/python3.8/site-packages/casbin/management_enforcer.py", line 133, in update_named_policy
    return self._update_policy("p", ptype, old_rule, new_rule)
  File "/Users/zhangyi/.virtualenvs/vnet.service.lib/lib/python3.8/site-packages/casbin/internal_enforcer.py", line 52, in _update_policy
    if self.adapter.update_policy(sec, ptype, old_rule, new_rule) is False:
AttributeError: 'Adapter' object has no attribute 'update_policy'

SQLAlchemy adapter object has no attribute update_policy, hope the author add, thank you!:)

New Release 0.0.3

Can you guys create a new release with the latest code as a v0.0.3, v0.0.2 doesn't contain the changes for delete_policy.

Support for policy subset loading

I am using python and casbin_sqlalchemy_adapter adapter.
I see that file adapter has support for policy subset loading. Is it possible in casbin_sqlalchemy_adapter

Readme has 3rd parameter as True which causes TypError: __init__() takes from 1 to 3 positional arguments but 3 were given

Readme has enforcer being initialized with the following line: e = casbin.Enforcer('path/to/model.conf', adapter, True)

BUT, CoreEnforcer init only has the following params: def __init__(self, model=None, adapter=None)

I get the following error when I leave the 3rd param as True: TypeError: __init__() takes from 1 to 3 positional arguments but 4 were given

If this is confirmed as a bug in the readme, please lmk if I can help to make the change as it would be my first 😄

possibly wrong behavior for `remove_policies`

Assume I have the following policies:

p, developer, domain, obj1, write
p, guest, domain, obj2, read
g, user, developer, domain

And I remove one of the policy using

policies_for_obj = enforcer.get_filtered_policy(2, "obj1")  # This returns ['developer', 'domain', 'obj1', 'write']
enforcer.remove_policies(policies_for_obj)

Then all the policies are deleted.

In these lines,

for rule in rules:
query = query.filter(or_(getattr(self._db_class, "v{}".format(i)) == v for i, v in enumerate(rule)))

the or_ will translate the filter into something like:

v0==developer or v1==domain or v2==obj1 or v3==write

and all the policies will match this filter since v1==domain holds for all of them.

Adapter _save_policy_line only writes to v0 for all rule fields

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

When I pass in a rule the only value that gets written to the database is the last value field of the rule and this always gets written into v0 as it is the only column referenced in each case.

The column for each case should be updated to match the rule field index, line.v1 = rule[1], etc.

2006, 'MySQL server has gone away'

Moved from: casbin/pycasbin#136

When I visited the next day, I got this prompt:

StatementError at /api/test/admin/
(sqlalchemy.exc.InvalidRequestError) Can't reconnect until invalid transaction is rolled back
[SQL: SELECT casbin_rule.id AS casbin_rule_id, casbin_rule.ptype AS casbin_rule_ptype, casbin_rule.v0 AS casbin_rule_v0, casbin_rule.v1 AS casbin_rule_v1, casbin_rule.v2 AS casbin_rule_v2, casbin_rule.v3 AS casbin_rule_v3, casbin_rule.v4 AS casbin_rule_v4, casbin_rule.v5 AS casbin_rule_v5 
FROM casbin_rule]
[parameters: [immutabledict({})]]

or:

OperationalError at /api/test/admin/
(MySQLdb._exceptions.OperationalError) (2006, 'MySQL server has gone away')
[SQL: SELECT casbin_rule.id AS casbin_rule_id, casbin_rule.ptype AS casbin_rule_ptype, casbin_rule.v0 AS casbin_rule_v0, casbin_rule.v1 AS casbin_rule_v1, casbin_rule.v2 AS casbin_rule_v2, casbin_rule.v3 AS casbin_rule_v3, casbin_rule.v4 AS casbin_rule_v4, casbin_rule.v5 AS casbin_rule_v5 
FROM casbin_rule]
(Background on this error at: http://sqlalche.me/e/13/e3q8)

My environment:

Python:3.9.2 and 3.9.4
Django: 3.1.7
ServerHost:AliYun and QingYun

My configuration is as follows:

# casbin_middleware

import casbin
import casbin_sqlalchemy_adapter
from django.core.exceptions import PermissionDenied
from casbin_pro.settings import env
adapter = casbin_sqlalchemy_adapter.Adapter(env.get_value("CASBIN_URL"))
enforcer = casbin.Enforcer("casbin_middleware/authz_model.conf", adapter, True)
class CasbinMiddleware:
    """
    Casbin middleware.
    """

    def __init__(self, get_response):
        self.get_response = get_response
        # Initialize the Casbin enforcer, executed only on once.
        self.enforcer = enforcer
    ...
    ...
CASBIN_URL=mysql+pymysql://root:[email protected]:3306/aliyun_casbin?autocommit=true
# or
CASBIN_URL=mysql://root:[email protected]:3306/aliyun_casbin?charset=utf8&autocommit=true

start-up:
gunicorn casbin_pro.asgi:application -b 0:8000 -w 2 -k uvicorn.workers.UvicornWorker --reload --log-level info -t 600

how to use custom sqlalchemy model

so far I've been unsuccessful in trying to use a custom model in place of CasbinRule. is this possible?

importing Base and adding a model to that still tries to create the casbin_rule table from CasbinRule

fix inconsistent schema

Trying to use the python's casbin_sqlalchemy_adapte to access a Casbin policy stored on Postgres with Golang's sql-adapter return the following error:

LINE 1: SELECT casbin_rule.id AS casbin_rule_id, casbin_rule.ptype A...```

This is due to the fact that the Golang's sql adapter does not add an `id` column which is actually required for the Python adapter.

The schema should be made consistent in order to allow interoperability of the same Casbin rule system/table across different languages.

Release v0.1.0

Could you please release the v0.1.0 with the recent changes that completed the adapter interface?(maybe after #5 lands?) Thank you very much.

save_policy doesn't work as describe in document

The docuemnt says:

This is unlike SavePolicy(), because the latter will delete all policy rules in the storage and save all policy rules from Casbin enforcer to the storage.

import casbin_sqlalchemy_adapter
import casbin


adapter = casbin_sqlalchemy_adapter.Adapter('sqlite:///test.db')

report_paths = [{'path': '/api/v1/report/product/ungrouped/items/', 'method': 'get', 'tags': 'report_product_ungrouped'}, {'path': '/api/v1/report/product/ungrouped/items2/', 'method': 'get', 'tags': 'report_product_ungrouped'}]

e = casbin.Enforcer('C:\\Users\\username\\Documents\\scripts\\myproject\\app\\casbin_model.conf', adapter, True)
e.enable_auto_save(False)

e.add_policy('alice', 'data5', 'read')

e.save_policy()
e.save_policy()

When I run the above code, it just save another record of the same policy to database.

Inconsistent schema with Original Gorm adapter

Hi,

I've opened a similar ticket yesterday but this time it's about an inconsistency between the pycasbin/sqlalchemy-adapter and the casbin/gorm-adapter

When the casbin Rule Table is created through the gorm adapter, the 1st column is named p_type.

When the same Table is created by SQLAlchemy, the 1st column is named ptype.

This creates interoperability issues.

This could either be fixed in the Gorm Adaper by changing the name (see here) or in the SQLAlchemy adapter.

Let me know if you need some help with this.

Thank you

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.