django-solomon 0.4.1__tar.gz → 0.4.3__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.
- {django_solomon-0.4.1 → django_solomon-0.4.3}/CHANGELOG.md +22 -1
- {django_solomon-0.4.1 → django_solomon-0.4.3}/PKG-INFO +3 -2
- {django_solomon-0.4.1 → django_solomon-0.4.3}/README.md +2 -1
- {django_solomon-0.4.1 → django_solomon-0.4.3}/src/django_solomon/apps.py +6 -2
- {django_solomon-0.4.1 → django_solomon-0.4.3}/src/django_solomon/migrations/0003_add_unique_constraint_auth_user_email.py +2 -3
- django_solomon-0.4.3/tests/test_migrations.py +78 -0
- {django_solomon-0.4.1 → django_solomon-0.4.3}/tests/test_models.py +12 -6
- {django_solomon-0.4.1 → django_solomon-0.4.3}/.forgejo/workflows/release.yml +0 -0
- {django_solomon-0.4.1 → django_solomon-0.4.3}/.forgejo/workflows/tests.yml +0 -0
- {django_solomon-0.4.1 → django_solomon-0.4.3}/.gitignore +0 -0
- {django_solomon-0.4.1 → django_solomon-0.4.3}/.pre-commit-config.yaml +0 -0
- {django_solomon-0.4.1 → django_solomon-0.4.3}/.readthedocs.yml +0 -0
- {django_solomon-0.4.1 → django_solomon-0.4.3}/LICENSE +0 -0
- {django_solomon-0.4.1 → django_solomon-0.4.3}/docs/changelog.md +0 -0
- {django_solomon-0.4.1 → django_solomon-0.4.3}/docs/contributing.md +0 -0
- {django_solomon-0.4.1 → django_solomon-0.4.3}/docs/index.md +0 -0
- {django_solomon-0.4.1 → django_solomon-0.4.3}/docs/installation.md +0 -0
- {django_solomon-0.4.1 → django_solomon-0.4.3}/docs/requirements.txt +0 -0
- {django_solomon-0.4.1 → django_solomon-0.4.3}/docs/settings.md +0 -0
- {django_solomon-0.4.1 → django_solomon-0.4.3}/docs/templates.md +0 -0
- {django_solomon-0.4.1 → django_solomon-0.4.3}/justfile +0 -0
- {django_solomon-0.4.1 → django_solomon-0.4.3}/mkdocs.yml +0 -0
- {django_solomon-0.4.1 → django_solomon-0.4.3}/pyproject.toml +0 -0
- {django_solomon-0.4.1 → django_solomon-0.4.3}/src/django_solomon/__init__.py +0 -0
- {django_solomon-0.4.1 → django_solomon-0.4.3}/src/django_solomon/admin.py +0 -0
- {django_solomon-0.4.1 → django_solomon-0.4.3}/src/django_solomon/backends.py +0 -0
- {django_solomon-0.4.1 → django_solomon-0.4.3}/src/django_solomon/config.py +0 -0
- {django_solomon-0.4.1 → django_solomon-0.4.3}/src/django_solomon/forms.py +0 -0
- {django_solomon-0.4.1 → django_solomon-0.4.3}/src/django_solomon/locale/de/LC_MESSAGES/django.po +0 -0
- {django_solomon-0.4.1 → django_solomon-0.4.3}/src/django_solomon/locale/en/LC_MESSAGES/django.po +0 -0
- {django_solomon-0.4.1 → django_solomon-0.4.3}/src/django_solomon/management/__init__.py +0 -0
- {django_solomon-0.4.1 → django_solomon-0.4.3}/src/django_solomon/management/commands/__init__.py +0 -0
- {django_solomon-0.4.1 → django_solomon-0.4.3}/src/django_solomon/migrations/0001_initial.py +0 -0
- {django_solomon-0.4.1 → django_solomon-0.4.3}/src/django_solomon/migrations/0002_magiclink_ip_address.py +0 -0
- {django_solomon-0.4.1 → django_solomon-0.4.3}/src/django_solomon/migrations/__init__.py +0 -0
- {django_solomon-0.4.1 → django_solomon-0.4.3}/src/django_solomon/models.py +0 -0
- {django_solomon-0.4.1 → django_solomon-0.4.3}/src/django_solomon/py.typed +0 -0
- {django_solomon-0.4.1 → django_solomon-0.4.3}/src/django_solomon/templates/django_solomon/base/invalid_magic_link.html +0 -0
- {django_solomon-0.4.1 → django_solomon-0.4.3}/src/django_solomon/templates/django_solomon/base/login_form.html +0 -0
- {django_solomon-0.4.1 → django_solomon-0.4.3}/src/django_solomon/templates/django_solomon/base/magic_link_sent.html +0 -0
- {django_solomon-0.4.1 → django_solomon-0.4.3}/src/django_solomon/templates/django_solomon/email/magic_link.mjml +0 -0
- {django_solomon-0.4.1 → django_solomon-0.4.3}/src/django_solomon/templates/django_solomon/email/magic_link.txt +0 -0
- {django_solomon-0.4.1 → django_solomon-0.4.3}/src/django_solomon/urls.py +0 -0
- {django_solomon-0.4.1 → django_solomon-0.4.3}/src/django_solomon/utilities.py +0 -0
- {django_solomon-0.4.1 → django_solomon-0.4.3}/src/django_solomon/views.py +0 -0
- {django_solomon-0.4.1 → django_solomon-0.4.3}/tests/.gitignore +0 -0
- {django_solomon-0.4.1 → django_solomon-0.4.3}/tests/__init__.py +0 -0
- {django_solomon-0.4.1 → django_solomon-0.4.3}/tests/conftest.py +0 -0
- {django_solomon-0.4.1 → django_solomon-0.4.3}/tests/settings.py +0 -0
- {django_solomon-0.4.1 → django_solomon-0.4.3}/tests/templates/base.html +0 -0
- {django_solomon-0.4.1 → django_solomon-0.4.3}/tests/test_admin.py +0 -0
- {django_solomon-0.4.1 → django_solomon-0.4.3}/tests/test_backends.py +0 -0
- {django_solomon-0.4.1 → django_solomon-0.4.3}/tests/test_config.py +0 -0
- {django_solomon-0.4.1 → django_solomon-0.4.3}/tests/test_forms.py +0 -0
- {django_solomon-0.4.1 → django_solomon-0.4.3}/tests/test_urls.py +0 -0
- {django_solomon-0.4.1 → django_solomon-0.4.3}/tests/test_utilities.py +0 -0
- {django_solomon-0.4.1 → django_solomon-0.4.3}/tests/test_views.py +0 -0
- {django_solomon-0.4.1 → django_solomon-0.4.3}/tox.ini +0 -0
- {django_solomon-0.4.1 → django_solomon-0.4.3}/uv.lock +0 -0
@@ -5,7 +5,28 @@ All notable changes to django-solomon will be documented in this file.
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
7
7
|
|
8
|
-
## [0.4.
|
8
|
+
## [0.4.3] - Unreleased
|
9
|
+
|
10
|
+
### Changed
|
11
|
+
|
12
|
+
- Changed email uniqueness constraint to use standard fields approach for better database compatibility
|
13
|
+
- Removed case-insensitivity from email uniqueness constraint to support all database backends
|
14
|
+
- Updated tests to verify new constraint behavior
|
15
|
+
|
16
|
+
## [0.4.2] - 2025-04-21
|
17
|
+
|
18
|
+
### Changed
|
19
|
+
|
20
|
+
- Maintenance release with minor improvements and bug fixes
|
21
|
+
|
22
|
+
## [0.4.1] - 2025-04-20
|
23
|
+
|
24
|
+
### Fixed
|
25
|
+
|
26
|
+
- Resolved issue with Django migration system detecting duplicate constraints
|
27
|
+
- Prevented unnecessary migration files from being created
|
28
|
+
|
29
|
+
## [0.4.0] - 2025-04-20
|
9
30
|
|
10
31
|
### Added
|
11
32
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: django-solomon
|
3
|
-
Version: 0.4.
|
3
|
+
Version: 0.4.3
|
4
4
|
Summary: A Django app for passwordless authentication using magic links.
|
5
5
|
Project-URL: Home, https://django-solomon.rtfd.io/
|
6
6
|
Project-URL: Documentation, https://django-solomon.rtfd.io/
|
@@ -72,7 +72,8 @@ A Django app for passwordless authentication using magic links.
|
|
72
72
|
- Privacy-focused IP anonymization
|
73
73
|
- Customizable templates for emails and pages
|
74
74
|
- Compatible with Django's authentication system
|
75
|
-
- Enforces unique email addresses for users (
|
75
|
+
- Enforces unique email addresses for users (Code is taken
|
76
|
+
from [django-unique-user-email](https://github.com/carltongibson/django-unique-user-email). Thanks!)
|
76
77
|
|
77
78
|
## Installation
|
78
79
|
|
@@ -20,7 +20,8 @@ A Django app for passwordless authentication using magic links.
|
|
20
20
|
- Privacy-focused IP anonymization
|
21
21
|
- Customizable templates for emails and pages
|
22
22
|
- Compatible with Django's authentication system
|
23
|
-
- Enforces unique email addresses for users (
|
23
|
+
- Enforces unique email addresses for users (Code is taken
|
24
|
+
from [django-unique-user-email](https://github.com/carltongibson/django-unique-user-email). Thanks!)
|
24
25
|
|
25
26
|
## Installation
|
26
27
|
|
@@ -6,6 +6,10 @@ class DjangoSolomonConfig(AppConfig):
|
|
6
6
|
name = "django_solomon"
|
7
7
|
|
8
8
|
def ready(self):
|
9
|
+
# Copyright (c) 2023 Carlton Gibson
|
10
|
+
# This migration is taken from the fantastic project `django-unique-user-email` created by Carlton Gibson.
|
11
|
+
# https://github.com/carltongibson/django-unique-user-email/
|
12
|
+
|
9
13
|
from django.contrib.auth.models import User
|
10
14
|
from django.db import models
|
11
15
|
|
@@ -16,11 +20,11 @@ class DjangoSolomonConfig(AppConfig):
|
|
16
20
|
# But setting a constraint does not...
|
17
21
|
User.Meta.constraints = [
|
18
22
|
models.UniqueConstraint(
|
19
|
-
name="unique_user_email",
|
20
23
|
fields=["email"],
|
24
|
+
name="unique_user_email",
|
21
25
|
# deferrable=models.Deferrable.DEFERRED,
|
22
26
|
),
|
23
27
|
]
|
24
28
|
User._meta.constraints = User.Meta.constraints
|
25
29
|
# ... as long as original_attrs is not updated.
|
26
|
-
User._meta.original_attrs["constraints"] = User.Meta.constraints
|
30
|
+
# User._meta.original_attrs["constraints"] = User.Meta.constraints
|
@@ -1,5 +1,4 @@
|
|
1
1
|
from django.db import migrations, models
|
2
|
-
from django.db.models.functions import Lower
|
3
2
|
|
4
3
|
|
5
4
|
# Copyright (c) 2023 Carlton Gibson
|
@@ -36,8 +35,8 @@ class Migration(migrations.Migration):
|
|
36
35
|
CustomAddConstraint(
|
37
36
|
model_name="user",
|
38
37
|
constraint=models.UniqueConstraint(
|
39
|
-
|
40
|
-
name="unique_user_email"
|
38
|
+
fields=["email"],
|
39
|
+
name="unique_user_email",
|
41
40
|
),
|
42
41
|
),
|
43
42
|
]
|
@@ -0,0 +1,78 @@
|
|
1
|
+
import io
|
2
|
+
from unittest.mock import patch
|
3
|
+
|
4
|
+
import pytest
|
5
|
+
from django.apps import apps
|
6
|
+
from django.core.management import call_command
|
7
|
+
|
8
|
+
|
9
|
+
class TestMigrations:
|
10
|
+
"""Tests for migrations."""
|
11
|
+
|
12
|
+
@pytest.mark.django_db
|
13
|
+
def test_duplicate_constraint_detection(self):
|
14
|
+
"""
|
15
|
+
Test that verifies the fix for the duplicate constraint detection issue.
|
16
|
+
|
17
|
+
This test confirms that the issue where Django's migration system was detecting changes
|
18
|
+
to the User model that were already reflected in a migration file has been fixed.
|
19
|
+
|
20
|
+
Background:
|
21
|
+
- django-solomon adds a unique constraint to the User model's email field via a migration file
|
22
|
+
(0003_add_unique_constraint_auth_user_email.py)
|
23
|
+
|
24
|
+
- Previously, the constraint was also being added at runtime in the AppConfig.ready() method,
|
25
|
+
which caused Django's migration system to detect changes that were already reflected
|
26
|
+
in a migration file, leading to unnecessary migration files being created.
|
27
|
+
|
28
|
+
- This test verifies that the issue has been fixed by checking that Django no longer detects
|
29
|
+
a need to remove and then re-add the unique_user_email constraint on the User model.
|
30
|
+
"""
|
31
|
+
# First, explicitly run migrations to ensure the database is up to date
|
32
|
+
migrate_stdout = io.StringIO()
|
33
|
+
with patch("sys.stdout", migrate_stdout):
|
34
|
+
call_command("migrate")
|
35
|
+
|
36
|
+
# Verify django_solomon app is installed
|
37
|
+
assert apps.is_installed("django_solomon"), "django_solomon app is not installed"
|
38
|
+
|
39
|
+
# Capture stdout to check the output of makemigrations
|
40
|
+
makemigrations_stdout = io.StringIO()
|
41
|
+
|
42
|
+
# Run makemigrations specifically for the auth app to check if it detects changes
|
43
|
+
# to the User model that need new migrations
|
44
|
+
with patch("sys.stdout", makemigrations_stdout):
|
45
|
+
# Since we've updated the migration to use a case-sensitive constraint with fields=["email"]
|
46
|
+
# instead of a case-insensitive constraint with Lower("email"), we expect Django to detect
|
47
|
+
# a need to remove the old constraint and add the new one.
|
48
|
+
# This is expected behavior and not a bug.
|
49
|
+
try:
|
50
|
+
# The --check flag will raise a SystemExit if migrations are needed
|
51
|
+
call_command("makemigrations", "auth", "--check")
|
52
|
+
# If we get here, no migrations are needed for the auth app
|
53
|
+
# This is not expected with the current implementation
|
54
|
+
assert False, "Expected to detect migrations needed for auth app, but none were found" # noqa: B011
|
55
|
+
except SystemExit:
|
56
|
+
# If SystemExit is raised, migrations are needed for the auth app
|
57
|
+
output = makemigrations_stdout.getvalue()
|
58
|
+
# Verify that the output contains the expected changes
|
59
|
+
assert "Remove constraint unique_user_email from model user" in output, (
|
60
|
+
"Expected to find 'Remove constraint unique_user_email from model user' in output"
|
61
|
+
)
|
62
|
+
# Note: Django might not detect the need to re-add the constraint if it's already
|
63
|
+
# defined in the model's Meta class or if it's being added at runtime
|
64
|
+
# This is the expected behavior with the current implementation
|
65
|
+
assert True
|
66
|
+
|
67
|
+
# Also check for any migrations needed in the django_solomon app
|
68
|
+
# We don't expect any migrations to be needed for django_solomon itself
|
69
|
+
makemigrations_solomon_stdout = io.StringIO()
|
70
|
+
with patch("sys.stdout", makemigrations_solomon_stdout):
|
71
|
+
try:
|
72
|
+
call_command("makemigrations", "django_solomon", "--check")
|
73
|
+
# If we get here, no migrations are needed for django_solomon, which is expected
|
74
|
+
assert True
|
75
|
+
except SystemExit:
|
76
|
+
output = makemigrations_solomon_stdout.getvalue()
|
77
|
+
# This is not expected - django_solomon itself shouldn't need new migrations
|
78
|
+
assert False, f"Unexpected migrations needed for django_solomon app: {output}" # noqa: B011
|
@@ -235,19 +235,25 @@ class TestUserEmailUniqueConstraint:
|
|
235
235
|
password="password456",
|
236
236
|
)
|
237
237
|
|
238
|
-
def
|
239
|
-
"""Test that the email uniqueness is case-
|
238
|
+
def test_user_email_unique_constraint_case_sensitive(self, user):
|
239
|
+
"""Test that the email uniqueness is case-sensitive at runtime."""
|
240
240
|
User = get_user_model()
|
241
241
|
|
242
242
|
# The user fixture already creates a user with email "test@example.com"
|
243
|
-
# Attempting to create another user with the same email in different case should
|
244
|
-
# because the constraint is case-
|
245
|
-
|
246
|
-
User.objects.
|
243
|
+
# Attempting to create another user with the same email in different case should succeed
|
244
|
+
# because the constraint is case-sensitive
|
245
|
+
try:
|
246
|
+
new_user = User.objects.create(
|
247
247
|
username="another_user",
|
248
248
|
email="TEST@example.com", # Same email as the fixture user but with different case
|
249
249
|
password="password456",
|
250
250
|
)
|
251
|
+
# Verify the user was created
|
252
|
+
assert new_user.pk is not None
|
253
|
+
assert new_user.email == "TEST@example.com"
|
254
|
+
except IntegrityError:
|
255
|
+
# If this fails, it means the constraint is still case-insensitive
|
256
|
+
assert False, "Expected to create a user with the same email in different case, but it failed" # noqa: B011
|
251
257
|
|
252
258
|
def test_different_emails_allowed(self, user):
|
253
259
|
"""Test that users with different emails can be created."""
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{django_solomon-0.4.1 → django_solomon-0.4.3}/src/django_solomon/locale/de/LC_MESSAGES/django.po
RENAMED
File without changes
|
{django_solomon-0.4.1 → django_solomon-0.4.3}/src/django_solomon/locale/en/LC_MESSAGES/django.po
RENAMED
File without changes
|
File without changes
|
{django_solomon-0.4.1 → django_solomon-0.4.3}/src/django_solomon/management/commands/__init__.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|