You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@airavata.apache.org by ma...@apache.org on 2019/05/09 16:19:56 UTC

[airavata-django-portal] 01/06: AIRAVATA-3030 Display inherited parent permissions, parent entity owner

This is an automated email from the ASF dual-hosted git repository.

machristie pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/airavata-django-portal.git

commit a3037536fbec1611c56daa8404e53a0b689176d3
Author: Marcus Christie <ma...@apache.org>
AuthorDate: Fri May 3 15:27:54 2019 -0400

    AIRAVATA-3030 Display inherited parent permissions, parent entity owner
---
 .../js/components/experiment/ExperimentEditor.vue  |  3 +
 .../static/common/js/components/ShareButton.vue    | 85 ++++++++++++++++++++--
 .../common/js/components/SharedEntityEditor.vue    | 55 ++++++++++++--
 3 files changed, 129 insertions(+), 14 deletions(-)

diff --git a/django_airavata/apps/workspace/static/django_airavata_workspace/js/components/experiment/ExperimentEditor.vue b/django_airavata/apps/workspace/static/django_airavata_workspace/js/components/experiment/ExperimentEditor.vue
index 773b9c8..16193c1 100644
--- a/django_airavata/apps/workspace/static/django_airavata_workspace/js/components/experiment/ExperimentEditor.vue
+++ b/django_airavata/apps/workspace/static/django_airavata_workspace/js/components/experiment/ExperimentEditor.vue
@@ -18,6 +18,9 @@
         <share-button
           ref="shareButton"
           :entity-id="localExperiment.experimentId"
+          :entity-label="'Experiment'"
+          :parent-entity-id="localExperiment.projectId"
+          :parent-entity-label="'Project'"
           :auto-add-default-gateway-users-group="false"
         />
       </div>
diff --git a/django_airavata/static/common/js/components/ShareButton.vue b/django_airavata/static/common/js/components/ShareButton.vue
index 4e947b0..f9eb6f9 100644
--- a/django_airavata/static/common/js/components/ShareButton.vue
+++ b/django_airavata/static/common/js/components/ShareButton.vue
@@ -1,13 +1,52 @@
 <template>
   <div class="share-button btn-container">
-    <b-button :variant="'outline-primary'" :title="title" :disabled="!shareButtonEnabled" @click="openSharingSettingsModal">
+    <b-button
+      :variant="'outline-primary'"
+      :title="title"
+      :disabled="!shareButtonEnabled"
+      @click="openSharingSettingsModal"
+    >
       Share
       <b-badge>{{ totalCount }}</b-badge>
     </b-button>
-    <b-modal class="modal-share-settings" title="Sharing Settings" ref="sharingSettingsModal" ok-title="Save" @ok="saveSharedEntity"
-      @cancel="cancelEditSharedEntity" no-close-on-esc no-close-on-backdrop hide-header-close @show="showSharingSettingsModal">
-      <shared-entity-editor v-if="localSharedEntity && users && groups" v-model="localSharedEntity" :users="users"
-        :groups="groups" :disallow-editing-admin-groups="disallowEditingAdminGroups" />
+    <b-modal
+      class="modal-share-settings"
+      title="Sharing Settings"
+      ref="sharingSettingsModal"
+      ok-title="Save"
+      @ok="saveSharedEntity"
+      @cancel="cancelEditSharedEntity"
+      no-close-on-esc
+      no-close-on-backdrop
+      hide-header-close
+      @show="showSharingSettingsModal"
+    >
+      <shared-entity-editor
+        v-if="localSharedEntity && users && groups"
+        v-model="localSharedEntity"
+        :users="users"
+        :groups="groups"
+        :parent-entity-owner="parentEntityOwner"
+        :parent-entity-label="parentEntityLabel"
+        :disallow-editing-admin-groups="disallowEditingAdminGroups"
+      />
+      <!-- Only show parent entity permissions for new entities -->
+      <template v-if="!entityId && hasParentSharedEntityPermissions">
+        <shared-entity-editor
+          v-if="parentSharedEntity && users && groups"
+          v-model="parentSharedEntity"
+          :users="users"
+          :groups="groups"
+          :readonly="true"
+          class="mt-5"
+        >
+          <span slot="permissions-header">Inherited {{ parentEntityLabel }} Permissions</span>
+        </shared-entity-editor>
+        <small class="text-muted">These permissions are inherited when your <span class="text-lowercase">{{ entityLabel
+            }}</span> is initially
+          created but can be updated
+          afterwards.</small>
+      </template>
     </b-modal>
   </div>
 </template>
