django-clerk-users 0.1.0__tar.gz → 0.1.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (108) hide show
  1. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/PKG-INFO +1 -1
  2. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/pyproject.toml +1 -1
  3. django_clerk_users-0.1.1/src/django_clerk_users/authentication/backends.py +83 -0
  4. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/uv.lock +1 -1
  5. django_clerk_users-0.1.0/src/django_clerk_users/authentication/backends.py +0 -89
  6. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/.flake8 +0 -0
  7. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/.github/workflows/main.yaml +0 -0
  8. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/.gitignore +0 -0
  9. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/.pre-commit-config.yaml +0 -0
  10. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/.python-version +0 -0
  11. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/CLAUDE.md +0 -0
  12. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/HYBRID_AUTH.md +0 -0
  13. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/LICENSE +0 -0
  14. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/README.md +0 -0
  15. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/examples/django_react_example/README.md +0 -0
  16. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/examples/django_react_example/TESTING.md +0 -0
  17. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/examples/django_react_example/backend/.env.example +0 -0
  18. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/examples/django_react_example/backend/.gitignore +0 -0
  19. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/examples/django_react_example/backend/api/__init__.py +0 -0
  20. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/examples/django_react_example/backend/api/admin.py +0 -0
  21. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/examples/django_react_example/backend/api/apps.py +0 -0
  22. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/examples/django_react_example/backend/api/migrations/__init__.py +0 -0
  23. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/examples/django_react_example/backend/api/models.py +0 -0
  24. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/examples/django_react_example/backend/api/tests.py +0 -0
  25. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/examples/django_react_example/backend/api/urls.py +0 -0
  26. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/examples/django_react_example/backend/api/views.py +0 -0
  27. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/examples/django_react_example/backend/backend/__init__.py +0 -0
  28. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/examples/django_react_example/backend/backend/asgi.py +0 -0
  29. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/examples/django_react_example/backend/backend/settings.py +0 -0
  30. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/examples/django_react_example/backend/backend/urls.py +0 -0
  31. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/examples/django_react_example/backend/backend/wsgi.py +0 -0
  32. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/examples/django_react_example/backend/manage.py +0 -0
  33. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/examples/django_react_example/e2e/fixtures/test-users.ts +0 -0
  34. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/examples/django_react_example/e2e/global-setup.ts +0 -0
  35. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/examples/django_react_example/e2e/package.json +0 -0
  36. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/examples/django_react_example/e2e/playwright.config.ts +0 -0
  37. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/examples/django_react_example/e2e/scripts/setup-test-users.ts +0 -0
  38. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/examples/django_react_example/e2e/tests/auth.spec.ts +0 -0
  39. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/examples/django_react_example/e2e/tests/protected-api.spec.ts +0 -0
  40. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/examples/django_react_example/e2e/tsconfig.json +0 -0
  41. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/examples/django_react_example/frontend/.env.example +0 -0
  42. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/examples/django_react_example/frontend/.gitignore +0 -0
  43. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/examples/django_react_example/frontend/.nvmrc +0 -0
  44. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/examples/django_react_example/frontend/README.md +0 -0
  45. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/examples/django_react_example/frontend/eslint.config.js +0 -0
  46. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/examples/django_react_example/frontend/index.html +0 -0
  47. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/examples/django_react_example/frontend/package-lock.json +0 -0
  48. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/examples/django_react_example/frontend/package.json +0 -0
  49. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/examples/django_react_example/frontend/public/vite.svg +0 -0
  50. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/examples/django_react_example/frontend/src/App.css +0 -0
  51. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/examples/django_react_example/frontend/src/App.jsx +0 -0
  52. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/examples/django_react_example/frontend/src/assets/react.svg +0 -0
  53. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/examples/django_react_example/frontend/src/index.css +0 -0
  54. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/examples/django_react_example/frontend/src/main.jsx +0 -0
  55. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/examples/django_react_example/frontend/vite.config.js +0 -0
  56. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/rav.yaml +0 -0
  57. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/src/django_clerk_users/__init__.py +0 -0
  58. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/src/django_clerk_users/apps.py +0 -0
  59. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/src/django_clerk_users/authentication/__init__.py +0 -0
  60. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/src/django_clerk_users/authentication/drf.py +0 -0
  61. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/src/django_clerk_users/authentication/utils.py +0 -0
  62. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/src/django_clerk_users/caching.py +0 -0
  63. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/src/django_clerk_users/checks.py +0 -0
  64. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/src/django_clerk_users/client.py +0 -0
  65. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/src/django_clerk_users/decorators.py +0 -0
  66. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/src/django_clerk_users/exceptions.py +0 -0
  67. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/src/django_clerk_users/management/__init__.py +0 -0
  68. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/src/django_clerk_users/management/commands/__init__.py +0 -0
  69. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/src/django_clerk_users/management/commands/migrate_users_to_clerk.py +0 -0
  70. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/src/django_clerk_users/management/commands/sync_clerk_organizations.py +0 -0
  71. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/src/django_clerk_users/management/commands/sync_clerk_users.py +0 -0
  72. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/src/django_clerk_users/managers.py +0 -0
  73. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/src/django_clerk_users/middleware/__init__.py +0 -0
  74. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/src/django_clerk_users/middleware/auth.py +0 -0
  75. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/src/django_clerk_users/migrations/0001_initial.py +0 -0
  76. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/src/django_clerk_users/migrations/0002_make_clerk_id_nullable.py +0 -0
  77. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/src/django_clerk_users/migrations/__init__.py +0 -0
  78. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/src/django_clerk_users/models.py +0 -0
  79. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/src/django_clerk_users/organizations/__init__.py +0 -0
  80. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/src/django_clerk_users/organizations/admin.py +0 -0
  81. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/src/django_clerk_users/organizations/apps.py +0 -0
  82. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/src/django_clerk_users/organizations/middleware.py +0 -0
  83. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/src/django_clerk_users/organizations/migrations/0001_initial.py +0 -0
  84. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/src/django_clerk_users/organizations/migrations/__init__.py +0 -0
  85. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/src/django_clerk_users/organizations/models.py +0 -0
  86. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/src/django_clerk_users/organizations/webhooks.py +0 -0
  87. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/src/django_clerk_users/settings.py +0 -0
  88. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/src/django_clerk_users/testing.py +0 -0
  89. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/src/django_clerk_users/utils.py +0 -0
  90. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/src/django_clerk_users/webhooks/__init__.py +0 -0
  91. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/src/django_clerk_users/webhooks/handlers.py +0 -0
  92. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/src/django_clerk_users/webhooks/security.py +0 -0
  93. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/src/django_clerk_users/webhooks/signals.py +0 -0
  94. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/src/django_clerk_users/webhooks/views.py +0 -0
  95. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/tests/__init__.py +0 -0
  96. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/tests/settings.py +0 -0
  97. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/tests/test_authentication.py +0 -0
  98. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/tests/test_caching.py +0 -0
  99. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/tests/test_decorators.py +0 -0
  100. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/tests/test_drf.py +0 -0
  101. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/tests/test_hybrid_auth.py +0 -0
  102. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/tests/test_import.py +0 -0
  103. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/tests/test_middleware.py +0 -0
  104. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/tests/test_models.py +0 -0
  105. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/tests/test_organizations.py +0 -0
  106. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/tests/test_testing.py +0 -0
  107. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/tests/test_utils.py +0 -0
  108. {django_clerk_users-0.1.0 → django_clerk_users-0.1.1}/tests/test_webhooks.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: django-clerk-users
