django-clerk-users 0.1.2__py3-none-any.whl → 0.1.4__py3-none-any.whl

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.
@@ -0,0 +1,64 @@
1
+ """
2
+ Django admin configuration for ClerkUser model.
3
+ """
4
+
5
+ from django.contrib import admin
6
+ from django.contrib.auth.admin import UserAdmin
7
+
8
+ from django_clerk_users.models import ClerkUser
9
+
10
+
11
+ @admin.register(ClerkUser)
12
+ class ClerkUserAdmin(UserAdmin):
13
+ list_display = [
14
+ "email",
15
+ "first_name",
16
+ "last_name",
17
+ "clerk_id",
18
+ "is_staff",
19
+ "is_active",
20
+ ]
21
+ list_filter = ["is_staff", "is_active", "created_at"]
22
+ search_fields = ["email", "first_name", "last_name", "clerk_id"]
23
+ ordering = ["-created_at"]
24
+
25
+ fieldsets = (
26
+ (None, {"fields": ("email", "password")}),
27
+ ("Personal info", {"fields": ("first_name", "last_name", "image_url")}),
28
+ ("Clerk", {"fields": ("clerk_id", "uid")}),
29
+ (
30
+ "Permissions",
31
+ {
32
+ "fields": (
33
+ "is_active",
34
+ "is_staff",
35
+ "is_superuser",
36
+ "groups",
37
+ "user_permissions",
38
+ )
39
+ },
40
+ ),
41
+ (
42
+ "Timestamps",
43
+ {"fields": ("created_at", "updated_at", "last_login", "last_logout")},
44
+ ),
45
+ )
46
+
47
+ add_fieldsets = (
48
+ (
49
+ None,
50
+ {
51
+ "classes": ("wide",),
52
+ "fields": ("email", "password1", "password2"),
53
+ },
54
+ ),
55
+ )
56
+
57
+ readonly_fields = [
58
+ "uid",
59
+ "clerk_id",
60
+ "created_at",
61
+ "updated_at",
62
+ "last_login",
63
+ "last_logout",
64
+ ]
@@ -7,9 +7,6 @@ class DjangoClerkUsersConfig(AppConfig):
7
7
  default_auto_field = "django.db.models.BigAutoField"
8
8
 
9
9
  def ready(self):
10
- # Import checks to register them with Django
11
- from django_clerk_users import checks # noqa: F401
12
-
13
10
  # Disconnect Django's update_last_login signal
14
11
  # Clerk manages authentication externally
15
12
  from django.contrib.auth import get_user_model
@@ -13,7 +13,11 @@ from clerk_backend_api.security.types import AuthenticateRequestOptions
13
13
  from django.core.cache import cache
14
14
 
15
15
  from django_clerk_users.client import get_clerk_client
16
- from django_clerk_users.exceptions import ClerkAuthenticationError, ClerkTokenError
16
+ from django_clerk_users.exceptions import (
17
+ ClerkAuthenticationError,
18
+ ClerkConfigurationError,
19
+ ClerkTokenError,
20
+ )
17
21
  from django_clerk_users.settings import CLERK_AUTH_PARTIES, CLERK_CACHE_TIMEOUT
18
22
 
19
23
  if TYPE_CHECKING:
@@ -72,7 +76,11 @@ def get_clerk_payload_from_request(request: "HttpRequest") -> dict[str, Any] | N
72
76
 
73
77
  try:
74
78
  clerk = get_clerk_client()
79
+ except ClerkConfigurationError:
80
+ # Clerk is not configured, skip authentication silently
81
+ return None
75
82
 
83
+ try:
76
84
  # Build auth options with authorized parties
77
85
  auth_options = None
78
86
  if CLERK_AUTH_PARTIES:
@@ -14,6 +14,7 @@ from django.apps import apps
14
14
  from django.core.management.base import BaseCommand, CommandError
15
15
 
