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 2020/04/14 21:39:24 UTC

[airavata-django-portal] branch develop updated: AIRAVATA-3320: AIRAVATA-3320 Check user has READ access to all GRP tokens

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

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


The following commit(s) were added to refs/heads/develop by this push:
     new 675d550  AIRAVATA-3320: AIRAVATA-3320 Check user has READ access to all GRP tokens
     new f2b3350  Merge branch 'AIRAVATA-3320-disallow-editing-grp-when-user-doesn-t-have-at-lea' into develop
675d550 is described below

commit 675d550ea97f306bda5273318c32de4923f7e196
Author: Marcus Christie <ma...@apache.org>
AuthorDate: Tue Apr 14 17:37:32 2020 -0400

    AIRAVATA-3320: AIRAVATA-3320 Check user has READ access to all GRP tokens
---
 .../ComputePreference.vue                          | 75 ++++++++++++++--------
 .../credentials/SSHCredentialSelector.vue          | 49 +++++++++++---
 .../gatewayprofile/StoragePreferenceEditor.vue     |  2 +-
 django_airavata/apps/api/serializers.py            | 14 +++-
 4 files changed, 100 insertions(+), 40 deletions(-)

diff --git a/django_airavata/apps/admin/static/django_airavata_admin/src/components/admin/group_resource_preferences/ComputePreference.vue b/django_airavata/apps/admin/static/django_airavata_admin/src/components/admin/group_resource_preferences/ComputePreference.vue
index 794a552..12f9923 100644
--- a/django_airavata/apps/admin/static/django_airavata_admin/src/components/admin/group_resource_preferences/ComputePreference.vue
+++ b/django_airavata/apps/admin/static/django_airavata_admin/src/components/admin/group_resource_preferences/ComputePreference.vue
@@ -7,10 +7,9 @@
             v-if="localGroupResourceProfile"
             class="group-resource-profile-name text-muted text-uppercase"
           >
-            <i
-              class="fa fa-server"
-              aria-hidden="true"
-            ></i> {{ localGroupResourceProfile.groupResourceProfileName }}</div>
+            <i class="fa fa-server" aria-hidden="true"></i>
+            {{ localGroupResourceProfile.groupResourceProfileName }}
+          </div>
           {{ computeResource.hostName }}
         </h1>
       </div>
@@ -22,7 +21,9 @@
             <b-form-group
               label="Login Username"
               label-for="login-username"
-              :invalid-feedback="validationFeedback.loginUserName.invalidFeedback"
+              :invalid-feedback="
+                validationFeedback.loginUserName.invalidFeedback
+              "
               :state="validationFeedback.loginUserName.state"
             >
               <b-form-input
@@ -42,16 +43,26 @@
               <ssh-credential-selector
                 v-model="data.resourceSpecificCredentialStoreToken"
                 v-if="localGroupResourceProfile"
-                :null-option-default-credential-token="localGroupResourceProfile.defaultCredentialStoreToken"
-                :null-option-disabled="!localGroupResourceProfile.defaultCredentialStoreToken"
+                :null-option-default-credential-token="
+                  localGroupResourceProfile.defaultCredentialStoreToken
+                "
+                :null-option-disabled="
+                  !localGroupResourceProfile.defaultCredentialStoreToken
+                "
               >
                 <template
                   slot="null-option-label"
                   slot-scope="nullOptionLabelScope"
                 >
                   <span v-if="nullOptionLabelScope.defaultCredentialSummary">
-                    Use the default SSH credential for {{ localGroupResourceProfile.groupResourceProfileName }} ({{
-                    nullOptionLabelScope.defaultCredentialSummary.description }})
+                    Use the default SSH credential for
+                    {{ localGroupResourceProfile.groupResourceProfileName }} ({{
+                      nullOptionLabelScope.defaultCredentialSummary.username
+                    }}
+                    -
+                    {{
+                      nullOptionLabelScope.defaultCredentialSummary.description
+                    }})
                   </span>
                   <span v-else>
                     Select a SSH credential
@@ -73,7 +84,9 @@
             <b-form-group
               label="Scratch Location"
               label-for="scratch-location"
