# simple-rbac **Repository Path**: dwdcth/simple-rbac ## Basic Information - **Project Name**: simple-rbac - **Description**: No description available - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2020-02-14 - **Last Updated**: 2020-12-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README |Build Status| |Coverage Status| |PyPI Version| |Wheel Status| Simple RBAC =========== This is a simple role based access control utility in Python. Quick Start ----------- 1. Install Simple RBAC ~~~~~~~~~~~~~~~~~~~~~~ :: pip install simple-rbac 2. Create a Access Control List ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :: import rbac.acl acl = rbac.acl.Registry() 3. Register Roles and Resources ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :: acl.add_role("member") acl.add_role("student", ["member"]) acl.add_role("teacher", ["member"]) acl.add_role("junior-student", ["student"]) acl.add_resource("course") acl.add_resource("senior-course", ["course"]) 4. Add Rules ~~~~~~~~~~~~ :: acl.allow("member", "view", "course") acl.allow("student", "learn", "course") acl.allow("teacher", "teach", "course") acl.deny("junior-student", "learn", "senior-course") 5. Use It to Check Permission ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :: if acl.is_allowed("student", "view", "course"): print("Students chould view courses.") else: print("Students chould not view courses.") if acl.is_allowed("junior-student", "learn", "senior-course"): print("Junior students chould learn senior courses.") else: print("Junior students chould not learn senior courses.") Custom Role and Resource Class ------------------------------ It’s not necessary to use string as role object and resource object like "Quick Start". You could define role class and resource class of yourself, such as a database mapped model in SQLAlchemy. Whatever which role class and resource class you will use, it must implement ``__hash__`` method and ``__eq__`` method to be `hashable`_. Example ~~~~~~~ :: class Role(db.Model): """The role.""" id = db.Column(db.Integer, primary_key=True) screen_name = db.Column(db.Unicode, nullable=False, unique=True) def __hash__(self): return hash("ROLE::%d" % self.id) def __eq__(self, other): return self.id == other.id class Resource(db.Model): """The resource.""" id = db.Column(db.Integer, primary_key=True) screen_name = db.Column(db.Unicode, nullable=False, unique=True) def __hash__(self): return hash("RESOURCE::%d" % self.id) def __eq__(self, other): return self.id == other.id Of course, You could use the built-in hashable types too, such as tuple, namedtuple, frozenset and more. Use the Identity Context Check Your Permission ---------------------------------------------- Obviously, the work of checking permission is a cross-cutting concern. The module named ``rbac.context``, our ``IdentityContext``, provide some ways to make our work neater. 1. Create the Context Manager ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :: acl = Registry() context = IdentityContext(acl) 2. Set a Loader ~~~~~~~~~~~~~~~ The loader should load the roles of current user. :: from myapp import get_current_user @context.set_roles_loader def second_load_roles(): user = get_current_user() yield "everyone" for role in user.roles: yield str(role) 3. Protect Your Action ~~~~~~~~~~~~~~~~~~~~~~ Now you could protect your action from unauthorized access. As you please, you could choose many ways to check the permission, including python ``decorator``, python ``with statement`` or simple method calling. Decorator ^^^^^^^^^ :: @context.check_permission("view", "article", message="can't view") def article_page(): return "your-article" With Statement ^^^^^^^^^^^^^^ :: def article_page(): with context.check_permission("view", "article", message="can't view"): return "your-article" Simple Method Calling ^^^^^^^^^^^^^^^^^^^^^ :: def article_page(): context.check_permission("view", "article", message="can't view").check() return "your-article" Exception Handler and Non-Zero Checking ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Whatever which way you choosen, a exception ``rbac.context.PermissionDenied`` will be raised while a unauthorized access happening. The keyword arguments sent to the ``context.check_permission`` will be set into a attirbute named ``kwargs`` of the exception. You could get those data in your exception handler. :: @context.check_permission("view", "article", message="can not view") def article_page(): return "your-article" try: print article_page() except PermissionDenied as exception: print "The access has been denied, you %s" % exception.kwargs['message'] If you don’t want to raise the exception but only check the access is allowed or not, you could use the checking like a boolean value. :: if not context.check_permission("view", "article"): print "Oh! the access has been denied." is_allowed = bool(context.check_permission("view", "article")) .. _hashable: http://docs.python.org/glossary.html#term-hashable .. |Build Status| image:: https://img.shields.io/travis/tonyseek/simple-rbac.svg?style=flat :target: https://travis-ci.org/tonyseek/simple-rbac :alt: Build Status .. |Coverage Status| image:: https://img.shields.io/coveralls/tonyseek/simple-rbac.svg?style=flat :target: https://coveralls.io/r/tonyseek/simple-rbac :alt: Coverage Status .. |Wheel Status| image:: https://img.shields.io/pypi/wheel/simple-rbac.svg?style=flat :target: https://warehouse.python.org/project/simple-rbac :alt: Wheel Status .. |PyPI Version| image:: https://img.shields.io/pypi/v/simple-rbac.svg?style=flat :target: https://pypi.python.org/pypi/simple-rbac :alt: PyPI Version