feat: Kalender - Autocomplete + Privat-Flag + Share-Liste + Bugfix

Sharing-Fix:
Calendar-Model hatte keine owner-Relation zu User - list_calendars
stuerzte beim Listen geteilter Kalender ab (c.owner.username ->
AttributeError). Jetzt mit explizitem foreign_keys Relationship.

Benutzer-Autocomplete:
"Kalender teilen" nutzt jetzt /users/search wie bei Dateien.
Tippt man 2+ Zeichen, erscheint ein Dropdown mit passenden
Benutzernamen. Klick uebernimmt den Namen.

Bestehende Freigaben werden im Menue angezeigt mit Muelleimer
zum Entfernen.

Privat-Flag fuer Termine:
CalendarEvent bekommt is_private-Spalte. Checkbox im Termin-
Dialog "🔒 Privat (Teilnehmer sehen nur den Zeitblock)".

Redaction greift an drei Stellen:
* GET /events: Nicht-Owner sehen summary="Privat", description
  und location = null. Zeitfenster bleibt voll sichtbar.
* iCal-Export (/ical/<token>): Privat-Events werden mit
  CLASS:PRIVATE ausgegeben und SUMMARY/DESCRIPTION/LOCATION
  werden gestrippt.
* CalDAV: aktuell werden eh nur eigene Kalender exportiert,
  also keine Redaction noetig. Kommt bei Share-Support rein.

Der Eigentuemer sieht natuerlich in seiner eigenen Ansicht alle
Details seines privaten Termins.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Stefan Hacker
2026-04-12 12:56:25 +02:00
parent 5797a7b738
commit a143325bbe
3 changed files with 133 additions and 4 deletions
+3
View File
@@ -21,6 +21,7 @@ class Calendar(db.Model):
cascade='all, delete-orphan')
shares = db.relationship('CalendarShare', backref='calendar', lazy='dynamic',
cascade='all, delete-orphan')
owner = db.relationship('User', foreign_keys=[owner_id])
def to_dict(self):
return {
@@ -50,6 +51,7 @@ class CalendarEvent(db.Model):
all_day = db.Column(db.Boolean, default=False)
recurrence_rule = db.Column(db.Text, nullable=True)
exdates = db.Column(db.Text, nullable=True) # Komma-separiert, ISO-Datum (YYYY-MM-DD)
is_private = db.Column(db.Boolean, default=False, nullable=False)
created_at = db.Column(db.DateTime, default=lambda: datetime.now(timezone.utc))
updated_at = db.Column(db.DateTime, default=lambda: datetime.now(timezone.utc),
onupdate=lambda: datetime.now(timezone.utc))
@@ -67,6 +69,7 @@ class CalendarEvent(db.Model):
'all_day': self.all_day,
'recurrence_rule': self.recurrence_rule,
'exdates': self.exdates.split(',') if self.exdates else [],
'is_private': bool(self.is_private),
'created_at': self.created_at.isoformat() if self.created_at else None,
'updated_at': self.updated_at.isoformat() if self.updated_at else None,
}