Metadata-Version: 2.4
Name: ngits-drf-cube-proxy
Version: 1.0.1
Summary: Cube.js JWT proxy for Django REST Framework
Author-email: "NG IT Services Sp. z o. o." <biuro@ngits.pl>
License: BSD-3-Clause
Project-URL: Homepage, https://ngits.dev
Classifier: Environment :: Web Environment
Classifier: Framework :: Django
Classifier: Framework :: Django :: 5.0
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: BSD License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3.11
Classifier: Topic :: Internet :: WWW/HTTP
Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
Requires-Python: >=3.11
Description-Content-Type: text/x-rst
Requires-Dist: Django<6.0,>=5.0
Requires-Dist: djangorestframework<4.0,>=3.15
Requires-Dist: PyJWT<3.0,>=2.8
Requires-Dist: requests>=2.30
Provides-Extra: schemas
Requires-Dist: drf-spectacular>=0.27; extra == "schemas"

ngits-drf-cube-proxy
====================

Server-side proxy for the Cube.js ``/load`` endpoint, packaged as a small
Django/DRF application. The proxy signs an HS256 JWT per request with an
identity value (e.g. a tenant UUID, an organisation id, a project id …)
resolved from the authenticated user, so the Cube.js secret never reaches
the browser.

Setup
-----

1. Install with pip:
~~~~~~~~~~~~~~~~~~~~

::

    pip install ngits-drf-cube-proxy

   (or ``pip install "ngits-drf-cube-proxy[schemas]"`` for the
   drf-spectacular OpenAPI schemas)

2. Update your ``settings`` file:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

::

    import os

    INSTALLED_APPS = [
        ...
        "rest_framework",
        "cube_proxy",
    ]

    # Required
    CUBEJS_API_URL = os.environ["CUBEJS_API_URL"]
    CUBEJS_API_SECRET = os.environ["CUBEJS_API_SECRET"]
    CUBE_PROXY_IDENTITY_RESOLVER = "myproject.cube.resolve_identity"

    # Optional
    CUBE_PROXY_PERMISSION_CLASSES = (
        "rest_framework.permissions.IsAuthenticated",
        "myproject.permissions.IsModerator",
    )
    CUBE_PROXY_JWT_CLAIM_NAME = "tenant"                 # default
    CUBE_PROXY_JWT_TTL_HOURS = 24                        # default
    CUBE_PROXY_JWT_ALGORITHM = "HS256"                   # default
    CUBE_PROXY_REQUEST_TIMEOUT = 30                      # default
    CUBE_PROXY_IDENTITY_NOT_FOUND_DETAIL = "Identity could not be resolved."

   ``CUBE_PROXY_IDENTITY_RESOLVER`` is the dotted path to a callable
   ``resolve(user) -> str | None``. The returned value is stamped into the
   JWT under ``CUBE_PROXY_JWT_CLAIM_NAME`` (default ``tenant``) and becomes
   the Cube.js security-context key. Returning ``None`` yields a
   ``403 {"detail": "Identity could not be resolved."}`` response.

3. Add the URLs:
~~~~~~~~~~~~~~~~

::

    from django.urls import include, path

    urlpatterns = [
        ...
        path("cube/", include("cube_proxy.urls")),
    ]

   The endpoint is then available at ``/cube/load/`` and accepts both ``GET``
   (query-as-URL-params, used by the Cube.js JS SDK for small queries) and
   ``POST`` (query in body, used for large queries).
