We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Users should only be shown the View-Edit toggle if they have edit access for the source/chant in question
@annamorphism made a comment on #441 that really deserves its own issue

> also is there a way to not have the "Edit" tab show up for unauthorized people? it's annoying to try to edit something and then be sent to a 403.

Currently, the view-edit toggle is being displayed whenever the user is logged in. Instead, we need to properly check that the user is actually allowed to edit the chant before displaying the Edit link.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `django/cantusdb_project/main_app/views/sequence.py`
Content:
```
1 from django.views.generic import DetailView, ListView, UpdateView
2 from main_app.models import Sequence
3 from django.db.models import Q
4 from main_app.forms import SequenceEditForm
5 from django.contrib.auth.mixins import LoginRequiredMixin
6 from django.contrib import messages
7 from django.contrib.auth.mixins import UserPassesTestMixin
8 from django.core.exceptions import PermissionDenied
9 
10 
11 class SequenceDetailView(DetailView):
12     """
13     Displays a single Sequence object. Accessed with ``sequences/<int:pk>``
14     """
15 
16     model = Sequence
17     context_object_name = "sequence"
18     template_name = "sequence_detail.html"
19 
20     def get_context_data(self, **kwargs):
21         sequence = self.get_object()
22         source = sequence.source
23         # if the sequence's source isn't published,
24         # only logged-in users should be able to view the sequence's detail page
25         if (
26             (source is not None)
27             and (source.published is False)
28             and (not self.request.user.is_authenticated)
29         ):
30             raise PermissionDenied()
31 
32         context = super().get_context_data(**kwargs)
33         context["concordances"] = (
34             Sequence.objects.filter(cantus_id=sequence.cantus_id)
35             .select_related("source")
36             .order_by("siglum")
37         )
38         return context
39 
40 
41 class SequenceListView(ListView):
42     """
43     Displays a list of Sequence objects. Accessed with ``sequences/``
44     """
45 
46     paginate_by = 100
47     context_object_name = "sequences"
48     template_name = "sequence_list.html"
49 
50     def get_queryset(self):
51         queryset = Sequence.objects.select_related("source")
52         display_unpublished = self.request.user.is_authenticated
53         if display_unpublished:
54             q_obj_filter = Q()
55         else:
56             q_obj_filter = Q(source__published=True)
57 
58         if self.request.GET.get("incipit"):
59             incipit = self.request.GET.get("incipit")
60             q_obj_filter &= Q(incipit__icontains=incipit)
61         if self.request.GET.get("siglum"):
62             siglum = self.request.GET.get("siglum")
63             q_obj_filter &= Q(siglum__icontains=siglum)
64         if self.request.GET.get("cantus_id"):
65             cantus_id = self.request.GET.get("cantus_id")
66             q_obj_filter &= Q(cantus_id__icontains=cantus_id)
67 
68         return queryset.filter(q_obj_filter).order_by("siglum", "s_sequence")
69 
70 
71 class SequenceEditView(LoginRequiredMixin, UserPassesTestMixin, UpdateView):
72     template_name = "sequence_edit.html"
73     model = Sequence
74     form_class = SequenceEditForm
75     pk_url_kwarg = "sequence_id"
76 
77     def form_valid(self, form):
78         form.instance.last_updated_by = self.request.user
79         messages.success(
80             self.request,
81             "Sequence updated successfully!",
82         )
83         return super().form_valid(form)
84 
85     def test_func(self):
86         user = self.request.user
87         # checks if the user is a project manager (they should have the privilege to edit any sequence)
88         is_project_manager = user.groups.filter(name="project manager").exists()
89 
90         if is_project_manager:
91             return True
92         else:
93             return False
94
```
--- 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()

