diff --git a/aleksis/core/models.py b/aleksis/core/models.py
index 37ba7e4c0e6901970a94ec7a88a7550786cac971..90e710171bee515361ff00e15a74e0601313faf2 100644
--- a/aleksis/core/models.py
+++ b/aleksis/core/models.py
@@ -582,4 +582,5 @@ class GlobalPermissions(ExtensibleModel):
             ("link_persons_accounts", _("Can link persons to accounts")),
             ("manage_data", _("Can manage data")),
             ("impersonate", _("Can impersonate")),
+            ("search", _("Can use search")),
         )
diff --git a/aleksis/core/rules.py b/aleksis/core/rules.py
index 8cadab888900a04feb5f0d53af89614e67c2b587..371949baa67aca1463c1c286795a31c9189bc54d 100644
--- a/aleksis/core/rules.py
+++ b/aleksis/core/rules.py
@@ -12,6 +12,13 @@ from aleksis.core.util.predicates import (
 
 add_perm("core", always_allow)
 
+# View dashboard
+add_perm("core.view_dashboard", has_person_predicate)
+
+# Use search
+search_predicate = has_person_predicate & has_global_perm("core.search")
+add_perm("core.search", search_predicate)
+
 # View persons
 view_persons_predicate = has_person_predicate & (
     has_global_perm("core.view_person") | has_any_object("core.view_person", Person)
diff --git a/aleksis/core/views.py b/aleksis/core/views.py
index d2721ff88ad1b8ce58acce44bc29e1d52d560952..d566ce328f7fbe5aa73d3261dfcaeecfe0aa4846 100644
--- a/aleksis/core/views.py
+++ b/aleksis/core/views.py
@@ -26,7 +26,7 @@ from .tables import GroupsTable, PersonsTable
 from .util import messages
 
 
-@person_required
+@permission_required("core.view_dashboard")
 def index(request: HttpRequest) -> HttpResponse:
     context = {}
 
@@ -347,7 +347,7 @@ def delete_announcement(request: HttpRequest, pk: int) -> HttpResponse:
     return redirect("announcements")
 
 
-@login_required
+@permission_required("core.search")
 def searchbar_snippets(request: HttpRequest) -> HttpResponse:
     query = request.GET.get('q', '')
     limit = int(request.GET.get('limit', '5'))