# -*- coding: utf-8 -*-
from setuptools import setup

packages = \
['siwe_auth',
 'siwe_auth.custom_groups',
 'siwe_auth.migrations',
 'siwe_auth.utils']

package_data = \
{'': ['*'], 'siwe_auth': ['static/siwe_auth/js/*', 'templates/siwe_auth/*']}

install_requires = \
['Django>=4.0.1,<5.0.0',
 'django-ratelimit>=3.0.1,<4.0.0',
 'pytz>=2021.3,<2022.0',
 'siwe>=1.0.0,<2.0.0',
 'web3>=5.26.0,<6.0.0']

setup_kwargs = {
    'name': 'django-siwe-auth',
    'version': '0.3.0',
    'description': 'Custom Django authentication backend using Sign-In with Ethereum (EIP-4361) with a custom wallet user model.',
    'long_description': '<div id="top"></div>\n\n<!-- PROJECT SHIELDS -->\n[![Contributors][contributors-shield]][contributors-url]\n[![Forks][forks-shield]][forks-url]\n[![Stargazers][stars-shield]][stars-url]\n[![Issues][issues-shield]][issues-url]\n[![MIT License][license-shield]][license-url]\n\n<!-- PROJECT LOGO -->\n<br />\n<div align="center">\n  <a href="https://github.com/payton/django-siwe-auth">\n    <img src="images/logo.png" alt="Logo" width="400" height="auto">\n  </a>\n<h3 align="center">Django Sign-In with Ethereum Auth</h3>\n  <p align="center">\n    A complete Django authentication system overhaul for Web3. Treat Ethereum wallets as first-class citizens with authentication via Sign-In with Ethereum (EIP-4361) and authorization via on-chain attributes such as NFT (ERC721/ERC1155) and ERC20 token ownership. \n    <br />\n    <h4><b><u>DISCLAIMER: django-siwe-auth is still in early development (it will change often!)</u></b></h4>\n    <a href="https://github.com/payton/django-siwe-auth"><strong>Explore the docs »</strong></a>\n    <br />\n    <br />\n    <a href="https://github.com/payton/django-siwe-auth">Live Demo</a>\n    ·\n    <a href="https://github.com/payton/django-siwe-auth/issues">Report Bug</a>\n    ·\n    <a href="https://github.com/payton/django-siwe-auth/issues">Request Feature</a>\n  </p>\n</div>\n\n<!-- TABLE OF CONTENTS -->\n<details>\n  <summary>Table of Contents</summary>\n  <ol>\n    <li>\n      <a href="#about-the-project">About The Project</a>\n    </li>\n    <li>\n      <a href="#getting-started">Getting Started</a>\n    </li>\n    <li>\n        <a href="#usage">Usage</a>\n        <ul>\n            <li><a href="#useful-resources">Useful Resources</a></li>\n            <li><a href="#install">Install</a></li>\n            <li><a href="#rest-api">REST API</a></li>\n            <li><a href="#configuring-your-project">Configuring Your Project</a></li>\n            <li><a href="#group-plugins">Group Plugins</a></li>\n        </ul>\n    </li>\n    <li><a href="#contributing">Scenarios</a></li>\n    <li><a href="#contributing">Contributing</a></li>\n    <li><a href="#license">License</a></li>\n    <li><a href="#contact">Contact</a></li>\n    <li><a href="#acknowledgments">Acknowledgments</a></li>\n    <li><a href="#disclaimer">Disclaimer</a></li>\n  </ol>\n</details>\n\n<!-- ABOUT THE PROJECT -->\n## About The Project\n\nThis app provides four key features for new or existing Django projects.\n\n<ol>\n<li><b>Authentication Backend</b></li>\n<ul>\n<li>Authenticate incoming requests via the Sign-In with Ethereum (<a href="https://eips.ethereum.org/EIPS/eip-4361">EIP-4361</a>) standard.</li>\n</ul>\n<li><b>User Model</b></li>\n<ul>\n<li>Replace original user model with wallet model that is dependent on an Ethereum address.</li>\n<li>Removes the liability of storing user credentials in favor of managing transient session data (<a href="https://docs.djangoproject.com/en/4.0/topics/http/sessions/">handled by Django out of the box</a>).</li>\n<li><a href="https://ens.domains/">ENS</a> profile information is pulled by default.</li>\n</ul>\n<li><b>Groups</b></li>\n<ul>\n<li>Create custom user groups based on on-chain (or off-chain!) attributes.</li>\n<li>For example, we can easily define a group of <a href="https://boredapeyachtclub.com/#/">BAYC</a> owners by validating NFT ownership and subsequently serve them special content that non-owners don\'t have access to.</li>\n<li>This extension builds off of Django\'s well-defined <a href="https://docs.djangoproject.com/en/4.0/topics/auth/default/#permissions-and-authorization">authorization system</a>.</li>\n</ul>\n</ol>\n\nBelow is the included example application that authenticates with an Ethereum address and utilizes on-chain attributes to authorize access to various notepads.\n<div align="center">\n   <img src="images/example.gif" alt="Example Project" width="800" height="auto">\n</div>\n\n<p align="right">(<a href="#top">back to top</a>)</p>\n\n<!-- GETTING STARTED -->\n## Getting Started\n\nWith the included example applications, you can test out Sign-In with Ethereum along with using and creating custom groups. To get an example application up and running follow these steps.\n\n### Prerequisites\n\nRequirements for developing and running examples apps:\n* [poetry](https://python-poetry.org/docs/)\n* [npm](https://www.npmjs.com/)\n\n### Demo Application\n\n1. Install NPM dependencies\n   ```sh\n   npm --prefix examples/notepad/frontend install examples/notepad/frontend\n   ```\n2. Build frontend\n   ```sh\n   npm run --prefix examples/notepad/frontend build\n   ```\n3. Install Python dependencies\n   ```sh\n   poetry install\n   ```\n4. Set Web3 provider environment variable\n   ```sh\n   export SIWE_AUTH_PROVIDER="https://mainnet.infura.io/v3/..." # Any provider works\n   ```\n5. Django migrations\n   ```sh\n   # Create Django migrations\n   poetry run examples/notepad/manage.py makemigrations\n   # Apply Django migrations\n   poetry run examples/notepad/manage.py migrate\n   ```\n6. Run server\n   ```sh\n   poetry run examples/notepad/manage.py runserver\n   ```\n7. Test application at `https://localhost:8000`\n\n<p align="right">(<a href="#top">back to top</a>)</p>\n\n### Rebuild Demo JavaScript\nIf you make an update to the frontend directory or siwe submodule, rebuild bundle.js:\n```sh\ncd examples/notepad/frontend \\\nnpm install \\\nnpm run build\n```\n\n\n<!-- USAGE EXAMPLES -->\n## Usage\n\nThis project is highly configurable and modular allowing for applications to be as simple or complex as required. Authentication and authorization can be completely replaced or supplemented depending upon the use case. See scenario docs for detailed tutorials.\n\n### Useful Resources\n* [User authentication in Django](https://docs.djangoproject.com/en/4.0/topics/auth/)\n* [Customizing authentication in Django](https://docs.djangoproject.com/en/4.0/topics/auth/customizing/)\n* [How to Switch to a Custom Django User Model Mid-Project](https://www.caktusgroup.com/blog/2019/04/26/how-switch-custom-django-user-model-mid-project/)\n\n### Install\n\n#### Prerequisites\n\nRequirements for using `django-siwe-auth` in a Django application:\n* [pip](https://pip.pypa.io/en/stable/installation/)\n* [django](https://docs.djangoproject.com/en/4.0/intro/install/)\n* An existing [Django project](https://docs.djangoproject.com/en/4.0/intro/tutorial01/)\n\n1. Install package\n   ```sh\n   pip install django-siwe-auth\n   ```\n2. Add `siwe_auth.apps.SiweAuthConfig` to INSTALLED_APPS in your project\'s `settings.py`\n   ```python\n   INSTALLED_APPS = [\n    ...\n    "siwe_auth.apps.SiweAuthConfig", # Adds django-siwe-auth\n    "django.contrib.admin",\n    "django.contrib.auth",\n    "django.contrib.contenttypes",\n    "django.contrib.sessions",\n    "django.contrib.messages",\n    "django.contrib.staticfiles",\n   ]\n   ```\n3. Add app-specific definitions to your project\'s `settings.py` (same files as previous step). For more information, see the <a href="#configuring-your-project">Configuring Your Project</a> section\n   ```python\n   from siwe_auth.custom_groups.erc721 import ERC721OwnerManager\n   ...\n   # Django Sign-In with Ethereum Auth Settings\n   AUTH_USER_MODEL = "siwe_auth.Wallet"\n   AUTHENTICATION_BACKENDS = ["siwe_auth.backend.SiweBackend"]\n   LOGIN_URL = "/"\n   SESSION_COOKIE_AGE = 3 * 60 * 60 \n   CREATE_GROUPS_ON_AUTHN = False # defaults to False\n   CREATE_ENS_PROFILE_ON_AUTHN = True # defaults to True\n   CUSTOM_GROUPS = [\n       (\'ens_owners\', ERC721OwnerManager(config={\'contract\': \'0x57f1887a8BF19b14fC0dF6Fd9B2acc9Af147eA85\'})),\n       (\'bayc_owners\', ERC721OwnerManager(config={\'contract\': \'0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D\'})),\n       (\'shib_owners\', ERC20OwnerManager(config={\'contract\': \'0x95ad61b0a150d79219dcf64e1e6cc01f0b64c4ce\'})),\n   ]  # See "Group Plugins" section\n   PROVIDER = os.environ.get("SIWE_AUTH_PROVIDER", "https://mainnet.infura.io/v3/...")\n   ...\n   ```\n4. Add `api/auth/` endpoint to your project\'s `urls.py`\n   ```python\n   urlpatterns = [\n    path("admin/", admin.site.urls),\n    path("api/auth/", include("siwe_auth.urls")),\n    ...\n   ]\n   ```\n5. Run `manage.py makemigrations` and `manage.py migrate` to create custom user model\n6. Update frontend to interface with the <a href="#rest-api">REST API</a> as defined below. An example frontend is available in the notepad demo.\n7. Never handle a password ever again!\n\nFor more examples, please refer to the [Documentation](https://github.com/payton/django-siwe-auth)\n\n<p align="right">(<a href="#top">back to top</a>)</p>\n\n\n\n\n### REST API\n\nProjects that use this app will interact via these endpoints for authentication. Tools for authorization are provided but not enforced via any endpoints.\n\n#### Login\n* Authenticate user based on signed message.\n\n<details>\n<summary>/api/auth/logout</summary>\n\n* **Method:**\n\n  `POST`\n\n* **URL Params**\n\n   None\n\n* **Data Params**\n\n  **Required:**\n  SIWE Message\n\n* **Success Response:**\n\n   * **Code:** 200 <br />\n     **Content:** `{"success": True, "message": "Successful login."}`\n\n* **Error Response:**\n\n   * **Code:** 401 UNAUTHORIZED <br />\n     **Content:** `{"success": False, "message": "Wallet disabled."}`\n\n  OR\n\n   * **Code:** 403 FORBIDDEN <br />\n     **Content:** `{"success": False, "message": "Invalid login."}`\n\n  OR\n\n    * **Code:** 429 TOO MANY REQUESTS <br />\n      **Content:** `{"message": "Too many requests. Slow down."}`\n\n* **Sample Call:**\n```javascript\nfetch(`/api/auth/login`, {\n    method: \'POST\',\n    body: JSON.stringify({ message }),\n    headers: { \'Content-Type\': \'application/json\' },\n    credentials: \'include\',\n}).then(async (res) => {\n    if (res.status === 200) {\n        // Success, continue with authenticated flow\n    } else {\n        // Failure, handle alternative path\n    }\n});\n```\n\n</details>\n\n#### Logout\n\n* Logout authenticated user.\n\n<details>\n<summary>/api/auth/logout</summary>\n\n* **Method:**\n\n  `POST`\n\n* **URL Params**\n\n  None\n\n* **Data Params**\n\n  None\n\n* **Success Response:**\n\n    * **Code:** 200 <br />\n      **Content:** `{"success": True, "message": "Successful login."}`\n\n* **Error Response:**\n\n    * **Code:** 401 UNAUTHORIZED <br />\n      **Content:** `{"success": False, "message": "Wallet disabled."}`\n\n  OR\n\n    * **Code:** 403 FORBIDDEN <br />\n      **Content:** `{"success": False, "message": "Invalid login."}`\n\n  OR\n\n    * **Code:** 429 TOO MANY REQUESTS <br />\n      **Content:** `{"message": "Too many requests. Slow down."}`\n\n* **Sample Call:**\n```javascript\nfetch(\'/api/authentication/logout\', {\n    method: \'POST\',\n    credentials: \'include\',\n}).then(() => {\n    // Success, continue with logout flow\n});\n```\n</details>\n\n#### Nonce\n\n* Get temporary nonce to include in EIP-4361 (SIWE) message.\n\n<details>\n<summary>/api/auth/nonce</summary>\n\n* **Method:**\n\n  `GET`\n\n* **URL Params**\n\n  None\n\n* **Data Params**\n\n  None\n\n* **Success Response:**\n\n    * **Code:** 200 <br />\n      **Content:** `{"success": True, "message": "Successful login."}`\n\n* **Error Response:**\n\n    * **Code:** 429 TOO MANY REQUESTS <br />\n      **Content:** `{"message": "Too many requests. Slow down."}`\n\n* **Sample Call:**\n```javascript\nfetch(\'/api/authentication/nonce\', { \n    credentials: \'include\' \n}).then((res) =>\n    // Success, continue with message signing flow\n);\n```\n</details>\n\n<p align="right">(<a href="#top">back to top</a>)</p>\n\n\n\n### Configuring Your Project\n\n#### Relevant native Django settings\n\n```py\n# in settings.py\nAUTH_USER_MODEL = "siwe_auth.Wallet" # required for siwe as the default authentication\nAUTHENTICATION_BACKENDS = ["siwe_auth.backend.SiweBackend"] # required for siwe as the default authentication\nLOGIN_URL = "/" # optional, django\'s default is "/accounts/login/"\nSESSION_COOKIE_AGE = 3 * 60 * 60 # Age of cookie, in seconds. Optional, django\'s default is weeks.\n```\n\n#### django-siwe-auth specific settings\n```py\n# in settings.py\nCREATE_GROUPS_ON_AUTHN = True # optional, default is False\nCREATE_ENS_PROFILE_ON_AUTHN = True # optional, default is True\nCUSTOM_GROUPS = [] # optional, see "Adding a Group" below\n# Set environment variable SIWE_AUTH_PROVIDER for Web3.py\n# - Required if CREATE_GROUPS_ON_AUTHN or CREATE_ENS_PROFILE_ON_AUTHN are True. Optional otherwise.\n#   Any ethereum API key (infura or alchemy) will work.\nPROVIDER = os.environ.get("SIWE_AUTH_PROVIDER", "https://mainnet.infura.io/v3/...")\n```\n\n#### Override Admin Login Page\n\nIn order to login to the django admin page with siwe-auth, we need to override the login template.\n\n```python\n# in your app\'s admin.py, add the following line\nadmin.site.login_template = \'siwe_auth/login.html\'\n```\n\n\n<!-- USAGE EXAMPLES -->\n### Group Plugins\nA group plugin allows you to define your own group whose membership is defined by the output of a membership function. Some examples of what the membership function may check for include but are not limited to: NFT ownership, ERC-20 token ownership, ENS data, etc.\n\n#### GroupManager Class\nAll group plugins must implement the GroupManager class. This includes a function called `is_member` that is called to determine group membership when a user authenticates with the server.\n```python\nfrom abc import ABC, abstractmethod\n\nclass GroupManager(ABC):\n\n   @abstractmethod\n   def __init__(self, config: dict):\n      pass\n\n   @abstractmethod\n    def is_member(self, wallet: object) -> bool:\n        pass\n```\n\n#### Included Managers\n\n<ul>\n<li>ERC20Manager\n    <ul>\n        <li>ERC20OwnerManager</li>\n    </ul>\n</li>\n<li>ERC721Manager\n    <ul>\n        <li>ERC721OwnerManager</li>\n    </ul>\n</li>\n<li>ERC1155Manager\n    <ul>\n        <li>ERC1155OwnerManager</li>\n    </ul>\n</li>\n</ul>\n\n#### Adding a Group\nA custom group is defined by a tuple consisting of a name (string), MemberManager implementation.\n\nThe GroupManager\'s config can be used for anything, but some likely usecases are defining contract addresses or address include/exclude lists.\n\nIn your project\'s `settings.py`, append your group to the `CUSTOM_GROUPS` list added in the installation steps.\n\nSuppose we want to have only one group for `BAYC` (ERC721 NFT) owners and another group for `LPT` (ERC20 Token) owners. Our list would then look like:\n```python\nfrom siwe_auth.custom_groups.erc721 import ERC721OwnerManager\nfrom siwe_auth.custom_groups.erc20 import ERC20OwnerManager\n...\nCUSTOM_GROUPS=[\n   (\'bayc_owners\', ERC721OwnerManager(config={\'contract\': \'0xbc4ca0eda7647a8ab7c2061c2e118a18a936f13d\'})),\n   (\'lpt_owners\', ERC20OwnerManager(config={\'contract\': \'0x58b6a8a3302369daec383334672404ee733ab239\'})),\n]\n```\n\n\n\n## Scenarios (WIP)\n\nExamples:\n1. Start a new web app with wallet user model.\n2. Replace existing user model with wallet user model (non-trivial).\n3. Replace existing user model with weaker wallet user model that implements base model (less non-trivial but still non-trivial).\n4. Creating permissions around on-chain based groups.\n\n\n\n<!-- CONTRIBUTING -->\n## Contributing\n\nContributions are what make the open source community such an amazing place to learn, inspire, and create. Any contributions you make are **greatly appreciated**.\n\nIf you have a suggestion that would make this better, please fork the repo and create a pull request. You can also simply open an issue with the tag "enhancement".\nDon\'t forget to give the project a star! Thanks again!\n\n1. Fork the Project\n2. Create your Feature Branch (`git checkout -b feature/AmazingFeature`)\n3. Commit your Changes (`git commit -m \'Add some AmazingFeature\'`)\n4. Push to the Branch (`git push origin feature/AmazingFeature`)\n5. Open a Pull Request\n\n<p align="right">(<a href="#top">back to top</a>)</p>\n\n\n\n<!-- LICENSE -->\n## License\n\nDistributed under the MIT License. See `LICENSE.txt` for more information.\n\n<p align="right">(<a href="#top">back to top</a>)</p>\n\n\n\n<!-- CONTACT -->\n## Contact\n\npayton - [@paytongarland](https://twitter.com/paytongarland) - paytongarland.eth\n\nProject Link: [https://github.com/payton/django-siwe-auth](https://github.com/payton/django-siwe-auth)\n\n<p align="right">(<a href="#top">back to top</a>)</p>\n\n\n\n<!-- ACKNOWLEDGMENTS -->\n## Acknowledgments\n\n* [Spruce](https://www.spruceid.com/) - creators of EIP-4361\n* [jsdelivr](https://www.jsdelivr.com/) - external static asset distribution in example app\n* [Best-README-Template](https://github.com/othneildrew/Best-README-Template)\n* [98.css](https://jdan.github.io/98.css/)\n* [API Documentation Format](https://gist.github.com/iros/3426278)\n\n<p align="right">(<a href="#top">back to top</a>)</p>\n\n## Disclaimer\nThis django auth library has not yet undergone a formal security audit. We welcome continued feedback on the usability, architecture, and security of this implementation.\n\n<p align="right">(<a href="#top">back to top</a>)</p>\n\n<!-- MARKDOWN LINKS & IMAGES -->\n<!-- https://www.markdownguide.org/basic-syntax/#reference-style-links -->\n[contributors-shield]: https://img.shields.io/github/contributors/payton/django-siwe-auth.svg?style=for-the-badge\n[contributors-url]: https://github.com/payton/django-siwe-auth/graphs/contributors\n[forks-shield]: https://img.shields.io/github/forks/payton/django-siwe-auth.svg?style=for-the-badge\n[forks-url]: https://github.com/payton/django-siwe-auth/network/members\n[stars-shield]: https://img.shields.io/github/stars/payton/django-siwe-auth.svg?style=for-the-badge\n[stars-url]: https://github.com/payton/django-siwe-auth/stargazers\n[issues-shield]: https://img.shields.io/github/issues/payton/django-siwe-auth.svg?style=for-the-badge\n[issues-url]: https://github.com/payton/django-siwe-auth/issues\n[license-shield]: https://img.shields.io/github/license/payton/django-siwe-auth.svg?style=for-the-badge\n[license-url]: https://github.com/payton/django-siwe-auth/blob/main/LICENSE.txt\n[product-screenshot]: images/screenshot.png\n',
    'author': 'Payton Garland',
    'author_email': 'payton.r.g@gmail.com',
    'maintainer': None,
    'maintainer_email': None,
    'url': 'https://github.com/payton/django-siwe-auth',
    'packages': packages,
    'package_data': package_data,
    'install_requires': install_requires,
    'python_requires': '>=3.8,<4.0',
}


setup(**setup_kwargs)
