diff --git a/aleksis/apps/alsijil/rules.py b/aleksis/apps/alsijil/rules.py
index 9045598fdf362f0bedb57424fd73bb450d80d669..5f85fec8020798a2045f89ff51fb946aaddd4546 100644
--- a/aleksis/apps/alsijil/rules.py
+++ b/aleksis/apps/alsijil/rules.py
@@ -13,9 +13,11 @@ from aleksis.core.util.predicates import (
 from .util.predicates import (
     can_edit_documentation,
     can_edit_participation_status,
+    can_edit_personal_note,
     can_view_any_documentation,
     can_view_documentation,
     can_view_participation_status,
+    can_view_personal_note,
     has_lesson_group_object_perm,
     has_person_group_object_perm,
     has_personal_note_group_perm,
@@ -435,3 +437,21 @@ add_perm(
     "alsijil.edit_participation_status_for_documentation_rule",
     edit_participation_status_for_documentation_predicate,
 )
+
+view_personal_note_predicate = has_person & (
+    has_global_perm("alsijil.change_newpersonalnote") | can_view_personal_note
+)
+add_perm(
+    "alsijil.view_personal_note_rule",
+    view_personal_note_predicate,
+)
+
+edit_personal_note_predicate = (
+    has_person
+    & (has_global_perm("alsijil.change_newpersonalnote") | can_edit_personal_note)
+    & is_in_allowed_time_range
+)
+add_perm(
+    "alsijil.edit_personal_note_rule",
+    edit_personal_note_predicate,
+)
diff --git a/aleksis/apps/alsijil/schema/extra_marks.py b/aleksis/apps/alsijil/schema/extra_marks.py
index 90f3e28d2a07b818240d484ed2b5c46a8dd9ba37..4eb9f0fe17a769402c4ba91b575ad8430c64b79e 100644
--- a/aleksis/apps/alsijil/schema/extra_marks.py
+++ b/aleksis/apps/alsijil/schema/extra_marks.py
@@ -1,4 +1,7 @@
+from django.core.exceptions import PermissionDenied
+
 from graphene_django import DjangoObjectType
+from guardian.shortcuts import get_objects_for_user
 
 from aleksis.apps.alsijil.models import ExtraMark
 from aleksis.core.schema.base import (
@@ -9,6 +12,7 @@ from aleksis.core.schema.base import (
     OptimisticResponseTypeMixin,
     PermissionsTypeMixin,
 )
+from aleksis.core.util.core_helpers import has_person
 
 
 class ExtraMarkType(
@@ -21,23 +25,44 @@ class ExtraMarkType(
         model = ExtraMark
         fields = ("id", "short_name", "name", "colour_fg", "colour_bg", "show_in_coursebook")
 
+    @classmethod
+    def get_queryset(cls, queryset, info):
+        if has_person(info.context.user):
+            return get_objects_for_user(info.context.user, "alsijil.view_extramark", queryset)
+        raise PermissionDenied()
+
 
 class ExtraMarkBatchCreateMutation(BaseBatchCreateMutation):
     class Meta:
         model = ExtraMark
         fields = ("short_name", "name", "colour_fg", "colour_bg", "show_in_coursebook")
         optional_fields = ("name",)
-        permissions = ("alsijil.create_extra_mark",)  # FIXME
+
+    @classmethod
+    def check_permissions(cls, root, info, input):  # noqa
+        if info.context.user.has_perm("alsijil.add_extramark_rule"):
+            return
+        raise PermissionDenied()
 
 
 class ExtraMarkBatchDeleteMutation(BaseBatchDeleteMutation):
     class Meta:
         model = ExtraMark
-        permissions = ("alsijil.delete_extra_mark",)  # FIXME
+
+    @classmethod
+    def check_permissions(cls, root, info, input):  # noqa
+        if info.context.user.has_perm("alsijil.delete_extramark_rule"):
+            return
+        raise PermissionDenied()
 
 
 class ExtraMarkBatchPatchMutation(BaseBatchPatchMutation):
     class Meta:
         model = ExtraMark
         fields = ("id", "short_name", "name", "colour_fg", "colour_bg", "show_in_coursebook")
-        permissions = ("alsijil.change_extra_mark",)  # FIXME
+
+    @classmethod
+    def check_permissions(cls, root, info, input):  # noqa
+        if info.context.user.has_perm("alsijil.edit_extramark_rule"):
+            return
+        raise PermissionDenied()
diff --git a/aleksis/apps/alsijil/schema/personal_note.py b/aleksis/apps/alsijil/schema/personal_note.py
index 7558378aefcefbef8b86d8ed694e5266317ff713..dfe36359d87345a0b51992e689627065638fcd4e 100644
--- a/aleksis/apps/alsijil/schema/personal_note.py
+++ b/aleksis/apps/alsijil/schema/personal_note.py
@@ -32,7 +32,7 @@ class PersonalNoteBatchCreateMutation(BaseBatchCreateMutation):
         type_name = "BatchCreatePersonalNoteInput"
         return_field_name = "personalNotes"
         fields = ("note", "extra_mark", "documentation", "person")
-        permissions = ("alsijil.create_personal_note",)  # FIXME
+        permissions = ("alsijil.edit_personal_note_rule",)
 
 
 class PersonalNoteBatchPatchMutation(BaseBatchPatchMutation):
@@ -41,10 +41,10 @@ class PersonalNoteBatchPatchMutation(BaseBatchPatchMutation):
         type_name = "BatchPatchPersonalNoteInput"
         return_field_name = "personalNotes"
         fields = ("id", "note", "extra_mark", "documentation", "person")
-        permissions = ("alsijil.change_personal_note",)  # FIXME
+        permissions = ("alsijil.edit_personal_note_rule",)
 
 
 class PersonalNoteBatchDeleteMutation(BaseBatchDeleteMutation):
     class Meta:
         model = NewPersonalNote
-        permissions = ("alsijil.delete_personal_note",)  # FIXME
+        permissions = ("alsijil.edit_personal_note_rule",)
diff --git a/aleksis/apps/alsijil/util/predicates.py b/aleksis/apps/alsijil/util/predicates.py
index 9f06195e279b6e9bc9564731146d33ea7995498d..122442edd50c08b193c7aa6798ff1a4c6e745856 100644
--- a/aleksis/apps/alsijil/util/predicates.py
+++ b/aleksis/apps/alsijil/util/predicates.py
@@ -12,7 +12,7 @@ from aleksis.core.models import Group, Person
 from aleksis.core.util.core_helpers import get_site_preferences
 from aleksis.core.util.predicates import check_object_permission
 
-from ..models import Documentation, PersonalNote
+from ..models import Documentation, NewPersonalNote, PersonalNote
 
 
 @predicate
@@ -475,8 +475,14 @@ def can_edit_participation_status(user: User, obj: Documentation):
 
 
 @predicate
-def is_in_allowed_time_range(user: User, obj: Documentation):
-    """Predicate which checks if the documentation is in the allowed time range for editing."""
+def is_in_allowed_time_range(user: User, obj: Union[Documentation, NewPersonalNote]):
+    """Predicate for documentations or new personal notes with linked documentation.
+
+    Predicate which checks if the given documentation or the documentation linked
+    to the given NewPersonalNote is in the allowed time range for editing.
+    """
+    if isinstance(obj, NewPersonalNote):
+        obj = obj.documentation
     if obj and (
         get_site_preferences()["alsijil__allow_edit_future_documentations"] == "all"
         or (
@@ -498,3 +504,31 @@ def is_in_allowed_time_range_for_participation_status(user: User, obj: Documenta
     if obj and obj.value_start_datetime(obj) <= now():
         return True
     return False
+
+
+@predicate
+def can_view_personal_note(user: User, obj: NewPersonalNote):
+    """Predicate which checks if the user is allowed to view a personal note."""
+    if obj.documentation:
+        if is_documentation_teacher(user, obj.documentation):
+            return True
+        if obj.documentation.amends:
+            return is_lesson_event_teacher(
+                user, obj.documentation.amends
+            ) | is_lesson_event_group_owner(user, obj.documentation.amends)
+        if obj.documentation.course:
+            return is_course_teacher(user, obj.documentation.course)
+    return False
+
+
+@predicate
+def can_edit_personal_note(user: User, obj: NewPersonalNote):
+    """Predicate which checks if the user is allowed to edit a personal note."""
+    if obj.documentation:
+        if is_documentation_teacher(user, obj.documentation):
+            return True
+        if obj.documentation.amends:
+            return is_lesson_event_teacher(
+                user, obj.documentation.amends
+            ) | is_lesson_event_group_owner(user, obj.documentation.amends)
+    return False