16
16
  from django_clerk_users.client import get_clerk_client
17
+ from django_clerk_users.exceptions import ClerkConfigurationError
17
18
 
18
19
 
19
20
  class Command(BaseCommand):
@@ -86,7 +87,13 @@ class Command(BaseCommand):
86
87
  "You must specify --email, --all, or --created-before"
87
88
  )
88
89
 
89
- clerk = get_clerk_client()
90
+ try:
91
+ clerk = get_clerk_client()
92
+ except ClerkConfigurationError:
93
+ raise CommandError(
94
+ "CLERK_SECRET_KEY is not configured. "
95
+ "Set it in your Django settings to use Clerk sync commands."
96
+ )
90
97
 
91
98
  # Build queryset
92
99
  queryset = SourceUser.objects.all()
@@ -2,9 +2,10 @@
2
2
  Management command to sync organizations from Clerk to Django.
3
3
  """
4
4
 
5
- from django.core.management.base import BaseCommand
5
+ from django.core.management.base import BaseCommand, CommandError
6
6
 
7
7
  from django_clerk_users.client import get_clerk_client
8
+ from django_clerk_users.exceptions import ClerkConfigurationError
8
9
 
9
10
 
10
11
  class Command(BaseCommand):
@@ -61,7 +62,13 @@ class Command(BaseCommand):
61
62
  sync_members = options["sync_members"]
62
63
  dry_run = options["dry_run"]
63
64
 
64
- clerk = get_clerk_client()
65
+ try:
66
+ clerk = get_clerk_client()
67
+ except ClerkConfigurationError:
68
+ raise CommandError(
69
+ "CLERK_SECRET_KEY is not configured. "
70
+ "Set it in your Django settings to use Clerk sync commands."
71
+ )
65
72
 
66
73
  created_count = 0
67
74
  updated_count = 0
@@ -2,9 +2,10 @@
2
2
  Management command to sync users from Clerk to Django.
3
3
  """
4
4
 
5
- from django.core.management.base import BaseCommand
5
+ from django.core.management.base import BaseCommand, CommandError
6
6
 
7
7
  from django_clerk_users.client import get_clerk_client
8
+ from django_clerk_users.exceptions import ClerkConfigurationError
8
9
  from django_clerk_users.utils import update_or_create_clerk_user
9
10
 
10
11
 
@@ -41,7 +42,13 @@ class Command(BaseCommand):
41
42
  sync_all = options["all"]
42
43
  dry_run = options["dry_run"]
43
44
 
44
- clerk = get_clerk_client()
45
+ try:
46
+ clerk = get_clerk_client()
47
+ except ClerkConfigurationError:
48
+ raise CommandError(
49
+ "CLERK_SECRET_KEY is not configured. "
50
+ "Set it in your Django settings to use Clerk sync commands."
51
+ )
45
52
 
46
53
  created_count = 0
47
54
  updated_count = 0
@@ -20,7 +20,10 @@ from django_clerk_users.authentication.utils import (
20
20
  get_or_create_user_from_payload,
21
21
  )
22
22
  from django_clerk_users.exceptions import ClerkAuthenticationError, ClerkTokenError
23
- from django_clerk_users.settings import CLERK_SESSION_REVALIDATION_SECONDS
23
+ from django_clerk_users.settings import (
24
+ CLERK_SECRET_KEY,
25
+ CLERK_SESSION_REVALIDATION_SECONDS,
26
+ )
24
27
 
25
28
  if TYPE_CHECKING:
26
29
  from django.http import HttpRequest, HttpResponse
@@ -81,6 +84,10 @@ class ClerkAuthMiddleware:
81
84
  request.clerk_payload = None # type: ignore
82
85
  request.org = None # type: ignore
83
86
 
87
+ # Skip Clerk authentication if not configured
88
+ if not CLERK_SECRET_KEY:
89
+ return
90
+
84
91
  # Check if user is already authenticated via Django's standard auth
