diff --git a/README.md b/README.md index 469a4e17b681f4021609071f459bd6e7261527a7..5116df20b6e49d57f343adea6865f2ab56b6fb70 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,8 @@ Django app na uživatele, týmy a skupiny, s napojením na LDAP a SSO. [](https://github.com/psf/black) [](LICENSE) + + ## Použití @@ -73,3 +75,13 @@ OIDC_OP_USER_ENDPOINT = join(OIDC_RP_REALM_URL, "protocol/openid-connect/userinf ``` URL patterns pro OpenID Connect už jsou součástí `pirates.urls` (viz výše). + +#### Signál po přihlášení + +Po přihlášení uživatele je poslán signál `pirates.signals.post_login` s +parametry: + +* `sender` - `PiratesOIDCAuthenticationBackend` +* `user` - přihlášený uživatel (instance `AUTH_USER_MODEL`) +* `created` - `True`/`False` zda-li byl vytvořen nový uživatel +* `request` - instance `HttpRequest` diff --git a/pirates/auth.py b/pirates/auth.py index e45133e9460ed43e1b44cb3826d86e9451180304..eade39779156c662641a3ac056e1216b99cb60aa 100644 --- a/pirates/auth.py +++ b/pirates/auth.py @@ -1,5 +1,7 @@ from mozilla_django_oidc.auth import OIDCAuthenticationBackend +from .signals import post_login + class PiratesOIDCAuthenticationBackend(OIDCAuthenticationBackend): """ @@ -23,13 +25,25 @@ class PiratesOIDCAuthenticationBackend(OIDCAuthenticationBackend): first_name = claims.get("given_name", "") last_name = claims.get("family_name", "") email = claims.get("email", "") - return self.UserModel.objects.create( + user = self.UserModel.objects.create( sso_id=sso_id, first_name=first_name, last_name=last_name, email=email ) + self.send_post_login_signal(user, True, claims) + return user def update_user(self, user, claims): user.first_name = claims.get("given_name", "") user.last_name = claims.get("family_name", "") user.email = claims.get("email", "") user.save() + self.send_post_login_signal(user, False, claims) return user + + def send_post_login_signal(self, user, created, claims): + post_login.send( + sender=self.__class__, + user=user, + created=created, + claims=claims, + request=self.request, + ) diff --git a/pirates/signals.py b/pirates/signals.py new file mode 100644 index 0000000000000000000000000000000000000000..d14a1302bc0db50463e193388a1041ac13f2d1d9 --- /dev/null +++ b/pirates/signals.py @@ -0,0 +1,3 @@ +from django.dispatch import Signal + +post_login = Signal() diff --git a/setup.py b/setup.py index 345874a165722da9521abcafd61e9f09f1e13b74..3e71bf91fcee079b59329d509451d9c372cf9a1f 100755 --- a/setup.py +++ b/setup.py @@ -13,7 +13,7 @@ def read(fname): setup( name="pirates", - version="0.3.1", + version="0.4.0", license="MIT", description="Django app for users, teamds and groups.", long_description=read("README.md"), @@ -34,7 +34,12 @@ setup( "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", "Programming Language :: Python :: Implementation :: CPython", + "Framework :: Django", + "Framework :: Django :: 2.2", + "Framework :: Django :: 3.0", + "Framework :: Django :: 3.1", "Topic :: Utilities", ], project_urls={ @@ -44,5 +49,5 @@ setup( }, keywords=["django", "openid", "sso"], python_requires=">=3.6", - install_requires=["mozilla-django-oidc>=1.2.3,<2", "python-ldap>=3.2.0,<4"], + install_requires=["mozilla-django-oidc>=1.2.4,<2", "python-ldap>=3.2.0,<4"], ) diff --git a/tests/requirements.txt b/tests/requirements.txt index e2f939e9e9cadcc1d972bda9c53d66ae966033b7..8bb1a4ea82b42a97a73f3c148274b900a259a885 100644 --- a/tests/requirements.txt +++ b/tests/requirements.txt @@ -2,3 +2,4 @@ pytest pytest-cov pytest-factoryboy pytest-django +pytest-mock diff --git a/tests/test_auth.py b/tests/test_auth.py index b9f69522fad862d9013822aa8e6de53af5775beb..98cf4c5b9ffc764282c781836a177497d810f414 100644 --- a/tests/test_auth.py +++ b/tests/test_auth.py @@ -10,8 +10,10 @@ fake = Faker() @pytest.fixture -def backend(): - return PiratesOIDCAuthenticationBackend() +def backend(mocker): + instance = PiratesOIDCAuthenticationBackend() + instance.request = mocker.Mock() + return instance def test_auth_backend__get_sso_id(backend): @@ -69,3 +71,39 @@ def test_auth_backend__update_user(backend, user): assert updated_user.last_name == claims["family_name"] assert updated_user.email == claims["email"] assert get_user_model().objects.get() == updated_user + + +def test_auth_backend__create_user__send_post_login(backend, mocker): + m_post_login = mocker.patch("pirates.auth.post_login") + claims = { + "sub": fake.random_letters(), + "given_name": fake.first_name(), + "family_name": fake.last_name(), + "email": fake.email(), + } + user = backend.create_user(claims) + m_post_login.send.assert_called_once_with( + sender=backend.__class__, + user=user, + created=True, + claims=claims, + request=backend.request, + ) + + +def test_auth_backend__update_user__send_post_login(backend, user, mocker): + m_post_login = mocker.patch("pirates.auth.post_login") + claims = { + "sub": fake.random_letters(), + "given_name": fake.first_name(), + "family_name": fake.last_name(), + "email": fake.email(), + } + updated_user = backend.update_user(user, claims) + m_post_login.send.assert_called_once_with( + sender=backend.__class__, + user=updated_user, + created=False, + claims=claims, + request=backend.request, + ) diff --git a/tox.ini b/tox.ini index bc14a56a63952c6197ce225dcdc85f524d22f9d1..a7bafd63549972248ccb9c94bd0f9da068440203 100644 --- a/tox.ini +++ b/tox.ini @@ -1,10 +1,11 @@ [tox] envlist = - py{36,37,38}-django{30,22} + py{36,37,38,39}-django{31,30,22} [testenv] deps = -r{toxinidir}/tests/requirements.txt + django31: Django>=3.1,<3.2 django30: Django>=3.0,<3.1 django22: Django>=2.2,<3 setenv =