Berechtigungssystem¶
Bifolk implementiert Rollenbasierte Zugriffskontrolle (RBAC), bei der Berechtigungen basierend auf der Rolle eines Benutzers innerhalb einer Organisation vergeben werden.
Zielgruppe: Softwareentwickler
Kernkonzepte¶
- Organisationen: Alle Geschäftsdaten gehören zu einer Organisation
- Mitgliedschaft: Benutzer gehören Organisationen über
OrganizationMembershipan - Rollen: Jede Mitgliedschaft hat eine Rolle (Besitzer, Admin, Mitglied, Betrachter)
- Datenisolierung: Benutzer sehen nur Daten ihrer Organisationen
Rollenhierarchie¶
| Rolle | Ansehen | Erstellen | Eigene bearbeiten | Alle bearbeiten | Löschen | Mitglieder verwalten | Org löschen |
|---|---|---|---|---|---|---|---|
| Besitzer | Ja | Ja | Ja | Ja | Ja | Ja | Ja |
| Admin | Ja | Ja | Ja | Ja | Ja | Ja | Nein |
| Mitglied | Ja | Ja | Ja | Nein | Nein | Nein | Nein |
| Betrachter | Ja | Nein | Nein | Nein | Nein | Nein | Nein |
Berechtigungs-Hilfsfunktionen¶
Alle zentralisiert in organizations/utils.py.
Kernfunktionen¶
| Funktion | Rückgabe | Beschreibung |
|---|---|---|
get_user_role(user, organization) |
str oder None |
Benutzerrolle: 'owner', 'admin', 'member', 'viewer' |
get_user_organizations(user) |
QuerySet |
Alle Organisationen des Benutzers |
user_is_member(user, organization) |
bool |
Prüfung auf aktive Mitgliedschaft |
Ressourcen-Berechtigungsfunktionen¶
| Funktion | Parameter | Regeln |
|---|---|---|
user_can_view(user, resource) |
Ressource mit organization-Attribut |
Jedes Mitglied kann ansehen |
user_can_create(user, organization) |
Organisation | Mitglied+ kann erstellen |
user_can_edit(user, resource) |
Ressource mit organization, created_by |
Besitzer/Admin: alle; Mitglied: nur eigene |
user_can_delete(user, resource) |
Ressource mit organization |
Nur Besitzer/Admin |
Organisationsverwaltungs-Funktionen¶
from organizations.utils import (
user_can_manage_members,
user_can_delete_org,
user_can_change_org_settings,
)
| Funktion | Regeln |
|---|---|
user_can_manage_members(user, org) |
Besitzer/Admin |
user_can_delete_org(user, org) |
Nur Besitzer |
user_can_change_org_settings(user, org) |
Besitzer/Admin |
Abfragefilterung¶
from organizations.utils import filter_by_user_organizations
user_hives = filter_by_user_organizations(Hive.objects.all(), request.user)
Berechtigungen auf Modellebene¶
Alle Geschäftsmodelle implementieren Berechtigungsmethoden:
class Hive(models.Model):
organization = models.ForeignKey(Organization, on_delete=models.CASCADE)
created_by = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
def user_can_view(self, user):
# Jedes aktive Mitglied der Organisation
...
def user_can_edit(self, user):
# Besitzer/Admin: alle; Mitglied: nur eigene; Betrachter: nein
...
def user_can_delete(self, user):
# Nur Besitzer/Admin
...
Modelle mit diesen Methoden: Hive, Queen, HiveInspection, HarvestRecord, alle BeekeepingOperation-Unterklassen, QueenBreeding, ColonySplit, InventoryItem, InventoryTransaction, ProductSale.
Berechtigungen auf View-Ebene¶
In Views¶
from django.http import HttpResponseForbidden
from organizations.utils import user_can_edit
def edit_hive(request, hive_id):
hive = get_object_or_404(Hive, id=hive_id)
if not user_can_edit(request.user, hive):
return HttpResponseForbidden()
# mit Bearbeitung fortfahren...
QuerySets filtern¶
Immer nach aktueller Organisation filtern:
def hive_list(request):
if request.current_organization:
hives = Hive.objects.filter(organization=request.current_organization)
else:
hives = Hive.objects.none()
return render(request, 'hives/hive_list.html', {'hives': hives})
Berechtigungen auf Template-Ebene¶
{% load organization_tags %}
{% if hive.user_can_edit user %}
<a href="{% url 'hives:edit' hive.id %}">Bearbeiten</a>
{% endif %}
{% if hive.user_can_delete user %}
<a href="{% url 'hives:delete' hive.id %}">Löschen</a>
{% endif %}
Organizations-Middleware¶
OrganizationMiddleware (organizations/middleware.py) läuft nach AuthenticationMiddleware und stellt bereit:
request.current_organization- Aktive Organisation (aus Session oder Standard)request.user_organizations- Alle Organisationen des Benutzers
Wechseln: Benutzer wechseln Organisationen über den Seitenleisten-Wähler. Die ausgewählte Organisation wird in der Session gespeichert.
Best Practices¶
- Immer Berechtigungen prüfen in Views vor der Datenänderung
- Immer QuerySets filtern nach
request.current_organization - Organisation beim Erstellen setzen:
obj.organization = request.current_organization - Die Hilfsfunktionen verwenden statt Berechtigungslogik neu zu implementieren
- None-Organisation behandeln für Benutzer ohne Organisationen
- Nicht existierende Ressourcen verbergen: QuerySets filtern, um Ressourcenexistenz nicht preiszugeben
# Bevorzugt (verbirgt Existenz)
hive = get_object_or_404(Hive, id=hive_id, organization__in=request.user_organizations)
# Statt (gibt Existenz preis)
hive = get_object_or_404(Hive, id=hive_id)
if not hive.user_can_view(request.user):
return HttpResponseForbidden()
Verwandte Dokumentation¶
- Datenbankmodelle - Berechtigungsmethoden auf Modellen
- Architekturübersicht - Mandantenfähiges Design
- Organisationsverwaltung - Admin-Perspektive
- Interne KI-Referenz:
docs/claude/03-PERMISSIONS.mdfür vollständige Funktionssignaturen