-              :invalid-feedback="validationFeedback.scratchLocation.invalidFeedback"
+              :invalid-feedback="
+                validationFeedback.scratchLocation.invalidFeedback
+              "
               :state="validationFeedback.scratchLocation.state"
             >
               <b-form-input
@@ -104,15 +117,27 @@
                 :key="batchQueue.queueName"
               >
                 <b-form-checkbox
-                  :checked="localComputeResourcePolicy.allowedBatchQueues.includes(batchQueue.queueName)"
+                  :checked="
+                    localComputeResourcePolicy.allowedBatchQueues.includes(
+                      batchQueue.queueName
+                    )
+                  "
                   @input="batchQueueChecked(batchQueue, $event)"
                 >
                   {{ batchQueue.queueName }}
                 </b-form-checkbox>
                 <batch-queue-resource-policy
-                  v-if="localComputeResourcePolicy.allowedBatchQueues.includes(batchQueue.queueName)"
+                  v-if="
+                    localComputeResourcePolicy.allowedBatchQueues.includes(
+                      batchQueue.queueName
+                    )
+                  "
                   :batch-queue="batchQueue"
-                  :value="localBatchQueueResourcePolicies.find(pol => pol.queuename === batchQueue.queueName)"
+                  :value="
+                    localBatchQueueResourcePolicies.find(
+                      pol => pol.queuename === batchQueue.queueName
+                    )
+                  "
                   @input="updatedBatchQueueResourcePolicy(batchQueue, $event)"
                   @valid="recordValidBatchQueueResourcePolicy(batchQueue)"
                   @invalid="recordInvalidBatchQueueResourcePolicy(batchQueue)"
@@ -125,21 +150,15 @@
     </div>
     <div class="row">
       <div class="col d-flex justify-content-end">
-        <b-button
-          variant="primary"
-          @click="save"
-          :disabled="!valid"
-        >Save</b-button>
-        <b-button
-          class="ml-2"
-          variant="danger"
-          @click="remove"
-        >Delete</b-button>
-        <b-button
-          class="ml-2"
-          variant="secondary"
-          @click="cancel"
-        >Cancel</b-button>
+        <b-button variant="primary" @click="save" :disabled="!valid"
+          >Save</b-button
+        >
+        <b-button class="ml-2" variant="danger" @click="remove"
+          >Delete</b-button
+        >
+        <b-button class="ml-2" variant="secondary" @click="cancel"
+          >Cancel</b-button
+        >
       </div>
     </div>
   </div>
diff --git a/django_airavata/apps/admin/static/django_airavata_admin/src/components/credentials/SSHCredentialSelector.vue b/django_airavata/apps/admin/static/django_airavata_admin/src/components/credentials/SSHCredentialSelector.vue
index f4b9ca0..2042e23 100644
--- a/django_airavata/apps/admin/static/django_airavata_admin/src/components/credentials/SSHCredentialSelector.vue
+++ b/django_airavata/apps/admin/static/django_airavata_admin/src/components/credentials/SSHCredentialSelector.vue
@@ -1,11 +1,25 @@
 <template>
   <div>
     <b-input-group>
-      <b-form-select v-model="data" :options="credentialStoreTokenOptions" :disabled="readonly">
-        <option v-if="nullOption" slot="first" :value="null" :disabled="nullOptionDisabled">
-          <slot name="null-option-label" :defaultCredentialSummary="defaultCredentialSummary">
+      <b-form-select
+        v-model="data"
+        :options="credentialStoreTokenOptions"
+        :disabled="readonly"
+      >
+        <option
+          v-if="nullOption"
+          slot="first"
+          :value="null"
+          :disabled="nullOptionDisabled"
+        >
+          <slot
+            name="null-option-label"
+            :defaultCredentialSummary="defaultCredentialSummary"
+          >
             <span v-if="defaultCredentialSummary">
-              Use the default SSH credential ({{ defaultCredentialSummary.description }})
+              Use the default SSH credential ({{
+                createCredentialDescription(defaultCredentialSummary)
+              }})
             </span>
             <span v-else>
               Unset the default SSH credential
@@ -16,12 +30,19 @@
       <b-input-group-append>
         <clipboard-copy-button variant="secondary" :text="copySSHPublicKeyText">
         </clipboard-copy-button>