85
92
  # (e.g., admin login with username/password)
86
93
  if hasattr(request, "user") and request.user.is_authenticated:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: django-clerk-users
3
- Version: 0.1.2
3
+ Version: 0.1.4
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
@@ -1,7 +1,7 @@
1
1
  django_clerk_users/__init__.py,sha256=Ph93iT6_RNdZej3GM6cez-cJjiXw6w1V-u4GCnGP8TY,2287
2
- django_clerk_users/apps.py,sha256=upj0qWYVg4P2D6_Vt8QZWTfBpAdIP7EAQjVjEnfHLRA,729
2
+ django_clerk_users/admin.py,sha256=2pCE554rGd3m9fisAg55NYWCUHJbm-4bz4A2x_3C-2M,1541
3
+ django_clerk_users/apps.py,sha256=twxTYml_kiGh4bYClV-clNdsnFnW5jqCIbz5bro8qBw,615
3
4
  django_clerk_users/caching.py,sha256=QXRd9cFvvUucrnLBd7_PId3xDodqcessDMybkHyskkU,4651
4
- django_clerk_users/checks.py,sha256=gnHccAyXixtGToGhgWl4gfCY-qPB5ckimpDVadOP3E4,4191
5
5
  django_clerk_users/client.py,sha256=-nBXsPOibVwD7zXQ-Z-qTBb7NyPuUZpvlDcAlDVFUBA,815
6
6
  django_clerk_users/decorators.py,sha256=Hm86XIxNdSiuDmqT8tFRrz6sQR9IOxB7zfxfO8MeJLg,5011
7
7
  django_clerk_users/exceptions.py,sha256=nVTJR1d5PxuMqC8js1Sj-MRHJHkI4KUwphjuCEN4fiM,890
@@ -13,14 +13,14 @@ django_clerk_users/utils.py,sha256=OMB2OCv-SUk6iAbWU6NPo-Psq63dcVJRSDTkAICFNmY,7
13
13
  django_clerk_users/authentication/__init__.py,sha256=PStQVzC-CA2Guyo4ksrxP58o93mfygW4qcJXWEjs6ak,614
14
14
  django_clerk_users/authentication/backends.py,sha256=bDJ2mEO66xhcJPc6f-jYa3F9x-PJ4RJrm9GD-pCTo6Y,2855
15
15
  django_clerk_users/authentication/drf.py,sha256=AqHvZTe9RnxN7FVzlSUXR72QBj2imGglkx9rpOrRDIk,3215
16
- django_clerk_users/authentication/utils.py,sha256=tpnRXQLbQPkosKV8OhxtXpapuema4c08g58YYmMl3js,5326
16
+ django_clerk_users/authentication/utils.py,sha256=5Jdbncsi3xrGt1kWKJ1FzZlbsb0Ou0g7z8ijQXEwqIA,5497
17
17
  django_clerk_users/management/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
18
18
  django_clerk_users/management/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
19
- django_clerk_users/management/commands/migrate_users_to_clerk.py,sha256=qjw4Q6pU7-4Tt7XourTzCw7IBm5kkOau4mPkW2Vz13E,8047
20
- django_clerk_users/management/commands/sync_clerk_organizations.py,sha256=G1kasAPvvwM-PPb5xXxKNlex_-gWyKDP2HLS5g8hVkk,6656
21
- django_clerk_users/management/commands/sync_clerk_users.py,sha256=hvWrvcqAkZHvjqQAOj3-e6pKx5TKtArmlsHDUottRMM,3755
19
+ django_clerk_users/management/commands/migrate_users_to_clerk.py,sha256=soDu2q7z11T6x4G8pqnt8w-MW6gJIwBG_o4XZ9JV7Sg,8348
20
+ django_clerk_users/management/commands/sync_clerk_organizations.py,sha256=uw5zqgUgO9HeF5DTdanTxDXC5syCEJ1WqgDl2xVH6vY,6971
21
+ django_clerk_users/management/commands/sync_clerk_users.py,sha256=MRqxpdUARa3eYWQT8NPdOpDr2BDGc9WulYSBohjvE-s,4070
22
22
  django_clerk_users/middleware/__init__.py,sha256=tnr4eBer0KGVBAZBgBQZVpcL7jf8t2_CBLsMnau5JW4,153