3
- Version: 0.1.0
3
+ Version: 0.1.1
4
4
  Summary: Integrate Clerk with Django
5
5
  Project-URL: Changelog, https://github.com/jmitchel3/django-clerk-users
6
6
  Project-URL: Documentation, https://github.com/jmitchel3/django-clerk-users
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "django-clerk-users"
7
- version = "0.1.0"
7
+ version = "0.1.1"
8
8
  description = "Integrate Clerk with Django"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.12"
@@ -0,0 +1,83 @@
1
+ """
2
+ Django authentication backend for Clerk.
3
+ """
4
+
5
+ from __future__ import annotations
6
+
7
+ import logging
8
+ from typing import TYPE_CHECKING, Any
9
+
10
+ from django.contrib.auth import get_user_model
11
+ from django.contrib.auth.backends import ModelBackend
12
+
13
+ if TYPE_CHECKING:
14
+ from django.http import HttpRequest
15
+
16
+ from django_clerk_users.models import AbstractClerkUser
17
+
18
+ logger = logging.getLogger(__name__)
19
+
20
+
21
+ class ClerkBackend(ModelBackend):
22
+ """
23
+ Django authentication backend for Clerk.
24
+
25
+ This backend extends Django's ModelBackend to add Clerk ID authentication
26
+ while preserving standard username/password authentication. This allows:
27
+
28
+ - Superusers to log into Django admin with email/password
29
+ - Clerk users to authenticate via JWT tokens (clerk_id)
30
+ - All standard Django permission checks to work as expected
31
+
32
+ To use this backend, add it to AUTHENTICATION_BACKENDS in settings:
33
+
34
+ AUTHENTICATION_BACKENDS = [
35
+ 'django_clerk_users.authentication.ClerkBackend',
36
+ ]
37
+
38
+ This is the only backend you need - it handles both Clerk authentication
39
+ and standard Django authentication (for admin access, etc.).
40
+ """
41
+
42
+ def authenticate(
43
+ self,
44
+ request: "HttpRequest | None" = None,
45
+ username: str | None = None,
46
+ password: str | None = None,
47
+ **kwargs: Any,
48
+ ) -> "AbstractClerkUser | None":
49
+ """
50
+ Authenticate a user by Clerk ID or username/password.
51
+
52
+ If a clerk_id is provided in kwargs, authenticates via Clerk ID lookup.
53
+ Otherwise, falls back to Django's standard username/password
54
+ authentication (inherited from ModelBackend).
55
+
56
+ Args:
57
+ request: The current HTTP request (optional).
58
+ username: The username (email) for standard auth (optional).
59
+ password: The password for standard auth (optional).
60
+ **kwargs: Additional keyword arguments. If 'clerk_id' is present,
61
+ Clerk authentication is used instead of password auth.
62
+
63
+ Returns:
64
+ The authenticated user or None if authentication fails.
65
+ """
66
+ # If clerk_id is provided, authenticate via Clerk
67
+ clerk_id = kwargs.pop("clerk_id", None)
68
+ if clerk_id:
69
+ User = get_user_model()
70
+
71
+ try:
72
+ user = User.objects.get(clerk_id=clerk_id)
73
+ if user.is_active:
74
+ return user
75
+ logger.debug(f"User {clerk_id} is inactive")
76
+ return None
77
+ except User.DoesNotExist:
78
+ logger.debug(f"No user found with clerk_id: {clerk_id}")
79
+ return None
80
+
81
+ # Otherwise, fall back to standard Django authentication
82
+ # This enables superuser login via Django admin
83
+ return super().authenticate(request, username, password, **kwargs)
@@ -289,7 +289,7 @@ wheels = [
289
289
 
290
290
  [[package]]
291
291
  name = "django-clerk-users"
292
- version = "0.0.2"
292
+ version = "0.1.0"
293
293
  source = { editable = "." }
294
294
  dependencies = [
295
295
  { name = "clerk-backend-api" },
@@ -1,89 +0,0 @@
1
- """
2
- Django authentication backend for Clerk.
3
- """
4
-
5
- from __future__ import annotations
6
-
7
- import logging
8
- from typing import TYPE_CHECKING, Any
9
-
10
- from django.contrib.auth import get_user_model
11
- from django.contrib.auth.backends import BaseBackend
12
-
13
- if TYPE_CHECKING:
14
- from django.http import HttpRequest
15
-
16
- from django_clerk_users.models import AbstractClerkUser
17
-
18
- logger = logging.getLogger(__name__)
19
-
20
-
21
- class ClerkBackend(BaseBackend):
22
- """
23
- Django authentication backend for Clerk.
24
-
25
- This backend authenticates users by their Clerk ID rather than
26
- username/password. It's designed to work with Clerk's JWT-based
27
- authentication.
28
-
29
- To use this backend, add it to AUTHENTICATION_BACKENDS in settings:
30
-
31
- AUTHENTICATION_BACKENDS = [
32
- 'django_clerk_users.authentication.ClerkBackend',
33
- ]
34
- """
35
-
36
- def authenticate(
37
- self,
38
- request: "HttpRequest | None" = None,
39
- clerk_id: str | None = None,
40
- **kwargs: Any,
41
- ) -> "AbstractClerkUser | None":
42
- """
43
- Authenticate a user by their Clerk ID.
44
-
45
- Args:
46
- request: The current HTTP request (optional).
47
- clerk_id: The Clerk user ID to authenticate.
48
- **kwargs: Additional keyword arguments (ignored).
49
-
50
- Returns:
51
- The authenticated user or None if authentication fails.
52
- """
53
- if not clerk_id:
54
- return None
55
-
56
- User = get_user_model()
57
-
58
- try:
59
- user = User.objects.get(clerk_id=clerk_id)
60
- if user.is_active:
61
- return user
62
- logger.debug(f"User {clerk_id} is inactive")
63
- return None
64
- except User.DoesNotExist:
65
- logger.debug(f"No user found with clerk_id: {clerk_id}")
66
- return None
67
-
68
- def get_user(self, user_id: int) -> "AbstractClerkUser | None":
69
- """
70
- Get a user by their Django primary key.
71
-
72
- This method is called by Django's authentication middleware
73
- to restore the user from the session.
74
-
75
- Args:
76
- user_id: The user's primary key.
77
-
78
- Returns:
79
- The user instance or None if not found.
80
- """
81
- User = get_user_model()
82
-
83
- try:
84
- user = User.objects.get(pk=user_id)
85
- if user.is_active:
86
- return user
87
- return None
88
- except User.DoesNotExist:
89
- return None