From 61870d427dfec2b2d4c5b1520f202ce26f3b01f8 Mon Sep 17 00:00:00 2001
From: Elmar Ludwig <elmar.ludwig@uni-osnabrueck.de>
Date: Thu, 21 Apr 2022 11:05:52 +0000
Subject: [PATCH] add pk for user inst, re #947

---
 app/controllers/admin/statusgroups.php        |  3 +-
 app/controllers/institute/members.php         |  5 +--
 app/controllers/settings/statusgruppen.php    |  3 +-
 db/migrations/5.2.1_add_pk_for_user_inst.php  | 32 +++++++++++++++++++
 .../InstituteMembershipsShow.php              |  2 +-
 lib/models/InstituteMember.class.php          | 12 +++++++
 6 files changed, 52 insertions(+), 5 deletions(-)
 create mode 100644 db/migrations/5.2.1_add_pk_for_user_inst.php

diff --git a/app/controllers/admin/statusgroups.php b/app/controllers/admin/statusgroups.php
index e9e4e45711b..57ad3185f69 100644
--- a/app/controllers/admin/statusgroups.php
+++ b/app/controllers/admin/statusgroups.php
@@ -380,7 +380,8 @@ class Admin_StatusgroupsController extends AuthenticatedController
             'inst' => [
                 'name' => _('Institut'),
                 'after_user_add' => function ($user_id) {
-                    $newInstUser = new InstituteMember([$user_id, Context::getId()]);
+                    $newInstUser = InstituteMember::findByUserAndInstitute($user_id, Context::getId()) ?:
+                                   InstituteMember::build(['user_id' => $user_id, 'institut_id' => Context::getId()]);
                     if ($newInstUser->isNew() || $newInstUser->inst_perms == 'user') {
                         $user = new User($user_id);
                         $newInstUser->inst_perms = $user->perms;
diff --git a/app/controllers/institute/members.php b/app/controllers/institute/members.php
index 2fec9072c31..162c96deb04 100644
--- a/app/controllers/institute/members.php
+++ b/app/controllers/institute/members.php
@@ -297,7 +297,8 @@ class Institute_MembersController extends AuthenticatedController
         $enable_mail_dozent = in_array('dozenten', $additionalCheckboxes);
 
         foreach ($mp->getAddedUsers() as $u_id) {
-            $member = new InstituteMember([$u_id, $this->institute->id]);
+            $member = InstituteMember::findByUserAndInstitute($u_id, $this->institute->id) ?:
+                      InstituteMember::build(['user_id' => $u_id, 'institut_id' => $this->institute->id]);
 
             if (!$member->isNew() && $member->inst_perms !== 'user') {
                 // der Admin hat Tomaten auf den Augen, der Mitarbeiter sitzt schon im Institut
@@ -442,7 +443,7 @@ class Institute_MembersController extends AuthenticatedController
             throw new Exception(_('Sie können sich nicht selbst aus der Einrichtung austragen.'));
         }
 
-        $member = InstituteMember::find([$user->id, $this->institute->id]);
+        $member = InstituteMember::findByUserAndInstitute($user->id, $this->institute->id);
         if ($member && $member->delete()) {
             PageLayout::postInfo(sprintf(
                 _('%s wurde von der Liste des Personals gelöscht.'),
diff --git a/app/controllers/settings/statusgruppen.php b/app/controllers/settings/statusgruppen.php
index d7de2546cfc..88e42df1266 100644
--- a/app/controllers/settings/statusgruppen.php
+++ b/app/controllers/settings/statusgruppen.php
@@ -208,7 +208,8 @@ class Settings_StatusgruppenController extends Settings_SettingsController
             } elseif (!$group->addUser($this->user->id)) {
                 PageLayout::postError(_('Fehler beim Eintragen in die Gruppe!'));
             } else {
-                $member  = new InstituteMember([$this->user->id, $range_id]);
+                $member  = InstituteMember::findByUserAndInstitute($this->user->id, $range_id) ?:
+                           InstituteMember::build(['user_id' => $this->user->id, 'institut_id' => $range_id]);
                 $member->inst_perms = $this->user->perms;
 
                 $was_new   = $member->isNew();
diff --git a/db/migrations/5.2.1_add_pk_for_user_inst.php b/db/migrations/5.2.1_add_pk_for_user_inst.php
new file mode 100644
index 00000000000..1a4e49bdcc8
--- /dev/null
+++ b/db/migrations/5.2.1_add_pk_for_user_inst.php
@@ -0,0 +1,32 @@
+<?php
+
+class AddPkForUserInst extends Migration
+{
+    public function description()
+    {
+        return 'add simple pk for user_inst table';
+    }
+
+    public function up()
+    {
+        $db = DBManager::get();
+
+        $sql = 'ALTER TABLE user_inst
+                ADD id int(11) NOT NULL AUTO_INCREMENT FIRST,
+                DROP PRIMARY KEY,
+                ADD PRIMARY KEY (id),
+                ADD UNIQUE KEY user_inst (Institut_id, user_id)';
+        $db->exec($sql);
+    }
+
+    public function down()
+    {
+        $db = DBManager::get();
+
+        $sql = 'ALTER TABLE user_inst
+                DROP id,
+                DROP KEY user_inst,
+                ADD PRIMARY KEY (Institut_id, user_id)';
+        $db->exec($sql);
+    }
+}
diff --git a/lib/classes/JsonApi/Routes/InstituteMemberships/InstituteMembershipsShow.php b/lib/classes/JsonApi/Routes/InstituteMemberships/InstituteMembershipsShow.php
index 1f0067a8b9f..7662af34693 100644
--- a/lib/classes/JsonApi/Routes/InstituteMemberships/InstituteMembershipsShow.php
+++ b/lib/classes/JsonApi/Routes/InstituteMemberships/InstituteMembershipsShow.php
@@ -17,7 +17,7 @@ class InstituteMembershipsShow extends JsonApiController
      */
     public function __invoke(Request $request, Response $response, $args)
     {
-        if (!$membership = \InstituteMember::find(explode('_', $args['id'], 2))) {
+        if (!$membership = \InstituteMember::find($args['id'])) {
             throw new RecordNotFoundException();
         }
 
diff --git a/lib/models/InstituteMember.class.php b/lib/models/InstituteMember.class.php
index fe1b19d8359..4048fdd72f8 100644
--- a/lib/models/InstituteMember.class.php
+++ b/lib/models/InstituteMember.class.php
@@ -134,6 +134,18 @@ class InstituteMember extends SimpleORMap implements PrivacyObject
         );
     }
 
+    /**
+     * Finds an institute membership by user and institute id.
+     *
+     * @param string $user_id
+     * @param string $institute_id
+     * @return InstituteMember|null
+     */
+    public static function findByUserAndInstitute($user_id, $institute_id)
+    {
+        return self::findOneBySQL('user_id = ? AND institut_id = ?', [$user_id, $institute_id]);
+    }
+
     public function getUserFullname($format = 'full')
     {
         return User::build(array_merge(
-- 
GitLab