Coder Social home page Coder Social logo

simple-rbac's Introduction

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"))

simple-rbac's People

Contributors

dbaneman avatar rahulraghu94 avatar shonenada avatar springtangent avatar tonyseek 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

simple-rbac's Issues

0.1.2?

Hi @tonyseek

The last release i.e. 0.1.1 was on June 10, 2012. I see there are some recent commits regarding Python3 compatibility. I am reaching out to you to find out whether you have any plans of releasing 0.1.2 anytime soon (available in pypi)?

Thank you,

Sangeeth

先deny,再allow的问题

用了一下你的这个工具,发现一个问题:
我一开始为一个角色allow了一系列的rule,在程序里我deny了某一个rule,然后我又allow了这个rule。
结果check_permission返回False。
我希望能在allow某个rule的时候,如果该rule曾经被deny过了,那么将其从_denied字典中移除。

Refactor Role/Resource Model

This project uses a static defination to find parent relationship of roles and resources. That way is hard to handle a situation that a role or a resource has a dynamic parents getter.

Currently my solution is using a proxy class to register parent defination rules implicatly. But this way is ugly and broken the Zen of Python.

I have a plan to refactor the role model and resource model, give them a flexible way to use more dynamic rules.

Writting Document for Simple RBAC

The Simple RBAC library has only a quick guide at current stage, which is simple but not complete. I hope to give it a detail document. This plan will be implemented in this summer holiday.

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.