Name | ariadne-auth JSON |
Version |
0.0.1.dev5
JSON |
| download |
home_page | None |
Summary | An Ariadne extension for authorization, allowing global permissions for all resolvers and fine-grained control over required permissions for specific resolvers in GraphQL APIs. |
upload_time | 2025-02-25 16:32:23 |
maintainer | None |
docs_url | None |
author | None |
requires_python | >=3.9 |
license | None |
keywords |
ariadne
ariadne-extension
authorization
permissions
|
VCS |
 |
bugtrack_url |
|
requirements |
No requirements were recorded.
|
Travis-CI |
No Travis.
|
coveralls test coverage |
No coveralls.
|
# How to use:
```shell
pip install ariadne-auth
```
### Set your Authorization Extension with global permissions
```python
from graphql import GraphQLResolveInfo
from ariadne_auth.authz import AuthorizationExtension
from ariadne_auth.types import HasPermissions
# Define a function that returns the permission object
def get_permission_obj(info: GraphQLResolveInfo) -> HasPermissions:
return info.context["my_permission_obj"]
# it can be also an async function
async def get_permission_obj_async(info: GraphQLResolveInfo) -> HasPermissions:
return info.context["my_permission_obj"]
# Instantiate the AuthorizationExtension
authz = AuthorizationExtension(permissions_object_provider_fn=get_permission_obj)
# Set list of permissions required for all resolvers
authz.set_required_global_permissions(["user:logged_in"])
```
### Configure resolvers
```python
query = QueryType()
ship = ObjectType("Ship")
faction = ObjectType("Faction")
# Set additional required permissions for specific resolvers
@query.field("rebels")
@authz.require_permissions(permissions=["read:rebels"]) # + "user:logged_in"
async def resolve_rebels(*_):
return FACTIONS[0]
@query.field("empire")
@authz.require_permissions(permissions=["read:empire"], ignore_global_permissions=False) # + "user:logged_in"
async def resolve_empire(*_):
return FACTIONS[1]
# Disable global permissions for specific resolver
@query.field("ships")
@authz.require_permissions(permissions=[], ignore_global_permissions=True) # + "user:logged_in"
async def resolve_ships(obj, *_):
return SHIPS
# Note the global permission is set on default_field_resolver method
# and it requires to disable permissions explicit for each field
@ship.field("name")
@authz.require_permissions(permissions=[], ignore_global_permissions=True)
async def resolve_ship_name(obj, *_):
return obj["name"]
```
If needed you may also overwrite the function to get the permission object for specific resolver
```python
def get_ship_permissions(info: GraphQLResolveInfo) -> HasPermissions:
return info.context["my_ship_permission_obj"]
@ship.field("name")
@authz.require_permissions(
permissions=[],
ignore_global_permissions=True,
permissions_object_provider_fn=get_ship_permissions
)
async def resolve_ship_name(obj, *_):
return obj["name"]
```
### Add your extension to Ariadne GraphQL instance
```python
app = GraphQL(
schema,
http_handler=GraphQLHTTPHandler(extensions=[authz]), # add the authz extension
)
```
You may also pass `authz` instance into info.context to use it directly
use `_auth.assert_permissions` or `await _auth.assert_permissions_async` to check permissions in your resovlers
```python
# Depends on the faction, additional permissions are required
@faction.field("ships")
async def resolve_faction_ships(faction_obj, info: GraphQLResolveInfo, *_):
_auth = info.context["auth"]
if (
faction_obj["name"] == "Alliance to Restore the Republic"
): # Rebels faction requires additional perm to read ships
_auth.assert_permissions(_auth.permissions_object_provider_fn(info), ["read:ships"])
return [_ship for _ship in SHIPS if _ship["factionId"] == faction_obj["id"]]
def get_context_value(request, data):
return {
**authz.generate_authz_context(request),
}
app = GraphQL(
schema,
context_value=get_context_value,
http_handler=GraphQLHTTPHandler(extensions=[authz])
)
```
## Run test app
The repository contains a test application that demonstrates how to use the library
#### To run test application use: `hatch run ariadne_auth`
Note that `user_id` is hardcoded in `test_app/app.py:148`
### Example request
for user with permissions
```
permissions=[
"user:logged_in",
"read:empire",
"read:rebels",
], # can't read rebels ships
```
```graphql
query {
empire{
id
name
ships {
id
name
}
}
rebels{
id
name
ships {
name
}
}
ships {
name
}
}
```
## Versioning policy ##
ariadne-auth follows a custom versioning scheme where the minor version increases for breaking changes, while the patch version increments for bug fixes, enhancements, and other non-breaking updates.
Since ariadne-auth has not yet reached a stable API, this approach is in place until version 1.0.0. Once the API stabilizes, the project will adopt Semantic Versioning.
----------------
**Crafted with ❤️ by [Mirumee Software](https://mirumee.com)**
hello@mirumee.com
Raw data
{
"_id": null,
"home_page": null,
"name": "ariadne-auth",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.9",
"maintainer_email": null,
"keywords": "ariadne, ariadne-extension, authorization, permissions",
"author": null,
"author_email": "Mirumee Labs <hello@mirumee.com>",
"download_url": "https://files.pythonhosted.org/packages/f0/93/890010ca9458fb58e6bd14559b20eb0e3204c8236e53315e35ff2ddbf86b/ariadne_auth-0.0.1.dev5.tar.gz",
"platform": null,
"description": "# How to use:\n```shell\npip install ariadne-auth\n```\n\n### Set your Authorization Extension with global permissions\n\n```python\nfrom graphql import GraphQLResolveInfo\nfrom ariadne_auth.authz import AuthorizationExtension\nfrom ariadne_auth.types import HasPermissions\n\n\n# Define a function that returns the permission object\ndef get_permission_obj(info: GraphQLResolveInfo) -> HasPermissions:\n return info.context[\"my_permission_obj\"]\n\n# it can be also an async function\nasync def get_permission_obj_async(info: GraphQLResolveInfo) -> HasPermissions:\n return info.context[\"my_permission_obj\"]\n\n\n# Instantiate the AuthorizationExtension\nauthz = AuthorizationExtension(permissions_object_provider_fn=get_permission_obj)\n\n# Set list of permissions required for all resolvers \nauthz.set_required_global_permissions([\"user:logged_in\"])\n```\n\n\n### Configure resolvers\n```python\nquery = QueryType()\nship = ObjectType(\"Ship\")\nfaction = ObjectType(\"Faction\")\n\n# Set additional required permissions for specific resolvers\n@query.field(\"rebels\")\n@authz.require_permissions(permissions=[\"read:rebels\"]) # + \"user:logged_in\"\nasync def resolve_rebels(*_):\n return FACTIONS[0]\n\n\n@query.field(\"empire\")\n@authz.require_permissions(permissions=[\"read:empire\"], ignore_global_permissions=False) # + \"user:logged_in\"\nasync def resolve_empire(*_):\n return FACTIONS[1]\n\n\n\n# Disable global permissions for specific resolver\n@query.field(\"ships\")\n@authz.require_permissions(permissions=[], ignore_global_permissions=True) # + \"user:logged_in\"\nasync def resolve_ships(obj, *_):\n return SHIPS\n\n# Note the global permission is set on default_field_resolver method\n# and it requires to disable permissions explicit for each field\n@ship.field(\"name\")\n@authz.require_permissions(permissions=[], ignore_global_permissions=True)\nasync def resolve_ship_name(obj, *_):\n return obj[\"name\"]\n```\n\nIf needed you may also overwrite the function to get the permission object for specific resolver\n```python\ndef get_ship_permissions(info: GraphQLResolveInfo) -> HasPermissions:\n return info.context[\"my_ship_permission_obj\"]\n\n@ship.field(\"name\")\n@authz.require_permissions(\n permissions=[],\n ignore_global_permissions=True,\n permissions_object_provider_fn=get_ship_permissions\n)\nasync def resolve_ship_name(obj, *_):\n return obj[\"name\"]\n\n```\n\n\n### Add your extension to Ariadne GraphQL instance\n```python\napp = GraphQL(\n schema,\n http_handler=GraphQLHTTPHandler(extensions=[authz]), # add the authz extension\n)\n```\n \nYou may also pass `authz` instance into info.context to use it directly \n\nuse `_auth.assert_permissions` or `await _auth.assert_permissions_async` to check permissions in your resovlers\n```python\n# Depends on the faction, additional permissions are required\n@faction.field(\"ships\")\nasync def resolve_faction_ships(faction_obj, info: GraphQLResolveInfo, *_):\n _auth = info.context[\"auth\"]\n if (\n faction_obj[\"name\"] == \"Alliance to Restore the Republic\"\n ): # Rebels faction requires additional perm to read ships\n _auth.assert_permissions(_auth.permissions_object_provider_fn(info), [\"read:ships\"])\n\n return [_ship for _ship in SHIPS if _ship[\"factionId\"] == faction_obj[\"id\"]]\n\n\n\ndef get_context_value(request, data):\n return {\n **authz.generate_authz_context(request),\n }\n\n\napp = GraphQL(\n schema,\n context_value=get_context_value,\n http_handler=GraphQLHTTPHandler(extensions=[authz])\n)\n```\n\n\n## Run test app \nThe repository contains a test application that demonstrates how to use the library\n\n#### To run test application use: `hatch run ariadne_auth`\nNote that `user_id` is hardcoded in `test_app/app.py:148`\n\n\n### Example request\nfor user with permissions\n```\n permissions=[\n \"user:logged_in\",\n \"read:empire\",\n \"read:rebels\",\n ], # can't read rebels ships\n```\n```graphql\nquery {\n empire{\n id\n name\n ships {\n id\n name\n }\n }\n rebels{\n id\n name\n ships {\n name\n }\n }\n ships {\n name\n }\n}\n```\n\n## Versioning policy ##\nariadne-auth follows a custom versioning scheme where the minor version increases for breaking changes, while the patch version increments for bug fixes, enhancements, and other non-breaking updates.\n\nSince ariadne-auth has not yet reached a stable API, this approach is in place until version 1.0.0. Once the API stabilizes, the project will adopt Semantic Versioning.\n\n----------------\n\n**Crafted with \u2764\ufe0f by [Mirumee Software](https://mirumee.com)**\nhello@mirumee.com",
"bugtrack_url": null,
"license": null,
"summary": "An Ariadne extension for authorization, allowing global permissions for all resolvers and fine-grained control over required permissions for specific resolvers in GraphQL APIs.",
"version": "0.0.1.dev5",
"project_urls": {
"Homepage": "https://github.com/mirumee/ariadne-auth",
"Issues": "https://github.com/mirumee/ariadne-auth/issues"
},
"split_keywords": [
"ariadne",
" ariadne-extension",
" authorization",
" permissions"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "684653d66d5ed791894d66fad039482f9ae7b774df0be6ea1dda932a4eda9830",
"md5": "d230273e164f3688e3b16cd30de2552e",
"sha256": "ac7eca2672ef6d8febb65cb7471cfb11de809a8135b397b13cbee304aa1a527d"
},
"downloads": -1,
"filename": "ariadne_auth-0.0.1.dev5-py3-none-any.whl",
"has_sig": false,
"md5_digest": "d230273e164f3688e3b16cd30de2552e",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.9",
"size": 6468,
"upload_time": "2025-02-25T16:32:22",
"upload_time_iso_8601": "2025-02-25T16:32:22.304748Z",
"url": "https://files.pythonhosted.org/packages/68/46/53d66d5ed791894d66fad039482f9ae7b774df0be6ea1dda932a4eda9830/ariadne_auth-0.0.1.dev5-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "f093890010ca9458fb58e6bd14559b20eb0e3204c8236e53315e35ff2ddbf86b",
"md5": "54a7760385864f70ef974b8061765f2a",
"sha256": "d9ff0df5fea862e2f0061d6920cd4c62782adb04436d2654ef87b64079b9c832"
},
"downloads": -1,
"filename": "ariadne_auth-0.0.1.dev5.tar.gz",
"has_sig": false,
"md5_digest": "54a7760385864f70ef974b8061765f2a",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.9",
"size": 10820,
"upload_time": "2025-02-25T16:32:23",
"upload_time_iso_8601": "2025-02-25T16:32:23.707280Z",
"url": "https://files.pythonhosted.org/packages/f0/93/890010ca9458fb58e6bd14559b20eb0e3204c8236e53315e35ff2ddbf86b/ariadne_auth-0.0.1.dev5.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-02-25 16:32:23",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "mirumee",
"github_project": "ariadne-auth",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "ariadne-auth"
}