@@ -20,6 +59,15 @@ export default {
   name: "share-button",
   props: {
     entityId: String,
+    parentEntityId: String,
+    parentEntityLabel: {
+      type: String,
+      default: "Parent"
+    },
+    entityLabel: {
+      type: String,
+      default: "Entity"
+    },
     sharedEntity: models.SharedEntity,
     autoAddDefaultGatewayUsersGroup: {
       type: Boolean,
@@ -36,6 +84,7 @@ export default {
   data: function() {
     return {
       localSharedEntity: null,
+      parentSharedEntity: null,
       sharedEntityCopy: null,
       defaultGatewayUsersGroup: null,
       users: null,
@@ -69,7 +118,9 @@ export default {
     },
     filteredGroupPermissions: function() {
       if (this.localSharedEntity && this.localSharedEntity.groupPermissions) {
-        return this.disallowEditingAdminGroups ? this.localSharedEntity.nonAdminGroupPermissions : this.localSharedEntity.groupPermissions;
+        return this.disallowEditingAdminGroups
+          ? this.localSharedEntity.nonAdminGroupPermissions
+          : this.localSharedEntity.groupPermissions;
       } else {
         return [];
       }
@@ -91,6 +142,16 @@ export default {
         this.localSharedEntity &&
         (!this.localSharedEntity.entityId || this.localSharedEntity.isOwner)
       );
+    },
+    hasParentSharedEntityPermissions() {
+      return (
+        this.parentSharedEntity &&
+        (this.parentSharedEntity.userPermissions.length > 0 ||
+          this.parentSharedEntity.groupPermissions.length > 0)
+      );
+    },
+    parentEntityOwner() {
+      return this.parentSharedEntity && this.parentSharedEntity.owner;
     }
   },
   methods: {
@@ -123,6 +184,13 @@ export default {
           })
         );
       }
+      if (this.parentEntityId) {
+        promises.push(
+          this.loadSharedEntity(this.parentEntityId).then(
+            sharedEntity => (this.parentSharedEntity = sharedEntity)
+          )
+        );
+      }
       Promise.all(promises).then(() => {
         if (this.sharedEntity) {
           this.localSharedEntity = this.sharedEntity.clone();
@@ -216,6 +284,11 @@ export default {
           sharedEntity => (this.localSharedEntity = sharedEntity)
         );
       }
+    },
+    parentEntityId(newParentEntityId) {
+      this.loadSharedEntity(newParentEntityId).then(sharedEntity => {
+        this.parentSharedEntity = sharedEntity;
+      });
     }
   }
 };
diff --git a/django_airavata/static/common/js/components/SharedEntityEditor.vue b/django_airavata/static/common/js/components/SharedEntityEditor.vue
index dcba2c7..be778ff 100644
--- a/django_airavata/static/common/js/components/SharedEntityEditor.vue
+++ b/django_airavata/static/common/js/components/SharedEntityEditor.vue
@@ -1,6 +1,7 @@
 <template>
   <div>
     <b-form-group
+      v-if="!readonly"
       label="Search for users/groups"
       labelFor="user-groups-autocomplete"
     >
@@ -24,40 +25,48 @@
         </template>
       </autocomplete-text-input>
     </b-form-group>
-    <h5 v-if="totalCount > 0">Currently Shared With</h5>
+    <h5 v-if="totalCount > 0">
+      <slot name="permissions-header">Currently Shared With</slot>
+    </h5>
     <b-table
       v-if="usersCount > 0"
       id="modal-user-table"
       hover
-      :items="sortedUserPermissions"
+      :items="sortedUserPermissionsData"
       :fields="userFields"
     >
       <template
         slot="name"
         slot-scope="data"
       >
-        <span :title="data.item.user.userId">{{data.item.user.firstName}} {{data.item.user.lastName}}</span>
+        <span :title="data.item.user.userId" :class="data.item.classes">{{data.item.user.firstName}} {{data.item.user.lastName}}</span>
       </template>
       <template
         slot="email"
         slot-scope="data"
       >
-        {{data.item.user.email}}
+        <span :class="data.item.classes">{{data.item.user.email}}</span>
       </template>
       <template
         slot="permission"
         slot-scope="data"
       >
         <b-form-select
+          v-if="!data.item.readonly"
           v-model="data.item.permissionType"
           :options="permissionOptions"
         />
+        <span
+          v-else
+          class="text-uppercase"
+          :class="data.item.classes"
+        >{{ data.item.permissionTypeLabel }}</span>
       </template>
       <template
         slot="remove"
         slot-scope="data"
       >
-        <b-link @click="removeUser(data.item.user)">
+        <b-link v-if="!data.item.readonly" @click="removeUser(data.item.user)">
           <span class="fa fa-trash"></span>
         </b-link>
       </template>
@@ -131,6 +140,17 @@ export default {
     disallowEditingAdminGroups: {
       type: Boolean,
       default: true
+    },
+    readonly: {
+      type: Boolean,
+      default: false
+    },
+    parentEntityOwner: {
+      type: models.UserProfile,
+    },
+    parentEntityLabel: {
+      type: String,
+      default: "Parent"
     }
   },
   components: {
@@ -157,14 +177,33 @@ export default {
         ? this.data.userPermissions.length
         : 0;
     },
-    sortedUserPermissions: function() {
+    sortedUserPermissionsData: function() {
       const userPermsCopy = this.data.userPermissions
         ? this.data.userPermissions.slice()
         : [];
-      return utils.StringUtils.sortIgnoreCase(
+      const sorted = utils.StringUtils.sortIgnoreCase(
         userPermsCopy,
         userPerm => userPerm.user.lastName + ", " + userPerm.user.firstName
       );
+      const sortedData = sorted.map(up => {
+        return {
+          user: up.user,
+          permissionType: up.permissionType,
+          permissionTypeLabel: up.permissionType.name,
+          readonly: this.readonly,
+          classes: this.readonly ? ['text-muted', 'font-italic'] : null
+        }
+      });
+      if (this.parentEntityOwner) {
+        sortedData.push({
+          user: this.parentEntityOwner,
+          permissionType: models.ResourcePermissionType.OWNER,
+          permissionTypeLabel: this.parentEntityLabel + " OWNER",
+          readonly: true,
+          classes: ['text-muted', 'font-italic']
+        });
+      }
+      return sortedData;
     },
     filteredGroupPermissions: function() {
       return this.data && this.data.groupPermissions
@@ -279,7 +318,7 @@ export default {
      * should not be allowed.
      */
     editingAllowed(group) {
-      return !this.disallowEditingAdminGroups || !group.isAdminGroup;
+      return !this.readonly && (!this.disallowEditingAdminGroups || !group.isAdminGroup);
     }
   }
 };