```

diff --git a/django/cantusdb_project/main_app/views/sequence.py b/django/cantusdb_project/main_app/views/sequence.py
--- a/django/cantusdb_project/main_app/views/sequence.py
+++ b/django/cantusdb_project/main_app/views/sequence.py
@@ -6,6 +6,7 @@
 from django.contrib import messages
 from django.contrib.auth.mixins import UserPassesTestMixin
 from django.core.exceptions import PermissionDenied
+from main_app.views.chant import user_can_edit_chants_in_source
 
 
 class SequenceDetailView(DetailView):
@@ -20,6 +21,8 @@
     def get_context_data(self, **kwargs):
         sequence = self.get_object()
         source = sequence.source
+        user = self.request.user
+
         # if the sequence's source isn't published,
         # only logged-in users should be able to view the sequence's detail page
         if (
@@ -35,6 +38,7 @@
             .select_related("source")
             .order_by("siglum")
         )
+        context["user_can_edit_sequence"] = user_can_edit_chants_in_source(user, source)
         return context

{"golden_diff": "diff --git a/django/cantusdb_project/main_app/views/sequence.py b/django/cantusdb_project/main_app/views/sequence.py\n--- a/django/cantusdb_project/main_app/views/sequence.py\n+++ b/django/cantusdb_project/main_app/views/sequence.py\n@@ -6,6 +6,7 @@\n from django.contrib import messages\n from django.contrib.auth.mixins import UserPassesTestMixin\n from django.core.exceptions import PermissionDenied\n+from main_app.views.chant import user_can_edit_chants_in_source\n \n \n class SequenceDetailView(DetailView):\n@@ -20,6 +21,8 @@\n     def get_context_data(self, **kwargs):\n         sequence = self.get_object()\n         source = sequence.source\n+        user = self.request.user\n+\n         # if the sequence's source isn't published,\n         # only logged-in users should be able to view the sequence's detail page\n         if (\n@@ -35,6 +38,7 @@\n             .select_related(\"source\")\n             .order_by(\"siglum\")\n         )\n+        context[\"user_can_edit_sequence\"] = user_can_edit_chants_in_source(user, source)\n         return context\n", "issue": "Users should only be shown the View-Edit toggle if they have edit access for the source/chant in question\n@annamorphism made a comment on #441 that really deserves its own issue\r\n\r\n> also is there a way to not have the \"Edit\" tab show up for unauthorized people? it's annoying to try to edit something and then be sent to a 403.\r\n\r\nCurrently, the view-edit toggle is being displayed whenever the user is logged in. Instead, we need to properly check that the user is actually allowed to edit the chant before displaying the Edit link.\n", "before_files": [{"content": "from django.views.generic import DetailView, ListView, UpdateView\nfrom main_app.models import Sequence\nfrom django.db.models import Q\nfrom main_app.forms import SequenceEditForm\nfrom django.contrib.auth.mixins import LoginRequiredMixin\nfrom django.contrib import messages\nfrom django.contrib.auth.mixins import UserPassesTestMixin\nfrom django.core.exceptions import PermissionDenied\n\n\nclass SequenceDetailView(DetailView):\n    \"\"\"\n    Displays a single Sequence object. Accessed with ``sequences/<int:pk>``\n    \"\"\"\n\n    model = Sequence\n    context_object_name = \"sequence\"\n    template_name = \"sequence_detail.html\"\n\n    def get_context_data(self, **kwargs):\n        sequence = self.get_object()\n        source = sequence.source\n        # if the sequence's source isn't published,\n        # only logged-in users should be able to view the sequence's detail page\n        if (\n            (source is not None)\n            and (source.published is False)\n            and (not self.request.user.is_authenticated)\n        ):\n            raise PermissionDenied()\n\n        context = super().get_context_data(**kwargs)\n        context[\"concordances\"] = (\n            Sequence.objects.filter(cantus_id=sequence.cantus_id)\n            .select_related(\"source\")\n            .order_by(\"siglum\")\n        )\n        return context\n\n\nclass SequenceListView(ListView):\n    \"\"\"\n    Displays a list of Sequence objects. Accessed with ``sequences/``\n    \"\"\"\n\n    paginate_by = 100\n    context_object_name = \"sequences\"\n    template_name = \"sequence_list.html\"\n\n    def get_queryset(self):\n        queryset = Sequence.objects.select_related(\"source\")\n        display_unpublished = self.request.user.is_authenticated\n        if display_unpublished:\n            q_obj_filter = Q()\n        else:\n            q_obj_filter = Q(source__published=True)\n\n        if self.request.GET.get(\"incipit\"):\n            incipit = self.request.GET.get(\"incipit\")\n            q_obj_filter &= Q(incipit__icontains=incipit)\n        if self.request.GET.get(\"siglum\"):\n            siglum = self.request.GET.get(\"siglum\")\n            q_obj_filter &= Q(siglum__icontains=siglum)\n        if self.request.GET.get(\"cantus_id\"):\n            cantus_id = self.request.GET.get(\"cantus_id\")\n            q_obj_filter &= Q(cantus_id__icontains=cantus_id)\n\n        return queryset.filter(q_obj_filter).order_by(\"siglum\", \"s_sequence\")\n\n\nclass SequenceEditView(LoginRequiredMixin, UserPassesTestMixin, UpdateView):\n    template_name = \"sequence_edit.html\"\n    model = Sequence\n    form_class = SequenceEditForm\n    pk_url_kwarg = \"sequence_id\"\n\n    def form_valid(self, form):\n        form.instance.last_updated_by = self.request.user\n        messages.success(\n            self.request,\n            \"Sequence updated successfully!\",\n        )\n        return super().form_valid(form)\n\n    def test_func(self):\n        user = self.request.user\n        # checks if the user is a project manager (they should have the privilege to edit any sequence)\n        is_project_manager = user.groups.filter(name=\"project manager\").exists()\n\n        if is_project_manager:\n            return True\n        else:\n            return False\n", "path": "django/cantusdb_project/main_app/views/sequence.py"}], "after_files": [{"content": "from django.views.generic import DetailView, ListView, UpdateView\nfrom main_app.models import Sequence\nfrom django.db.models import Q\nfrom main_app.forms import SequenceEditForm\nfrom django.contrib.auth.mixins import LoginRequiredMixin\nfrom django.contrib import messages\nfrom django.contrib.auth.mixins import UserPassesTestMixin\nfrom django.core.exceptions import PermissionDenied\nfrom main_app.views.chant import user_can_edit_chants_in_source\n\n\nclass SequenceDetailView(DetailView):\n    \"\"\"\n    Displays a single Sequence object. Accessed with ``sequences/<int:pk>``\n    \"\"\"\n\n    model = Sequence\n    context_object_name = \"sequence\"\n    template_name = \"sequence_detail.html\"\n\n    def get_context_data(self, **kwargs):\n        sequence = self.get_object()\n        source = sequence.source\n        user = self.request.user\n\n        # if the sequence's source isn't published,\n        # only logged-in users should be able to view the sequence's detail page\n        if (\n            (source is not None)\n            and (source.published is False)\n            and (not self.request.user.is_authenticated)\n        ):\n            raise PermissionDenied()\n\n        context = super().get_context_data(**kwargs)\n        context[\"concordances\"] = (\n            Sequence.objects.filter(cantus_id=sequence.cantus_id)\n            .select_related(\"source\")\n            .order_by(\"siglum\")\n        )\n        context[\"user_can_edit_sequence\"] = user_can_edit_chants_in_source(user, source)\n        return context\n\n\nclass SequenceListView(ListView):\n    \"\"\"\n    Displays a list of Sequence objects. Accessed with ``sequences/``\n    \"\"\"\n\n    paginate_by = 100\n    context_object_name = \"sequences\"\n    template_name = \"sequence_list.html\"\n\n    def get_queryset(self):\n        queryset = Sequence.objects.select_related(\"source\")\n        display_unpublished = self.request.user.is_authenticated\n        if display_unpublished:\n            q_obj_filter = Q()\n        else:\n            q_obj_filter = Q(source__published=True)\n\n        if self.request.GET.get(\"incipit\"):\n            incipit = self.request.GET.get(\"incipit\")\n            q_obj_filter &= Q(incipit__icontains=incipit)\n        if self.request.GET.get(\"siglum\"):\n            siglum = self.request.GET.get(\"siglum\")\n            q_obj_filter &= Q(siglum__icontains=siglum)\n        if self.request.GET.get(\"cantus_id\"):\n            cantus_id = self.request.GET.get(\"cantus_id\")\n            q_obj_filter &= Q(cantus_id__icontains=cantus_id)\n\n        return queryset.filter(q_obj_filter).order_by(\"siglum\", \"s_sequence\")\n\n\nclass SequenceEditView(LoginRequiredMixin, UserPassesTestMixin, UpdateView):\n    template_name = \"sequence_edit.html\"\n    model = Sequence\n    form_class = SequenceEditForm\n    pk_url_kwarg = \"sequence_id\"\n\n    def form_valid(self, form):\n        form.instance.last_updated_by = self.request.user\n        messages.success(\n            self.request,\n            \"Sequence updated successfully!\",\n        )\n        return super().form_valid(form)\n\n    def test_func(self):\n        user = self.request.user\n        # checks if the user is a project manager (they should have the privilege to edit any sequence)\n        is_project_manager = user.groups.filter(name=\"project manager\").exists()\n\n        if is_project_manager:\n            return True\n        else:\n            return False\n", "path": "django/cantusdb_project/main_app/views/sequence.py"}]}