23
- django_clerk_users/middleware/auth.py,sha256=FLo4DHkiL3QnEPZsvJDGFIahfH1HUcqkBEzYXEx0fN0,8889
23
+ django_clerk_users/middleware/auth.py,sha256=3W9168lT1ccyX64kPAcQDL7p03nYBfCttBCcxRJYuc8,9027
24
24
  django_clerk_users/migrations/0001_initial.py,sha256=tnPvGlLnWrItuhYS0s5mr3TJ8__2e_yNKJS4nsFuWhk,6246
25
25
  django_clerk_users/migrations/0002_make_clerk_id_nullable.py,sha256=OXad63KPFTMLn2lkwkuNkr8ZbM6BiNlsw6z72fhY-eU,640
26
26
  django_clerk_users/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -37,7 +37,7 @@ django_clerk_users/webhooks/handlers.py,sha256=GnotJNhN809DsrbfZjtJD0KurThKyAXZS
37
37
  django_clerk_users/webhooks/security.py,sha256=Ig2ZxF8SxX5o-4bNRehFhip4hVvcQxoGsTj3sTY3WSU,3461
38
38
  django_clerk_users/webhooks/signals.py,sha256=bytshg7IMDnlvnCZ0_TGjUXZZLRNxtn2RSx97qacZ-w,1668
39
39
  django_clerk_users/webhooks/views.py,sha256=0-ilzzO7tBfc-pENMy0ZSSkQ4uPqH2QAt249EK2wQKA,2287
