prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Invite: email address should be independent of letter case 
  After testing invites for private projects a lot with AEGEE, I finally found out what their problem was. When they invite users, the auto correct on their Android tablet lets email addresses start with an uppercase letter. The users they wanted to invite had their email address written in lowercase letters though. OPIN did not recognize them as the same users. We should change this behaviour ASAP. It should not matter anywhere whether a user inputs email addresses in lower or uppercase letters.
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `euth/memberships/views.py`
  Content:
  ```
  1 from django.http import Http404
  2 from django.shortcuts import redirect
  3 from django.views import generic
  4 from rules.compat import access_mixins as mixin
  5 
  6 from adhocracy4.projects import models as prj_models
  7 from adhocracy4.projects import views as prj_views
  8 
  9 from . import forms, models
  10 
  11 
  12 class RequestsProjectDetailView(prj_views.ProjectDetailView):
  13 
  14     def handle_no_permission(self):
  15         """
  16         Check if user clould join
  17         """
  18         user = self.request.user
  19         is_member = user.is_authenticated() and self.project.has_member(user)
  20 
  21         if is_member:
  22             return super().handle_no_permission()
  23         else:
  24             return self.handle_no_membership()
  25 
  26     def handle_no_membership(self):
  27         membership_impossible = (
  28             not self.request.user.is_authenticated()
  29             or self.project.is_draft
  30             or self.project.has_member(self.request.user)
  31         )
  32 
  33         if membership_impossible:
  34             return super().handle_no_permission()
  35         else:
  36             return redirect('memberships-request',
  37                             project_slug=self.project.slug)
  38 
  39 
  40 class InviteView(mixin.LoginRequiredMixin, generic.UpdateView):
  41     model = models.Invite
  42     form_class = forms.InviteForm
  43     slug_field = 'token'
  44     slug_url_kwarg = 'invite_token'
  45 
  46     def get_form_kwargs(self):
  47         kwargs = super().get_form_kwargs()
  48         kwargs.update({'user': self.request.user})
  49         return kwargs
  50 
  51     def form_valid(self, form):
  52         if form.is_accepted():
  53             form.instance.accept(self.request.user)
  54             return redirect(form.instance.project.get_absolute_url())
  55         else:
  56             form.instance.reject()
  57             return redirect('/')
  58 
  59 
  60 class RequestView(mixin.LoginRequiredMixin, generic.DetailView):
  61     """
  62     Displays membership request if it exists or allows to create one.
  63     """
  64     model = models.Request
  65     slug_field = 'project__slug'
  66     slug_url_kwarg = 'project_slug'
  67     context_object_name = 'join_request'
  68 
  69     def get_queryset(self):
  70         return self.model.objects.filter(creator=self.request.user)
  71 
  72     def get(self, request, *args, **kwargs):
  73         if self.project.has_member(request.user):
  74             return redirect(self.project.get_absolute_url())
  75         else:
  76             return super().get(request, *args, **kwargs)
  77 
  78     def post(self, request, *args, **kwargs):
  79         user = request.user
  80         project = self.project
  81         models.Request.objects.request_membership(project, user)
  82         return redirect(self.request.path)
  83 
  84     def get_object(self, queryset=None):
  85         try:
  86             return super().get_object(queryset)
  87         except Http404:
  88             return None
  89 
  90     @property
  91     def project(self):
  92         project_slug = self.kwargs[self.slug_url_kwarg]
  93         return prj_models.Project.objects.get(slug=project_slug)
  94
  ```
  
  Path: `euth/memberships/forms.py`
  Content:
  ```
  1 from django import forms
  2 from django.core.exceptions import ValidationError
  3 
  4 from . import models
  5 
  6 
  7 class InviteForm(forms.ModelForm):
  8     accept = forms.CharField(required=False)
  9     reject = forms.CharField(required=False)
  10 
  11     class Meta:
  12         model = models.Invite
  13         fields = ['accept', 'reject']
  14 
  15     def __init__(self, user=None, **kwargs):
  16         super().__init__(**kwargs)
  17         self.user = user
  18 
  19     def clean(self):
  20         data = self.data
  21         if 'accept' not in data and 'reject' not in data:
  22             raise ValidationError('Reject or accept')
  23         if 'accept' in data and not self.user.email == self.instance.email:
  24             raise ValidationError('This user has another email address than '
  25                                   'the one that received the invitation.')
  26         return data
  27 
  28     def is_accepted(self):
  29         data = self.data
  30         return 'accept' in data and 'reject' not in data
  31
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/euth/memberships/forms.py b/euth/memberships/forms.py
  --- a/euth/memberships/forms.py
  +++ b/euth/memberships/forms.py
  @@ -12,17 +12,10 @@
           model = models.Invite
           fields = ['accept', 'reject']
   
  -    def __init__(self, user=None, **kwargs):
  -        super().__init__(**kwargs)
  -        self.user = user
  -
       def clean(self):
           data = self.data
           if 'accept' not in data and 'reject' not in data:
               raise ValidationError('Reject or accept')
  -        if 'accept' in data and not self.user.email == self.instance.email:
  -            raise ValidationError('This user has another email address than '
  -                                  'the one that received the invitation.')
           return data
   
       def is_accepted(self):
  diff --git a/euth/memberships/views.py b/euth/memberships/views.py
  --- a/euth/memberships/views.py
  +++ b/euth/memberships/views.py
  @@ -43,11 +43,6 @@
       slug_field = 'token'
       slug_url_kwarg = 'invite_token'
   
  -    def get_form_kwargs(self):
  -        kwargs = super().get_form_kwargs()
  -        kwargs.update({'user': self.request.user})
  -        return kwargs
  -
       def form_valid(self, form):
           if form.is_accepted():
               form.instance.accept(self.request.user)
  
verification_info: {"golden_diff": "diff --git a/euth/memberships/forms.py b/euth/memberships/forms.py\n--- a/euth/memberships/forms.py\n+++ b/euth/memberships/forms.py\n@@ -12,17 +12,10 @@\n         model = models.Invite\n         fields = ['accept', 'reject']\n \n-    def __init__(self, user=None, **kwargs):\n-        super().__init__(**kwargs)\n-        self.user = user\n-\n     def clean(self):\n         data = self.data\n         if 'accept' not in data and 'reject' not in data:\n             raise ValidationError('Reject or accept')\n-        if 'accept' in data and not self.user.email == self.instance.email:\n-            raise ValidationError('This user has another email address than '\n-                                  'the one that received the invitation.')\n         return data\n \n     def is_accepted(self):\ndiff --git a/euth/memberships/views.py b/euth/memberships/views.py\n--- a/euth/memberships/views.py\n+++ b/euth/memberships/views.py\n@@ -43,11 +43,6 @@\n     slug_field = 'token'\n     slug_url_kwarg = 'invite_token'\n \n-    def get_form_kwargs(self):\n-        kwargs = super().get_form_kwargs()\n-        kwargs.update({'user': self.request.user})\n-        return kwargs\n-\n     def form_valid(self, form):\n         if form.is_accepted():\n             form.instance.accept(self.request.user)\n", "issue": "Invite: email address should be independent of letter case \nAfter testing invites for private projects a lot with AEGEE, I finally found out what their problem was. When they invite users, the auto correct on their Android tablet lets email addresses start with an uppercase letter. The users they wanted to invite had their email address written in lowercase letters though. OPIN did not recognize them as the same users. We should change this behaviour ASAP. It should not matter anywhere whether a user inputs email addresses in lower or uppercase letters.\n", "before_files": [{"content": "from django.http import Http404\nfrom django.shortcuts import redirect\nfrom django.views import generic\nfrom rules.compat import access_mixins as mixin\n\nfrom adhocracy4.projects import models as prj_models\nfrom adhocracy4.projects import views as prj_views\n\nfrom . import forms, models\n\n\nclass RequestsProjectDetailView(prj_views.ProjectDetailView):\n\n    def handle_no_permission(self):\n        \"\"\"\n        Check if user clould join\n        \"\"\"\n        user = self.request.user\n        is_member = user.is_authenticated() and self.project.has_member(user)\n\n        if is_member:\n            return super().handle_no_permission()\n        else:\n            return self.handle_no_membership()\n\n    def handle_no_membership(self):\n        membership_impossible = (\n            not self.request.user.is_authenticated()\n            or self.project.is_draft\n            or self.project.has_member(self.request.user)\n        )\n\n        if membership_impossible:\n            return super().handle_no_permission()\n        else:\n            return redirect('memberships-request',\n                            project_slug=self.project.slug)\n\n\nclass InviteView(mixin.LoginRequiredMixin, generic.UpdateView):\n    model = models.Invite\n    form_class = forms.InviteForm\n    slug_field = 'token'\n    slug_url_kwarg = 'invite_token'\n\n    def get_form_kwargs(self):\n        kwargs = super().get_form_kwargs()\n        kwargs.update({'user': self.request.user})\n        return kwargs\n\n    def form_valid(self, form):\n        if form.is_accepted():\n            form.instance.accept(self.request.user)\n            return redirect(form.instance.project.get_absolute_url())\n        else:\n            form.instance.reject()\n            return redirect('/')\n\n\nclass RequestView(mixin.LoginRequiredMixin, generic.DetailView):\n    \"\"\"\n    Displays membership request if it exists or allows to create one.\n    \"\"\"\n    model = models.Request\n    slug_field = 'project__slug'\n    slug_url_kwarg = 'project_slug'\n    context_object_name = 'join_request'\n\n    def get_queryset(self):\n        return self.model.objects.filter(creator=self.request.user)\n\n    def get(self, request, *args, **kwargs):\n        if self.project.has_member(request.user):\n            return redirect(self.project.get_absolute_url())\n        else:\n            return super().get(request, *args, **kwargs)\n\n    def post(self, request, *args, **kwargs):\n        user = request.user\n        project = self.project\n        models.Request.objects.request_membership(project, user)\n        return redirect(self.request.path)\n\n    def get_object(self, queryset=None):\n        try:\n            return super().get_object(queryset)\n        except Http404:\n            return None\n\n    @property\n    def project(self):\n        project_slug = self.kwargs[self.slug_url_kwarg]\n        return prj_models.Project.objects.get(slug=project_slug)\n", "path": "euth/memberships/views.py"}, {"content": "from django import forms\nfrom django.core.exceptions import ValidationError\n\nfrom . import models\n\n\nclass InviteForm(forms.ModelForm):\n    accept = forms.CharField(required=False)\n    reject = forms.CharField(required=False)\n\n    class Meta:\n        model = models.Invite\n        fields = ['accept', 'reject']\n\n    def __init__(self, user=None, **kwargs):\n        super().__init__(**kwargs)\n        self.user = user\n\n    def clean(self):\n        data = self.data\n        if 'accept' not in data and 'reject' not in data:\n            raise ValidationError('Reject or accept')\n        if 'accept' in data and not self.user.email == self.instance.email:\n            raise ValidationError('This user has another email address than '\n                                  'the one that received the invitation.')\n        return data\n\n    def is_accepted(self):\n        data = self.data\n        return 'accept' in data and 'reject' not in data\n", "path": "euth/memberships/forms.py"}], "after_files": [{"content": "from django.http import Http404\nfrom django.shortcuts import redirect\nfrom django.views import generic\nfrom rules.compat import access_mixins as mixin\n\nfrom adhocracy4.projects import models as prj_models\nfrom adhocracy4.projects import views as prj_views\n\nfrom . import forms, models\n\n\nclass RequestsProjectDetailView(prj_views.ProjectDetailView):\n\n    def handle_no_permission(self):\n        \"\"\"\n        Check if user clould join\n        \"\"\"\n        user = self.request.user\n        is_member = user.is_authenticated() and self.project.has_member(user)\n\n        if is_member:\n            return super().handle_no_permission()\n        else:\n            return self.handle_no_membership()\n\n    def handle_no_membership(self):\n        membership_impossible = (\n            not self.request.user.is_authenticated()\n            or self.project.is_draft\n            or self.project.has_member(self.request.user)\n        )\n\n        if membership_impossible:\n            return super().handle_no_permission()\n        else:\n            return redirect('memberships-request',\n                            project_slug=self.project.slug)\n\n\nclass InviteView(mixin.LoginRequiredMixin, generic.UpdateView):\n    model = models.Invite\n    form_class = forms.InviteForm\n    slug_field = 'token'\n    slug_url_kwarg = 'invite_token'\n\n    def form_valid(self, form):\n        if form.is_accepted():\n            form.instance.accept(self.request.user)\n            return redirect(form.instance.project.get_absolute_url())\n        else:\n            form.instance.reject()\n            return redirect('/')\n\n\nclass RequestView(mixin.LoginRequiredMixin, generic.DetailView):\n    \"\"\"\n    Displays membership request if it exists or allows to create one.\n    \"\"\"\n    model = models.Request\n    slug_field = 'project__slug'\n    slug_url_kwarg = 'project_slug'\n    context_object_name = 'join_request'\n\n    def get_queryset(self):\n        return self.model.objects.filter(creator=self.request.user)\n\n    def get(self, request, *args, **kwargs):\n        if self.project.has_member(request.user):\n            return redirect(self.project.get_absolute_url())\n        else:\n            return super().get(request, *args, **kwargs)\n\n    def post(self, request, *args, **kwargs):\n        user = request.user\n        project = self.project\n        models.Request.objects.request_membership(project, user)\n        return redirect(self.request.path)\n\n    def get_object(self, queryset=None):\n        try:\n            return super().get_object(queryset)\n        except Http404:\n            return None\n\n    @property\n    def project(self):\n        project_slug = self.kwargs[self.slug_url_kwarg]\n        return prj_models.Project.objects.get(slug=project_slug)\n", "path": "euth/memberships/views.py"}, {"content": "from django import forms\nfrom django.core.exceptions import ValidationError\n\nfrom . import models\n\n\nclass InviteForm(forms.ModelForm):\n    accept = forms.CharField(required=False)\n    reject = forms.CharField(required=False)\n\n    class Meta:\n        model = models.Invite\n        fields = ['accept', 'reject']\n\n    def clean(self):\n        data = self.data\n        if 'accept' not in data and 'reject' not in data:\n            raise ValidationError('Reject or accept')\n        return data\n\n    def is_accepted(self):\n        data = self.data\n        return 'accept' in data and 'reject' not in data\n", "path": "euth/memberships/forms.py"}]}