{"id":13489262,"url":"https://github.com/capless/pfunk","last_synced_at":"2025-03-28T04:31:00.031Z","repository":{"id":37201465,"uuid":"238505917","full_name":"capless/pfunk","owner":"capless","description":"A Python library to make writing applications with FaunaDB easier. Includes GraphQL and generic ABAC auth workflow integrations.","archived":false,"fork":false,"pushed_at":"2023-05-04T07:10:32.000Z","size":946,"stargazers_count":6,"open_issues_count":12,"forks_count":1,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-10-31T02:33:37.574Z","etag":null,"topics":["fauna","faunadb","orm"],"latest_commit_sha":null,"homepage":"https://www.pfunk.io/docs/pfunk.html","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/capless.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2020-02-05T17:14:48.000Z","updated_at":"2024-01-19T01:39:04.000Z","dependencies_parsed_at":"2024-01-16T09:05:23.332Z","dependency_job_id":"1f8d44cf-19b8-40bd-809c-2dfa56efdec8","html_url":"https://github.com/capless/pfunk","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/capless%2Fpfunk","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/capless%2Fpfunk/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/capless%2Fpfunk/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/capless%2Fpfunk/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/capless","download_url":"https://codeload.github.com/capless/pfunk/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245970395,"owners_count":20702401,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["fauna","faunadb","orm"],"created_at":"2024-07-31T19:00:21.429Z","updated_at":"2025-03-28T04:30:59.644Z","avatar_url":"https://github.com/capless.png","language":"Python","readme":"![Pfunk logo](https://qwigocom.b-cdn.net/opensource/images/pfunk.png?width=160 \"Pfunk\")\n\nA Python library to make writing applications with FaunaDB easier. \nIncludes GraphQL and generic ABAC auth workflow integrations.\n\n## Key Features\n- DRY (Don't Repeat Yourself) code to help you create multiple collections, indexes, roles, and user-defined functions \n  quickly. This helps you create more functionality with less code. \n- Mix and match authorization workflows (Group and user based)\n- Group level permissions\n- Create a GraphQL endpoint and a schema validating ORM with the same code.\n- Authentication collections, indexes, user-defined functions, and roles included.\n- Generic CRUD user-defined functions included\n- Create a REST API to integrate Fauna and Non-Fauna related tasks\n- Schema validation based on the [Valley](https://github.com/capless/valley) library.\n\n## Full Documentation\n\n[Documentation](https://pfunk.carcamp.dev/docs/pfunk.html)\n\n## Table of Contents\n\n- [Getting Started](#Getting-Started)\n    - [Installation](#Installation)\n    - [Setup the Connection](#setup-the-connection)\n    - [Define your Collections](#define-your-collections-collectionspy)\n    - [Choose an Auth Workflow](#auth-workflows)\n    - [Publish](#publish)\n    - [Save Some Data](#save-some-data)\n    - [Query Your Data](#query-your-data)\n    - [Delete a Record](#delete-a-record)\n        \n\n\n### Getting Started\n\n### Installation\n```pip install pfunk```\n\n### Setup the Connection\n\n#### Using Environment Variables (Preferred Method)\n\nIf you can easily set environment variables just set the ```FAUNA_SECRET``` environment variable to your key.\n\n### Define your Collections (collections.py)\n\nFor an example project let's create a project management app. \n\n```python\nfrom pfunk import (Collection, StringField, ReferenceField, DateField,\n                   Project, Enum, EnumField, IntegerField, FloatField,\n                  SlugField)\nfrom pfunk.contrib.auth.collections import User, Group\nfrom pfunk.contrib.auth.resources import GenericGroupBasedRole, GenericUserBasedRole\n\n\n\nSTATUS = Enum(name='ProductStatus', choices=['unstarted', 'started', 'completed', 'delivered'])\n\n\nclass AbstractGroupCollection(Collection):\n    \"\"\"\n    Abstract Collection very similar to abstract models in Django. \n    The main difference is you don't have to add abstract=True in the Meta class.\n    \"\"\"\n    # Here we are defining the roles that should be \n    # created for this collection (by proxy this role will be applied \n    # to its subclasses. We could however change the list of roles below.\n    collection_roles = [GenericGroupBasedRole]\n    title = StringField(required=True)\n    group = ReferenceField(Group, required=True)\n    \n    def __unicode__(self):\n        return self.title\n    \n    \nclass Product(AbstractGroupCollection):\n    slug = SlugField(required=True)\n    description = StringField()\n    due_date = DateField(required=False)\n    \n    class Meta:\n        \"\"\"\n        Add unique together index to ensure that the same slug is not used \n        for more than one product that belongs to a group. Similar to the\n        Github's repo naming convention ex. https://github.com/capless/pfunk. \n        In that example 'capless' is the group slug and 'pfunk' is the \n        product's slug\n        \"\"\"\n        unique_together = ('slug', 'group')\n    \n    \nclass Sprint(AbstractGroupCollection):\n    product = ReferenceField(Product, required=True)\n    start_date = DateField(required=True)\n    end_date = DateField(required=True)\n    \n    \nclass Story(AbstractGroupCollection):\n    description = StringField()\n    points = IntegerField()\n    product = ReferenceField(Product, required=True)\n    sprint = ReferenceField(Sprint, required=False)\n    status = EnumField(STATUS)\n    \n\n# Create a Project\nproject = Project()\n\n# Add Collections to the Project\nproject.add_resources([User, Group, Product, Story, Sprint])\n\n```\n### Auth Workflows\n\nIn the example above, the ```collection_roles``` list on the ```Collection``` classes attaches generic roles to the \ncollection.  Currently, you can choose a **group based** workflow, **user based**, or a **mix** of the two.\n\n#### User Based Role\n\nThis role allows you to create, read, write, and delete documents that you haveyou are the owner of. The `user` field determines if you are the owner.\n\n#### Group Based Role\n\nThis role allows you to create, read, write, and delete documents if both of the following conditions are true: \n\n1. You belong to the group that owns the document\n2. You have the create permission to perform the action (`create`, `read`, `write`, and `delete`) \n\n### Publish\n\n```python\nproject.publish()\n```\n\n### Create Group and User\nBoth of the code samples below will create a new user, group, and users_groups (many-to-many relationship through collection) record.\n```python\nfrom pfunk.contrib.auth.collections import Group, User\ngroup = Group.create(name='base', slug='base')\n\n# Example 2: You could also create a user with the following code\nuser = User.create(username='notthegoat', first_name='Lebron', last_name='James',\n                   email='notthegoat@gmail.com', account_status='ACTIVE', groups=[group],\n                   _credentials='hewillneverbethegoat')\n\n```\n\n### Give User New Permissions\n\n```python\n# User instance from above (username: notthegoat)\nuser.add_permissions(group, ['create', 'read', 'write', 'delete'])\n```\n### Login\n\n```python\nfrom pfunk.contrib.auth.collections import User\n\n#The login classmethod returns the authenticated token if the credentials are correct.\ntoken = User.login('goat23', 'cruelpass')\n```\n\n\n### Save Some Data\nLet's use the Video collection, and the authenticated token we created above to save some data.\n\n```python\n# Use the token from above so the current users permissions are used.\n\n\nproduct = Product.create(\n    title='PFunk Project',\n    slug='pfunk',\n    description='Some example project for test Pfunk',\n    group=group,\n    _token=token #The token gained in the previous step. If you do not specify a token here it defaults to the key used in the FAUNA_SECRET env.\n)\n\n```\n\n### Query your Data\nLet's get the video you just created.\n\n```python\nproduct = Product.get('the-key-for-the-previous-video', _token=token)\n```\n\nLet's query for all videos using the server key.\n\n```python\nproducts = Products.all()\n```\n\nLet's query for all videos that the logged in user has access to.\n\n```python\n\nproducts = Products.all(_token=token)\n```\n\n### Delete a Record\n\nLet's delete the record from above.\n\n```python\nproduct.delete()\n```\n","funding_links":[],"categories":["Tools"],"sub_categories":["Wrappers and libraries"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcapless%2Fpfunk","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcapless%2Fpfunk","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcapless%2Fpfunk/lists"}