diff --git a/bda/tests/test_views.py b/bda/tests/test_views.py index 75d01ec9..47cbd2bd 100644 --- a/bda/tests/test_views.py +++ b/bda/tests/test_views.py @@ -356,7 +356,9 @@ class TestReventeManageTest(TestCase): def test_can_get(self): client = Client() - client.force_login(self.user) + client.force_login( + self.user, backend="django.contrib.auth.backends.ModelBackend" + ) r = client.get(self.url) self.assertEqual(r.status_code, 200) diff --git a/bds/tests/test_views.py b/bds/tests/test_views.py index a40d3d85..ef6139f4 100644 --- a/bds/tests/test_views.py +++ b/bds/tests/test_views.py @@ -27,7 +27,9 @@ class TestHomeView(TestCase): def test_get(self, mock_messages): user = User.objects.create_user(username="random_user") give_bds_buro_permissions(user) - self.client.force_login(user) + self.client.force_login( + user, backend="django.contrib.auth.backends.ModelBackend" + ) resp = self.client.get(reverse("bds:home")) self.assertEquals(resp.status_code, 200) @@ -44,7 +46,7 @@ class TestRegistrationView(TestCase): self.assertRedirects(resp, login_url(next=url)) # Logged-in but unprivileged GET - client.force_login(user) + client.force_login(user, backend="django.contrib.auth.backends.ModelBackend") resp = client.get(url) self.assertEquals(resp.status_code, 403) @@ -64,7 +66,7 @@ class TestRegistrationView(TestCase): self.assertRedirects(resp, login_url(next=url)) # Logged-in but unprivileged GET - client.force_login(user) + client.force_login(user, backend="django.contrib.auth.backends.ModelBackend") resp = client.get(url) self.assertEquals(resp.status_code, 403) diff --git a/events/tests/test_views.py b/events/tests/test_views.py index ef3eda31..611f1871 100644 --- a/events/tests/test_views.py +++ b/events/tests/test_views.py @@ -54,7 +54,9 @@ class CSVExportAccessTest(MessagePatch, TestCase): def test_get(self): client = Client() - client.force_login(self.staff) + client.force_login( + self.staff, backend="django.contrib.auth.backends.ModelBackend" + ) r = client.get(self.url) self.assertEqual(r.status_code, 200) @@ -66,7 +68,7 @@ class CSVExportAccessTest(MessagePatch, TestCase): def test_unauthorised(self): client = Client() - client.force_login(self.u1) + client.force_login(self.u1, backend="django.contrib.auth.backends.ModelBackend") r = client.get(self.url) self.assertEqual(r.status_code, 403) @@ -86,7 +88,9 @@ class CSVExportContentTest(MessagePatch, CSVResponseMixin, TestCase): ) self.staff = make_staff_user("staff") self.client = Client() - self.client.force_login(self.staff) + self.client.force_login( + self.staff, backend="django.contrib.auth.backends.ModelBackend" + ) def test_simple_event(self): self.event.subscribers.set([self.u1, self.u2]) diff --git a/gestioasso/settings/cof_prod.py b/gestioasso/settings/cof_prod.py index 28133ebc..b8b1c0ff 100644 --- a/gestioasso/settings/cof_prod.py +++ b/gestioasso/settings/cof_prod.py @@ -111,11 +111,17 @@ CORS_ORIGIN_WHITELIST = ("bda.ens.fr", "www.bda.ens.fr" "cof.ens.fr", "www.cof.e # Auth-related stuff # --- -AUTHENTICATION_BACKENDS += [ - "gestioncof.shared.COFCASBackend", - "kfet.auth.backends.GenericBackend", -] - +AUTHENTICATION_BACKENDS = ( + [ + # Must be in first + "kfet.auth.backends.BlockFrozenAccountBackend" + ] + + AUTHENTICATION_BACKENDS + + [ + "gestioncof.shared.COFCASBackend", + "kfet.auth.backends.GenericBackend", + ] +) LOGIN_URL = "cof-login" LOGIN_REDIRECT_URL = "home" diff --git a/gestioncof/tests/test_views.py b/gestioncof/tests/test_views.py index dc9b8df0..ecbb20f6 100644 --- a/gestioncof/tests/test_views.py +++ b/gestioncof/tests/test_views.py @@ -641,7 +641,7 @@ class ClubListViewTests(ViewTestCaseMixin, TestCase): def test_as_staff(self): u = self.users["staff"] c = Client() - c.force_login(u) + c.force_login(u, backend="django.contrib.auth.backends.ModelBackend") r = c.get(self.url) @@ -686,7 +686,7 @@ class ClubMembersViewTests(ViewTestCaseMixin, TestCase): self.c.respos.add(u) c = Client() - c.force_login(u) + c.force_login(u, backend="django.contrib.auth.backends.ModelBackend") r = c.get(self.url) self.assertEqual(r.status_code, 200) diff --git a/kfet/auth/backends.py b/kfet/auth/backends.py index 55e18458..0f7789a1 100644 --- a/kfet/auth/backends.py +++ b/kfet/auth/backends.py @@ -1,4 +1,5 @@ from django.contrib.auth import get_user_model +from django.core.exceptions import PermissionDenied from kfet.models import Account, GenericTeamToken @@ -37,3 +38,36 @@ class GenericBackend(BaseKFetBackend): team_token.delete() return get_kfet_generic_user() + + +class BlockFrozenAccountBackend: + def authenticate(self, request, **kwargs): + return None + + def get_user(self, user_id): + return None + + def has_perm(self, user_obj, perm, obj=None): + app_label, _ = perm.split(".") + if app_label == "kfet": + if ( + hasattr(user_obj, "profile") + and hasattr(user_obj.profile, "account_kfet") + and user_obj.profile.account_kfet.is_frozen + ): + raise PermissionDenied + + # Dans le cas général, on se réfère aux autres backends + return False + + def has_module_perms(self, user_obj, app_label): + if app_label == "kfet": + if ( + hasattr(user_obj, "profile") + and hasattr(user_obj.profile, "account_kfet") + and user_obj.profile.account_kfet.is_frozen + ): + raise PermissionDenied + + # Dans le cas général, on se réfère aux autres backends + return False diff --git a/kfet/forms.py b/kfet/forms.py index d728afb1..e0d32102 100644 --- a/kfet/forms.py +++ b/kfet/forms.py @@ -61,7 +61,7 @@ class AccountForm(forms.ModelForm): class Meta: model = Account - fields = ["trigramme", "promo", "nickname", "is_frozen"] + fields = ["trigramme", "promo", "nickname"] widgets = {"trigramme": forms.TextInput(attrs={"autocomplete": "off"})} @@ -119,6 +119,12 @@ class AccountPwdForm(forms.Form): return self.account +class AccountFrozenForm(forms.ModelForm): + class Meta: + model = Account + fields = ["is_frozen"] + + class CofForm(forms.ModelForm): def clean_is_cof(self): instance = getattr(self, "instance", None) diff --git a/kfet/migrations/0076_unfreeze_accounts.py b/kfet/migrations/0076_unfreeze_accounts.py new file mode 100644 index 00000000..23901d99 --- /dev/null +++ b/kfet/migrations/0076_unfreeze_accounts.py @@ -0,0 +1,17 @@ +# Generated by Django 2.2.17 on 2021-02-23 22:51 + +from django.db import migrations + + +def unfreeze_accounts(apps, schema_editor): + Account = apps.get_model("kfet", "Account") + Account.objects.all().update(is_frozen=False) + + +class Migration(migrations.Migration): + + dependencies = [ + ("kfet", "0075_remove_accountnegative_balance_offset"), + ] + + operations = [migrations.RunPython(unfreeze_accounts, migrations.RunPython.noop)] diff --git a/kfet/migrations/0077_delete_frozen_permission.py b/kfet/migrations/0077_delete_frozen_permission.py new file mode 100644 index 00000000..8ac297fa --- /dev/null +++ b/kfet/migrations/0077_delete_frozen_permission.py @@ -0,0 +1,30 @@ +# Generated by Django 2.2.17 on 2021-02-23 23:22 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ("kfet", "0076_unfreeze_accounts"), + ] + + operations = [ + migrations.AlterModelOptions( + name="operation", + options={ + "permissions": ( + ("perform_deposit", "Effectuer une charge"), + ( + "perform_negative_operations", + "Enregistrer des commandes en négatif", + ), + ("cancel_old_operations", "Annuler des commandes non récentes"), + ( + "perform_commented_operations", + "Enregistrer des commandes avec commentaires", + ), + ) + }, + ), + ] diff --git a/kfet/models.py b/kfet/models.py index 7156ae52..628e5de6 100644 --- a/kfet/models.py +++ b/kfet/models.py @@ -180,9 +180,6 @@ class Account(models.Model): return set(), False if self.need_comment: perms.add("kfet.perform_commented_operations") - # Checking is frozen account - if self.is_frozen: - perms.add("kfet.override_frozen_protection") new_balance = self.balance + amount if new_balance < 0 and amount < 0: # Retrieving overdraft amount limit @@ -726,7 +723,6 @@ class Operation(models.Model): permissions = ( ("perform_deposit", "Effectuer une charge"), ("perform_negative_operations", "Enregistrer des commandes en négatif"), - ("override_frozen_protection", "Forcer le gel d'un compte"), ("cancel_old_operations", "Annuler des commandes non récentes"), ( "perform_commented_operations", diff --git a/kfet/open/tests.py b/kfet/open/tests.py index 0d527644..455f2cef 100644 --- a/kfet/open/tests.py +++ b/kfet/open/tests.py @@ -211,7 +211,7 @@ class OpenKfetConsumerTest(ChannelTestCase): ) t.user_permissions.add(is_team) c = WSClient() - c.force_login(t) + c.force_login(t, backend="django.contrib.auth.backends.ModelBackend") # connect c.send_and_consume( @@ -251,7 +251,9 @@ class OpenKfetScenarioTest(ChannelTestCase): self.r_c.login(username="root", password="root") # its client (for websockets) self.r_c_ws = WSClient() - self.r_c_ws.force_login(self.r) + self.r_c_ws.force_login( + self.r, backend="django.contrib.auth.backends.ModelBackend" + ) self.kfet_open = OpenKfet( cache_prefix="test_kfetopen_%s" % random.randrange(2 ** 20) diff --git a/kfet/static/kfet/js/kfet.js b/kfet/static/kfet/js/kfet.js index 1ff3c583..2030304f 100644 --- a/kfet/static/kfet/js/kfet.js +++ b/kfet/static/kfet/js/kfet.js @@ -150,6 +150,12 @@ function getErrorsHtml(data) { content += '