-        <b-button v-if="!readonly" variant="secondary" @click="showNewSSHCredentialModal">
+        <b-button
+          v-if="!readonly"
+          variant="secondary"
+          @click="showNewSSHCredentialModal"
+        >
           <i class="fa fa-plus"></i>
         </b-button>
       </b-input-group-append>
     </b-input-group>
-    <new-ssh-credential-modal ref="newSSHCredentialModal" @new="createSSHCredential" />
+    <new-ssh-credential-modal
+      ref="newSSHCredentialModal"
+      @new="createSSHCredential"
+    />
   </div>
 </template>
 
@@ -69,7 +90,7 @@ export default {
         ? this.credentials.map(summary => {
             return {
               value: summary.token,
-              text: summary.description ? summary.description : `No description (${summary.token})`
+              text: this.createCredentialDescription(summary)
             };
           })
         : [];
@@ -94,8 +115,8 @@ export default {
       return this.selectedCredential
         ? this.selectedCredential.publicKey.trim()
         : this.defaultCredentialSummary
-          ? this.defaultCredentialSummary.publicKey.trim()
-          : null;
+        ? this.defaultCredentialSummary.publicKey.trim()
+        : null;
     }
   },
   methods: {
@@ -107,6 +128,15 @@ export default {
         this.credentials.push(cred);
         this.data = cred.token;
       });
+    },
+    createCredentialDescription(summary) {
+      return (
+        summary.username +
+        " - " +
+        (summary.description
+          ? summary.description
+          : `No description (${summary.token})`)
+      );
     }
   },
   created() {
@@ -118,4 +148,3 @@ export default {
   }
 };
 </script>
-
diff --git a/django_airavata/apps/admin/static/django_airavata_admin/src/components/gatewayprofile/StoragePreferenceEditor.vue b/django_airavata/apps/admin/static/django_airavata_admin/src/components/gatewayprofile/StoragePreferenceEditor.vue
index 53edfad..f3a79ae 100644
--- a/django_airavata/apps/admin/static/django_airavata_admin/src/components/gatewayprofile/StoragePreferenceEditor.vue
+++ b/django_airavata/apps/admin/static/django_airavata_admin/src/components/gatewayprofile/StoragePreferenceEditor.vue
@@ -11,7 +11,7 @@
         :null-option-default-credential-token="defaultCredentialStoreToken" :null-option-disabled="!defaultCredentialStoreToken">
         <template slot="null-option-label" slot-scope="nullOptionLabelScope">
           <span v-if="nullOptionLabelScope.defaultCredentialSummary">
-            Use the gateway's default SSH credential ({{ nullOptionLabelScope.defaultCredentialSummary.description }})
+            Use the gateway's default SSH credential ({{nullOptionLabelScope.defaultCredentialSummary.username}} - {{ nullOptionLabelScope.defaultCredentialSummary.description }})
           </span>
           <span v-else>
             Select a SSH credential
diff --git a/django_airavata/apps/api/serializers.py b/django_airavata/apps/api/serializers.py
index 58b1470..05af856 100644
--- a/django_airavata/apps/api/serializers.py
+++ b/django_airavata/apps/api/serializers.py
@@ -625,9 +625,21 @@ class GroupResourceProfileSerializer(
 
     def get_userHasWriteAccess(self, groupResourceProfile):
         request = self.context['request']
-        return request.airavata_client.userHasAccess(
+        write_access = request.airavata_client.userHasAccess(
             request.authz_token, groupResourceProfile.groupResourceProfileId,
             ResourcePermissionType.WRITE)
+        if not write_access:
+            return False
+        # Check that user has READ access to all tokens in this
+        # GroupResourceProfile
+        tokens = set([groupResourceProfile.defaultCredentialStoreToken] +
+                     [cp.resourceSpecificCredentialStoreToken
+                      for cp in groupResourceProfile.computePreferences])
+
+        def check_token(token):
+            return token is None or request.airavata_client.userHasAccess(
+                request.authz_token, token, ResourcePermissionType.READ)
+        return all(map(check_token, tokens))
 
 
 class UserPermissionSerializer(serializers.Serializer):