pyperms


Namepyperms JSON
Version 0.1.0 PyPI version JSON
download
home_pagehttps://github.com/X-AROK/pyperms
SummaryLibrary for convenient access control
upload_time2023-05-30 13:41:33
maintainer
docs_urlNone
authorX-AROK
requires_python>=3.8,<4.0
licenseMIT
keywords pyperms permissions casl ability
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # PyPerms (Python Permissions)

PyPerms is a library for convenient access control. The inspiration was the JS library - [CASL](https://casl.js.org/).

## Simple Usage

```python
from pyperms import PermissionsBuilder

from .models import User


def define_perms_for(user):
    builder = PermissionsBuilder()

    builder.can("read", "Post")
    if "admin" in user.roles:
        builder.can("*", "*")

    return builder.build()


admin = User(id=1, roles=["admin"])
user = User(id=2, roles=["user"])

admin_perms = define_perms_for(admin)
user_perms = define_perms_for(user)

admin_perms = define_perms_for(admin)
user_perms = define_perms_for(user)

admin_perms.can("read", "Post")  # True
admin_perms.can("create", "Post")  # True
admin_perms.can("read", "Article")  # True

user_perms.can("read", "Post")  # True
user_perms.can("create", "Post")  # False
```

## Typing

For typing `Actions` and `Subjects`, you can use `Literal` from the standard module `typing`.

```python
from typing import Literal

from pyperms import PermissionsBuilder

Actions = Literal["*", "read"]
Subjects = Literal["*", "Post"]


def define_perms():
    builder = PermissionsBuilder[Actions, Subjects]()

    builder.can("read", "Post")  # OK
    builder.can("*", "*")  # OK

    builder.can("create", "Post")  # Error

    return builder.build()
```

## Fields

For more flexible permission settings, you can use the `fields` parameter.

```python
from pyperms import PermissionsBuilder


def define_perms():
    builder = PermissionsBuilder()
    builder.can("read", "Post", fields=["title", "author"])
    return builder.build()


perms = define_perms()
perms.can("read", "Post", field="title")  # True
perms.can("read", "Post", field="created_at")  # False
```

## Conditions

Sometimes permission checks may require conditions, such as whether the user is the author of the post. For such cases, there is a `condiotion` parameter in the builder `can` and `cannot` methods. For it to work, it is necessary to pass an instance of the class with the same name in the `subject`.

```python
from pyperms import PermissionsBuilder
from pyperms import operators as _

from .models import Post, User


def define_perms_for(user):
    builder = PermissionsBuilder()
    builder.can("update", "Post", condition=_.Eq("author", user.id))
    return builder.build()


post = Post(id=1, author=1)

user1 = User(id=1)
user2 = User(id=2)

user1_perms = define_perms_for(user1)
user2_perms = define_perms_for(user2)

user1_perms.can("update", post)  # True
user2_perms.can("update", post)  # False
```

`Operator` is a callable object that returns a boolean value. When it is initialized, the first parameter is the path to the attribute (can be separated by dot for recursive access), the second parameter is the value to be checked.

Here is a list of default operators:

-   Logical:
    -   And
    -   Or
    -   Not
-   Other:
    -   Eq
    -   Ne
    -   Lt
    -   Le
    -   Gt
    -   Ge
    -   In
    -   NIn
    -   All
    -   Size
    -   Regex

## Attributes

Each operator, when called, tries to get the attribute using `getattr`. To reduce the number of `getattr` calls, you can use the `Attribute` class or the `attr` function. An instance of this class stores the received attribute value for each object (comparison by id).

```python
from pyperms import PermissionsBuilder, attr
from pyperms import operators as _


def define_perms_for(user):
    builder = PermissionsBuilder()

    author = attr("author")
    builder.can("read", "Post", condition=_.Eq(author, user.id))
    builder.can("update", "Post", condition=_.Eq(author, user.id))

    return builder.build()
```

## Custom operators

All operators are subclasses of one of three base classes: `BaseLogicOperator1`, `BaseLogicOperator2`, `BaseOperator`.

An example of your own operator:

```python
from pyperms.conditions.base import BaseOperator


def my_func(__a: int, __b: int) -> bool:
    return __a + __b == 2


class MyOperator(BaseOperator, func=my_func):
    "Docstring for MyOperator"
    ...
```

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/X-AROK/pyperms",
    "name": "pyperms",
    "maintainer": "",
    "docs_url": null,
    "requires_python": ">=3.8,<4.0",
    "maintainer_email": "",
    "keywords": "pyperms,permissions,casl,ability",
    "author": "X-AROK",
    "author_email": "an_xarok@mail.ru",
    "download_url": "https://files.pythonhosted.org/packages/2b/8b/f755ea5298563ee20ebbd23cbe45af04182cf1a6aa4aa789299afb739671/pyperms-0.1.0.tar.gz",
    "platform": null,
    "description": "# PyPerms (Python Permissions)\n\nPyPerms is a library for convenient access control. The inspiration was the JS library - [CASL](https://casl.js.org/).\n\n## Simple Usage\n\n```python\nfrom pyperms import PermissionsBuilder\n\nfrom .models import User\n\n\ndef define_perms_for(user):\n    builder = PermissionsBuilder()\n\n    builder.can(\"read\", \"Post\")\n    if \"admin\" in user.roles:\n        builder.can(\"*\", \"*\")\n\n    return builder.build()\n\n\nadmin = User(id=1, roles=[\"admin\"])\nuser = User(id=2, roles=[\"user\"])\n\nadmin_perms = define_perms_for(admin)\nuser_perms = define_perms_for(user)\n\nadmin_perms = define_perms_for(admin)\nuser_perms = define_perms_for(user)\n\nadmin_perms.can(\"read\", \"Post\")  # True\nadmin_perms.can(\"create\", \"Post\")  # True\nadmin_perms.can(\"read\", \"Article\")  # True\n\nuser_perms.can(\"read\", \"Post\")  # True\nuser_perms.can(\"create\", \"Post\")  # False\n```\n\n## Typing\n\nFor typing `Actions` and `Subjects`, you can use `Literal` from the standard module `typing`.\n\n```python\nfrom typing import Literal\n\nfrom pyperms import PermissionsBuilder\n\nActions = Literal[\"*\", \"read\"]\nSubjects = Literal[\"*\", \"Post\"]\n\n\ndef define_perms():\n    builder = PermissionsBuilder[Actions, Subjects]()\n\n    builder.can(\"read\", \"Post\")  # OK\n    builder.can(\"*\", \"*\")  # OK\n\n    builder.can(\"create\", \"Post\")  # Error\n\n    return builder.build()\n```\n\n## Fields\n\nFor more flexible permission settings, you can use the `fields` parameter.\n\n```python\nfrom pyperms import PermissionsBuilder\n\n\ndef define_perms():\n    builder = PermissionsBuilder()\n    builder.can(\"read\", \"Post\", fields=[\"title\", \"author\"])\n    return builder.build()\n\n\nperms = define_perms()\nperms.can(\"read\", \"Post\", field=\"title\")  # True\nperms.can(\"read\", \"Post\", field=\"created_at\")  # False\n```\n\n## Conditions\n\nSometimes permission checks may require conditions, such as whether the user is the author of the post. For such cases, there is a `condiotion` parameter in the builder `can` and `cannot` methods. For it to work, it is necessary to pass an instance of the class with the same name in the `subject`.\n\n```python\nfrom pyperms import PermissionsBuilder\nfrom pyperms import operators as _\n\nfrom .models import Post, User\n\n\ndef define_perms_for(user):\n    builder = PermissionsBuilder()\n    builder.can(\"update\", \"Post\", condition=_.Eq(\"author\", user.id))\n    return builder.build()\n\n\npost = Post(id=1, author=1)\n\nuser1 = User(id=1)\nuser2 = User(id=2)\n\nuser1_perms = define_perms_for(user1)\nuser2_perms = define_perms_for(user2)\n\nuser1_perms.can(\"update\", post)  # True\nuser2_perms.can(\"update\", post)  # False\n```\n\n`Operator` is a callable object that returns a boolean value. When it is initialized, the first parameter is the path to the attribute (can be separated by dot for recursive access), the second parameter is the value to be checked.\n\nHere is a list of default operators:\n\n-   Logical:\n    -   And\n    -   Or\n    -   Not\n-   Other:\n    -   Eq\n    -   Ne\n    -   Lt\n    -   Le\n    -   Gt\n    -   Ge\n    -   In\n    -   NIn\n    -   All\n    -   Size\n    -   Regex\n\n## Attributes\n\nEach operator, when called, tries to get the attribute using `getattr`. To reduce the number of `getattr` calls, you can use the `Attribute` class or the `attr` function. An instance of this class stores the received attribute value for each object (comparison by id).\n\n```python\nfrom pyperms import PermissionsBuilder, attr\nfrom pyperms import operators as _\n\n\ndef define_perms_for(user):\n    builder = PermissionsBuilder()\n\n    author = attr(\"author\")\n    builder.can(\"read\", \"Post\", condition=_.Eq(author, user.id))\n    builder.can(\"update\", \"Post\", condition=_.Eq(author, user.id))\n\n    return builder.build()\n```\n\n## Custom operators\n\nAll operators are subclasses of one of three base classes: `BaseLogicOperator1`, `BaseLogicOperator2`, `BaseOperator`.\n\nAn example of your own operator:\n\n```python\nfrom pyperms.conditions.base import BaseOperator\n\n\ndef my_func(__a: int, __b: int) -> bool:\n    return __a + __b == 2\n\n\nclass MyOperator(BaseOperator, func=my_func):\n    \"Docstring for MyOperator\"\n    ...\n```\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "Library for convenient access control",
    "version": "0.1.0",
    "project_urls": {
        "Homepage": "https://github.com/X-AROK/pyperms",
        "Repository": "https://github.com/X-AROK/pyperms"
    },
    "split_keywords": [
        "pyperms",
        "permissions",
        "casl",
        "ability"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "d43f017cc7f7d314d49d0c9566648e834ef6ff56944b233b8581efc98d99c7b7",
                "md5": "19f79df5f2c78c8320a842662f41b862",
                "sha256": "f35f8ac7925d09678a04b3577a951cdefd610fed1fcf22ad64ba53530b5902a8"
            },
            "downloads": -1,
            "filename": "pyperms-0.1.0-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "19f79df5f2c78c8320a842662f41b862",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.8,<4.0",
            "size": 8077,
            "upload_time": "2023-05-30T13:41:31",
            "upload_time_iso_8601": "2023-05-30T13:41:31.477439Z",
            "url": "https://files.pythonhosted.org/packages/d4/3f/017cc7f7d314d49d0c9566648e834ef6ff56944b233b8581efc98d99c7b7/pyperms-0.1.0-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "2b8bf755ea5298563ee20ebbd23cbe45af04182cf1a6aa4aa789299afb739671",
                "md5": "00090311ac896cfdc74a5f5355a14f55",
                "sha256": "73ea160c638f3551211dd8d949c73bf0ccc2469f65755c5b8fffdce67bbcb0a9"
            },
            "downloads": -1,
            "filename": "pyperms-0.1.0.tar.gz",
            "has_sig": false,
            "md5_digest": "00090311ac896cfdc74a5f5355a14f55",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.8,<4.0",
            "size": 6511,
            "upload_time": "2023-05-30T13:41:33",
            "upload_time_iso_8601": "2023-05-30T13:41:33.596849Z",
            "url": "https://files.pythonhosted.org/packages/2b/8b/f755ea5298563ee20ebbd23cbe45af04182cf1a6aa4aa789299afb739671/pyperms-0.1.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2023-05-30 13:41:33",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "X-AROK",
    "github_project": "pyperms",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "pyperms"
}
        
Elapsed time: 0.08029s