40
- django_clerk_users-0.1.2.dist-info/METADATA,sha256=FXGQeLLxETfuOZb53Zn-m4tbXonJDjldPgjx0z6TsRY,8687
41
- django_clerk_users-0.1.2.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
42
- django_clerk_users-0.1.2.dist-info/licenses/LICENSE,sha256=X4PZDRQG4RmPhHU5c0G21Ki9LXWDCuLQ8W4mnED5RDU,1071
43
- django_clerk_users-0.1.2.dist-info/RECORD,,
40
+ django_clerk_users-0.1.4.dist-info/METADATA,sha256=BPHupREOO3vsaBFVJqTMM2uYIHvA4QkhxDYri6jTW58,8687
41
+ django_clerk_users-0.1.4.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
42
+ django_clerk_users-0.1.4.dist-info/licenses/LICENSE,sha256=X4PZDRQG4RmPhHU5c0G21Ki9LXWDCuLQ8W4mnED5RDU,1071
43
+ django_clerk_users-0.1.4.dist-info/RECORD,,
@@ -1,127 +0,0 @@
1
- """
2
- Django system checks for django-clerk-users configuration.
3
- """
4
-
5
- from django.conf import settings
6
- from django.core.checks import Error, Warning, register
7
-
8
-
9
- @register()
10
- def check_clerk_secret_key(app_configs, **kwargs):
11
- """Check that CLERK_SECRET_KEY is configured."""
12
- errors = []
13
- if not getattr(settings, "CLERK_SECRET_KEY", None):
14
- errors.append(
15
- Error(
16
- "CLERK_SECRET_KEY is not configured.",
17
- hint="Set CLERK_SECRET_KEY in your Django settings.",
18
- id="django_clerk_users.E001",
19
- )
20
- )
21
- return errors
22
-
23
-
24
- @register()
25
- def check_clerk_webhook_signing_key(app_configs, **kwargs):
26
- """Check that CLERK_WEBHOOK_SIGNING_KEY is configured."""
27
- warnings = []
28
- if not getattr(settings, "CLERK_WEBHOOK_SIGNING_KEY", None):
29
- warnings.append(
30
- Warning(
31
- "CLERK_WEBHOOK_SIGNING_KEY is not configured.",
32
- hint=(
33
- "Set CLERK_WEBHOOK_SIGNING_KEY in your Django settings "
34
- "if you plan to use Clerk webhooks."
35
- ),
36
- id="django_clerk_users.W001",
37
- )
38
- )
39
- return warnings
40
-
41
-
42
- @register()
43
- def check_auth_user_model(app_configs, **kwargs):
44
- """Check that AUTH_USER_MODEL is configured for Clerk."""
45
- warnings = []
46
- auth_user_model = getattr(settings, "AUTH_USER_MODEL", "auth.User")
47
-
48
- # Check if using a Clerk-compatible user model
49
- if not (
50
- auth_user_model.startswith("django_clerk_users.")
51
- or "clerk" in auth_user_model.lower()
52
- ):
53
- warnings.append(
54
- Warning(
55
- f"AUTH_USER_MODEL is set to '{auth_user_model}'.",
56
- hint=(
57
- "Consider using 'django_clerk_users.ClerkUser' or a custom model "
58
- "that extends AbstractClerkUser for full Clerk integration."
59
- ),
60
- id="django_clerk_users.W002",
61
- )
62
- )
63
- return warnings
64
-
65
-
66
- @register()
67
- def check_middleware_installed(app_configs, **kwargs):
68
- """Check that ClerkAuthMiddleware is installed."""
69
- warnings = []
70
- middleware = getattr(settings, "MIDDLEWARE", [])
71
-
72
- clerk_middleware = "django_clerk_users.middleware.ClerkAuthMiddleware"
73
- if clerk_middleware not in middleware:
74
- warnings.append(
75
- Warning(
76
- "ClerkAuthMiddleware is not in MIDDLEWARE.",
77
- hint=(
78
- f"Add '{clerk_middleware}' to MIDDLEWARE in your Django settings "
79
- "for automatic Clerk authentication."
80
- ),
81
- id="django_clerk_users.W003",
82
- )
83
- )
84
- return warnings
85
-
86
-
87
- @register()
88
- def check_authentication_backend(app_configs, **kwargs):
89
- """Check that ClerkBackend is in AUTHENTICATION_BACKENDS."""
90
- warnings = []
91
- backends = getattr(settings, "AUTHENTICATION_BACKENDS", [])
92
-
93
- clerk_backend = "django_clerk_users.authentication.ClerkBackend"
94
- if clerk_backend not in backends:
95
- warnings.append(
96
- Warning(
97
- "ClerkBackend is not in AUTHENTICATION_BACKENDS.",
98
- hint=(
99
- f"Add '{clerk_backend}' to AUTHENTICATION_BACKENDS in your "
100
- "Django settings."
101
- ),
102
- id="django_clerk_users.W004",
103
- )
104
- )
105
- return warnings
106
-
107
-
108
- @register()
109
- def check_frontend_hosts(app_configs, **kwargs):
110
- """Check that CLERK_FRONTEND_HOSTS is configured."""
111
- warnings = []
112
- frontend_hosts = getattr(settings, "CLERK_FRONTEND_HOSTS", [])
113
- auth_parties = getattr(settings, "CLERK_AUTH_PARTIES", [])
114
-
115
- if not frontend_hosts and not auth_parties:
116
- warnings.append(
117
- Warning(
118
- "CLERK_FRONTEND_HOSTS is not configured.",
119
- hint=(
120
- "Set CLERK_FRONTEND_HOSTS in your Django settings to the list of "
121
- "frontend URLs that will be sending authenticated requests "
122
- "(e.g., ['https://myapp.com', 'http://localhost:3000'])."
123
- ),
124
- id="django_clerk_users.W005",
125
- )
126
- )
127
- return warnings