From f03e67bc8860bd8d1e0a70130d63be18b359e2af Mon Sep 17 00:00:00 2001
From: Jan-Hendrik Willms <tleilax+studip@gmail.com>
Date: Tue, 9 Jul 2024 11:24:05 +0000
Subject: [PATCH] consultation slot events are not editable/movable/deletable
 in fullcalendar, fixes #4375

Closes #4375

Merge request studip/studip!3188
---
 lib/models/ConsultationSlot.php                | 15 ++++++++++++---
 lib/models/calendar/CalendarDate.php           |  9 +++++++++
 lib/models/calendar/CalendarDateAssignment.php |  4 ----
 3 files changed, 21 insertions(+), 7 deletions(-)

diff --git a/lib/models/ConsultationSlot.php b/lib/models/ConsultationSlot.php
index f79568d3aea..5a59208c8a4 100644
--- a/lib/models/ConsultationSlot.php
+++ b/lib/models/ConsultationSlot.php
@@ -25,6 +25,8 @@
  */
 class ConsultationSlot extends SimpleORMap
 {
+    private const EVENT_PREFIX = 'Stud.IP-Consultation-Event#';
+
     /**
      * Configures the model.
      * @param array  $config Configuration
@@ -165,6 +167,14 @@ class ConsultationSlot extends SimpleORMap
         ]);
     }
 
+    /**
+     * Returns whether the given event is an event for a consultation slot.
+     */
+    public static function isSlotEvent(CalendarDate $event): bool
+    {
+        return str_starts_with($event->unique_id, self::EVENT_PREFIX);
+    }
+
     /**
      * Returns whether this slot is occupied (by a given user).
      */
@@ -233,10 +243,9 @@ class ConsultationSlot extends SimpleORMap
      * @param  User $user [description]
      * @return string unique event id
      */
-    protected function createEventId(User $user)
+    protected function createEventId(User $user): string
     {
-        $rand_id = md5(uniqid(self::class, true));
-        return "Termin{$rand_id}-{$user->id}";
+        return self::EVENT_PREFIX . "{$this->id}:{$user->id}";
     }
 
     /**
diff --git a/lib/models/calendar/CalendarDate.php b/lib/models/calendar/CalendarDate.php
index 0318dab5ef8..fc31d52f912 100644
--- a/lib/models/calendar/CalendarDate.php
+++ b/lib/models/calendar/CalendarDate.php
@@ -189,6 +189,15 @@ class CalendarDate extends SimpleORMap implements PrivacyObject
 
     public function isWritable(string $range_id)
     {
+        if (ConsultationSlot::isSlotEvent($this)) {
+            return false;
+        }
+
+        if ($this->author_id === $range_id) {
+            //The author may always modify one of their dates:
+            return true;
+        }
+
         if (CalendarDateAssignment::exists([$range_id, $this->id])) {
             //The date is in the calendar of the user/course
             //and therefore, the user or course administrator (tutor, dozent)
diff --git a/lib/models/calendar/CalendarDateAssignment.php b/lib/models/calendar/CalendarDateAssignment.php
index e0e2135452d..53d54d86608 100644
--- a/lib/models/calendar/CalendarDateAssignment.php
+++ b/lib/models/calendar/CalendarDateAssignment.php
@@ -521,10 +521,6 @@ class CalendarDateAssignment extends SimpleORMap implements Event
 
     public function isWritable(string $user_id): bool
     {
-        if ($this->calendar_date->author_id === $user_id) {
-            //The author may always modify one of their dates:
-            return true;
-        }
         if ($this->calendar_date->isWritable($user_id)) {
             //The date is writable.
             return true;
-- 
GitLab