diff --git a/rowers/backends.py b/rowers/backends.py index 55ae2ca1..a9cf55b2 100644 --- a/rowers/backends.py +++ b/rowers/backends.py @@ -1,6 +1,10 @@ from rules.permissions import ObjectPermissionBackend from rowers.models import User +from django.contrib.auth import get_user_model # gets the user_model django default or your own custom +from django.contrib.auth.backends import ModelBackend +from django.db.models import Q + class MyObjectPermissionBackend(ObjectPermissionBackend): def user_can_authenticate(self, user): return getattr(user, "is_active", True) @@ -11,4 +15,31 @@ class MyObjectPermissionBackend(ObjectPermissionBackend): except User.DoesNotExist: return None return user if self.user_can_authenticate(user) else None + +class EmailLoginBackend(ModelBackend): + def user_can_authenticate(self, user): + return getattr(user, "is_active", True) + + def authenticate(self, request, username=None, password=None, **kwargs): + try: + user = User.objects.filter( + Q(username__iexact=username) | + Q(email__iexact=username) + ).distinct() + except User.DoesNotExist: + return None + + if user.exists(): + user_obj = user.first() + if user_obj.check_password(password) and user_obj.is_active: + return user_obj + return None + else: + return None + + def get_user(self, user_id): + try: + return User.objects.get(pk=user_id) + except User.DoesNotExist: + return None diff --git a/rowers/forms.py b/rowers/forms.py index 311f1fa5..641afe89 100644 --- a/rowers/forms.py +++ b/rowers/forms.py @@ -1233,12 +1233,12 @@ class ExportChoices(forms.Form): class AssignChoices(forms.Form): remove_workout = forms.BooleanField(initial=False, required=False) - destination = forms.ModelMultipleChoiceField(label='Rowers', required=False, + rowers = forms.ModelMultipleChoiceField(label='Rowers', required=False, queryset=Rower.objects.filter(), widget=forms.CheckboxSelectMultiple()) def __init__(self, *args, **kwargs): super(AssignChoices, self).__init__(*args, **kwargs) - self.fields['destination'].queryset = Rower.objects.filter() + self.fields['rowers'].queryset = Rower.objects.filter() class WorkoutMultipleCompareForm(forms.Form): workouts = forms.ModelMultipleChoiceField( diff --git a/rowers/templates/workout_bulk_actions.html b/rowers/templates/workout_bulk_actions.html index 0c50413c..3d24853a 100644 --- a/rowers/templates/workout_bulk_actions.html +++ b/rowers/templates/workout_bulk_actions.html @@ -5,6 +5,7 @@ {% block title %}Change Workout {% endblock %} {% block main %} +

Bulk Actions

  • @@ -12,22 +13,18 @@

    Edit and confirm the action you want to perform on the following workouts:

    -

    +

    {{ form.as_p }} -

    -

    +

    +
    {{ actionform.as_p }} -

    - {% if action == 'export' %} -

    +

    +
    {{ exportchoice.as_p }} -

    - {% endif %} - {% if action == 'rower assign' %} -

    +

    +
    {{ assignchoices.as_p }} -

    - {% endif %} +
  • {% csrf_token %} @@ -35,7 +32,53 @@
+ + {% endblock %} diff --git a/rowers/tests/testdata/testdata.tcx.gz b/rowers/tests/testdata/testdata.tcx.gz index 6833bcc6..eccecade 100644 Binary files a/rowers/tests/testdata/testdata.tcx.gz and b/rowers/tests/testdata/testdata.tcx.gz differ diff --git a/rowers/views/workoutviews.py b/rowers/views/workoutviews.py index ced60404..9b3d92fe 100644 --- a/rowers/views/workoutviews.py +++ b/rowers/views/workoutviews.py @@ -2035,8 +2035,9 @@ def workouts_bulk_actions(request): assignchoices = AssignChoices(request.POST) if assignchoices.is_valid(): remove_workout = assignchoices.cleaned_data['remove_workout'] - rowers = assignchoices.cleaned_data['destination'] + rowers = assignchoices.cleaned_data['rowers'] _ = myqueue(queuehigh, handle_assignworkouts, workouts, rowers, remove_workout) + messages.info(request, "Your action will be performed in the background. It may take a few minutes to complete") url = reverse('workouts_view') return HttpResponseRedirect(url) else: # pragma: no cover @@ -2049,10 +2050,10 @@ def workouts_bulk_actions(request): actionform.fields["action"].initial = action assignchoices = AssignChoices() teams = Team.objects.filter(manager=request.user) - assignchoices.fields["destination"].queryset = Rower.objects.filter( + assignchoices.fields["rowers"].queryset = Rower.objects.filter( team__in=teams ).distinct().order_by("user__last_name", "user__first_name").exclude(rowerplan='freecoach') - assignchoices.fields["destination"].initial = [] + assignchoices.fields["rowers"].initial = [] form = WorkoutMultipleCompareForm() form.fields["workouts"].queryset = Workout.objects.filter(id__in=[w.id for w in workouts]) form.fields["workouts"].initial = workouts diff --git a/rowsandall_app/settings.py b/rowsandall_app/settings.py index facdb512..63ae2609 100644 --- a/rowsandall_app/settings.py +++ b/rowsandall_app/settings.py @@ -90,6 +90,7 @@ INSTALLED_APPS = [ AUTHENTICATION_BACKENDS = ( #'oauth2_provider.backends.OAuth2Backend', # Uncomment following if you want to access the admin + 'rowers.backends.EmailLoginBackend', 'django.contrib.auth.backends.ModelBackend', 'django.contrib.auth.backends.RemoteUserBackend', 'rowers.backends.MyObjectPermissionBackend',