From f9ae47fa0f4bbb67810412a9050b40f96f32d70e Mon Sep 17 00:00:00 2001
From: Petar Hristov <hristov@itc.rwth-aachen.de>
Date: Wed, 8 Jun 2022 15:30:18 +0200
Subject: [PATCH] Fix: User Invitation List API Call and access of member users
 to the /members page (coscine/issues#2144)

---
 src/modules/project/ProjectModule.vue         |  4 ----
 src/modules/project/pages/Members.vue         | 20 ++++++++++++++++++-
 .../project/pages/components/MembersTable.vue |  8 ++++++--
 .../pages/components/UserSearchRow.vue        | 17 ++++++++++------
 4 files changed, 36 insertions(+), 13 deletions(-)

diff --git a/src/modules/project/ProjectModule.vue b/src/modules/project/ProjectModule.vue
index ad174642..4c37c6bb 100644
--- a/src/modules/project/ProjectModule.vue
+++ b/src/modules/project/ProjectModule.vue
@@ -98,10 +98,6 @@ export default defineComponent({
       if (this.projectStore.roles === null) {
         this.projectStore.retrieveRoles();
       }
-      // Load Invitations for the project if not present
-      if (this.projectStore.currentInvitations === null) {
-        this.projectStore.retrieveInvitations(this.project);
-      }
     },
   },
 });
diff --git a/src/modules/project/pages/Members.vue b/src/modules/project/pages/Members.vue
index c9429980..ea239bab 100644
--- a/src/modules/project/pages/Members.vue
+++ b/src/modules/project/pages/Members.vue
@@ -8,6 +8,7 @@
         :member-role="memberRole"
         :project="project"
         :roles="roles"
+        :is-owner="isOwner"
         @addUser="addUser"
         @prepareInvitation="prepareInvitation"
         @setFilter="setFilter"
@@ -31,6 +32,7 @@
                 :remove-text="$t('buttons.remove')"
                 :owner-count="ownerCount"
                 :owner-role="ownerRole"
+                :is-owner="isOwner"
                 @tableFilteredRows="onFilteredRows"
                 @setRole="setRole"
                 @selectedItem="prepareDeletion"
@@ -38,7 +40,10 @@
             </b-tab>
 
             <!-- Invited Users  -->
-            <b-tab :title="$t('page.members.externalUsersTabTitle')">
+            <b-tab
+              v-if="isOwner"
+              :title="$t('page.members.externalUsersTabTitle')"
+            >
               <MembersTable
                 id="invitationTable"
                 :headers="invitationHeaders"
@@ -271,6 +276,19 @@ export default defineComponent({
         },
       ];
     },
+    isOwner(): boolean | undefined {
+      return this.projectStore.currentUserRoleIsOwner;
+    },
+  },
+
+  created() {
+    // Load Invitations for the project if not present
+    if (
+      this.projectStore.currentInvitations === null &&
+      this.projectStore.currentUserRoleIsOwner
+    ) {
+      this.projectStore.retrieveInvitations(this.project);
+    }
   },
 
   methods: {
diff --git a/src/modules/project/pages/components/MembersTable.vue b/src/modules/project/pages/components/MembersTable.vue
index ae503757..bb0fc214 100644
--- a/src/modules/project/pages/components/MembersTable.vue
+++ b/src/modules/project/pages/components/MembersTable.vue
@@ -36,7 +36,7 @@
             v-model="row.item.role.id"
             :options="roles"
             :disabled="
-              ownerCount === 1 && ownerRole && row.item.role.id === ownerRole.id
+              (ownerCount === 1 && ownerRole && row.item.role.id === ownerRole.id) || !isOwner
             "
             text-field="displayName"
             value-field="id"
@@ -61,7 +61,7 @@
             variant="danger"
             size="sm"
             :disabled="
-              ownerCount === 1 && ownerRole && row.item.role.id === ownerRole.id
+              (ownerCount === 1 && ownerRole && row.item.role.id === ownerRole.id) || !isOwner
             "
             @click="deleteItem(row.item)"
             >{{ removeText }}</b-button
@@ -171,6 +171,10 @@ export default defineComponent({
       default: "user.surname",
       type: String,
     },
+    isOwner: {
+      default: false,
+      type: Boolean,
+    }
   },
   data() {
     return {
diff --git a/src/modules/project/pages/components/UserSearchRow.vue b/src/modules/project/pages/components/UserSearchRow.vue
index cef3bbf3..4130a9b0 100644
--- a/src/modules/project/pages/components/UserSearchRow.vue
+++ b/src/modules/project/pages/components/UserSearchRow.vue
@@ -12,6 +12,7 @@
                 adaptSelect: true,
                 'no-results': queriedUsers.length === 0,
               }"
+              :disabled="!isOwner"
               :options="queriedUsers"
               :filter-by="filterMock"
               :selectable="(option) => !option.hasProjectRole"
@@ -67,6 +68,7 @@
                   ? memberRole.id
                   : null
               "
+              :disabled="!isOwner"
               text-field="displayName"
               value-field="id"
               @input="setNewRole"
@@ -80,7 +82,7 @@
             <b-button
               v-if="validInvitation && !validSelection"
               name="inviteUserToProject"
-              :disabled="!validInvitation"
+              :disabled="!validInvitation || !isOwner"
               @click="prepareInvitation(newUserRole)"
               >{{ $t("buttons.invite") }}</b-button
             >
@@ -88,12 +90,13 @@
             <b-button
               v-else
               name="addUserToProject"
-              :disabled="!validSelection"
+              :disabled="!validSelection || !isOwner"
               @click="addUser(newUserRole)"
               >{{ $t("buttons.addUser") }}</b-button
             >
             <b-button
               name="importUser"
+              :disabled="!isOwner"
               @click="$bvModal.show('importUserModal')"
               >{{ $t("buttons.import") }}</b-button
             >
@@ -155,6 +158,10 @@ export default defineComponent({
       default: null,
       type: [Array, null] as PropType<RoleObject[] | null>,
     },
+    isOwner: {
+      default: false,
+      type: Boolean,
+    }
   },
   setup() {
     const userStore = useUserStore();
@@ -266,10 +273,8 @@ export default defineComponent({
     async fetchUserOptions(search: string, loading: (value: boolean) => void) {
       if (search && this.project && this.project.id) {
         loading(true);
-        this.queriedUsers = await this.userStore.getUser(
-          search,
-          this.project.id
-        );
+        this.queriedUsers =
+          (await this.userStore.getUser(search, this.project.id)) ?? [];
         loading(false);
         if (this.validEmail && this.queriedUsers.length == 0) {
           // Add unknown entry as an entry to the list (email address of user to invite)
-- 
GitLab