Explorar o código

HUE-8983 [fb] Handle s3 with ListAllMyBuckets denied

When you don't have ListAllMyBuckets permission a message is now
displayed and the breadcrumbs path is focused.
Jean-Francois Desjeans Gauthier %!s(int64=6) %!d(string=hai) anos
pai
achega
03916b59be

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 0 - 0
apps/filebrowser/src/filebrowser/static/filebrowser/css/listdir_components.css


+ 0 - 4
apps/filebrowser/src/filebrowser/static/filebrowser/less/listdir_components.less

@@ -246,9 +246,5 @@
   margin-bottom: 3px;
   padding-left: 14px;
   border-radius: 2px;
-  border: 1px solid @cui-gray-050;
-  -webkit-box-shadow: none;
-  -moz-box-shadow: none;
-  box-shadow: none;
   font-weight: bold;
 }

+ 2 - 0
apps/filebrowser/src/filebrowser/templates/listdir.mako

@@ -197,6 +197,8 @@ ${ fb_components.menubar() }
       <div class="alert alert-warn" data-bind="visible: ! isCurrentDirSentryManaged() && selectedSentryFiles().length > 0">
         ${ _('The permissions of some of the selected files are managed by the Sentry Namenode plugin.') }
       </div>
+      <div class="alert alert-warn" data-bind="visible: errorMessage(), text: errorMessage">
+      </div>
 
       % if breadcrumbs:
         ${fb_components.breadcrumbs(path, breadcrumbs, True)}

+ 18 - 7
apps/filebrowser/src/filebrowser/templates/listdir_components.mako

@@ -938,6 +938,7 @@ from filebrowser.conf import ENABLE_EXTRACT_UPLOADED_ARCHIVE
       self.skipTrash = ko.observable(false);
       self.enableFilterAfterSearch = true;
       self.isCurrentDirSentryManaged = ko.observable(false);
+      self.errorMessage = ko.observable("");
       self.pendingUploads = ko.observable(0);
       self.pendingUploads.subscribe(function (val) {
         if (val > 0) {
@@ -1188,24 +1189,34 @@ from filebrowser.conf import ENABLE_EXTRACT_UPLOADED_ARCHIVE
             return false;
           }
 
-          self.updateFileList(data.files, data.page, data.breadcrumbs, data.current_dir_path, data.is_sentry_managed);
+          self.updateFileList(data.files, data.page, data.breadcrumbs, data.current_dir_path, data.is_sentry_managed, data.s3_listing_not_allowed);
 
           if (clearAssistCache) {
             huePubSub.publish('assist.'+self.fs()+'.refresh');
           }
-
-          if ($("#hueBreadcrumbText").is(":visible")) {
-            $(".hue-breadcrumbs").show();
-            $("#hueBreadcrumbText").hide();
-            $("#editBreadcrumb").show();
+          if (data.s3_listing_not_allowed) {
+            if (!$("#hueBreadcrumbText").is(":visible")) {
+              $(".hue-breadcrumbs").hide();
+              $("#hueBreadcrumbText").show();
+              $("#editBreadcrumb").hide();
+            }
+            $("#hueBreadcrumbText").focus();
+          } else {
+            if ($("#hueBreadcrumbText").is(":visible")) {
+              $(".hue-breadcrumbs").show();
+              $("#hueBreadcrumbText").hide();
+              $("#editBreadcrumb").show();
+            }
           }
+
         });
       };
 
-      self.updateFileList = function (files, page, breadcrumbs, currentDirPath, isSentryManaged) {
+      self.updateFileList = function (files, page, breadcrumbs, currentDirPath, isSentryManaged, s3_listing_not_allowed) {
         $(".tooltip").hide();
 
         self.isCurrentDirSentryManaged(isSentryManaged);
+        self.errorMessage(s3_listing_not_allowed);
 
         self.page(new Page(page));
         self.files(ko.utils.arrayMap(files, function (file) {

+ 11 - 5
apps/filebrowser/src/filebrowser/views.py

@@ -49,7 +49,7 @@ from django.utils.http import http_date
 from django.utils.html import escape
 from django.utils.translation import ugettext as _
 
-from aws.s3.s3fs import S3FileSystemException
+from aws.s3.s3fs import S3FileSystemException, S3ListAllBucketsException
 from avro import datafile, io
 from desktop import appmanager
 from desktop.lib import i18n
@@ -461,11 +461,16 @@ def listdir_paged(request, path):
     else:
       home_dir_path = None
     breadcrumbs = parse_breadcrumbs(path)
+    s3_listing_not_allowed = ''
 
-    if do_as:
-      all_stats = request.fs.do_as_user(do_as, request.fs.listdir_stats, path)
-    else:
-      all_stats = request.fs.listdir_stats(path)
+    try:
+      if do_as:
+        all_stats = request.fs.do_as_user(do_as, request.fs.listdir_stats, path)
+      else:
+        all_stats = request.fs.listdir_stats(path)
+    except S3ListAllBucketsException as e:
+      s3_listing_not_allowed = e.message
+      all_stats = []
 
 
     # Filter first
@@ -546,6 +551,7 @@ def listdir_paged(request, path):
         'show_download_button': SHOW_DOWNLOAD_BUTTON.get(),
         'show_upload_button': SHOW_UPLOAD_BUTTON.get(),
         'is_embeddable': request.GET.get('is_embeddable', False),
+        's3_listing_not_allowed': s3_listing_not_allowed
     }
     return render('listdir.mako', request, data)
 

+ 13 - 0
desktop/core/src/desktop/js/jquery/plugins/jquery.filechooser.js

@@ -574,6 +574,19 @@ Plugin.prototype.navigateTo = function(path) {
         }
       }, 100);
 
+      if (data.s3_listing_not_allowed) {
+        $("<div class='clearfix'>").appendTo($(_parent.element).find('.filechooser-tree'));
+        const _errorMsg = $('<div>')
+          .addClass('alert')
+          .addClass('alert-warn')
+          .text(data.s3_listing_not_allowed);
+        _errorMsg.appendTo($(_parent.element).find('.filechooser-tree'));
+
+        $scrollingBreadcrumbs.hide();
+        $hdfsAutocomplete.show();
+        $hdfsAutocomplete.focus();
+      }
+
       $(data.files).each((cnt, file) => {
         let _addFile = file.name !== '.';
         if (_parent.options.filterExtensions != '' && file.type == 'file') {

+ 2 - 0
desktop/core/src/desktop/js/ko/components/assist/assistStorageEntry.js

@@ -154,6 +154,8 @@ class AssistStorageEntry {
         );
         self.loaded = true;
         self.loading(false);
+        self.hasErrors(!!data.s3_listing_not_allowed); // Special case where we want errors inline instead of the default popover. We don't want errorCallback handling
+        self.errorText(data.s3_listing_not_allowed);
         if (callback) {
           callback();
         }

+ 4 - 3
desktop/core/src/desktop/js/ko/components/assist/ko.assistStoragePanel.js

@@ -164,9 +164,10 @@ const TEMPLATE = `
       <!-- /ko -->
     </div>
     <!-- ko hueSpinner: { spin: loading, center: true, size: 'large' } --><!-- /ko -->
-    <div class="assist-errors" data-bind="visible: ! loading() && hasErrors()">
-      <span>${I18n('Error loading contents.')}</span>
-    </div>
+    <span class="assist-errors" data-bind="visible: ! loading() && hasErrors(), text: errorText() || '${I18n(
+      'Error loading contents.'
+    )}'">
+    </span>
   </div>
   <!-- /ko -->
   <!-- /ko -->

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 0 - 0
desktop/core/src/desktop/static/desktop/css/hue.css


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 0 - 0
desktop/core/src/desktop/static/desktop/css/hue3-extra.css


+ 0 - 1
desktop/core/src/desktop/static/desktop/js/document/hueFileEntry.js

@@ -206,7 +206,6 @@ var HueFileEntry = (function () {
     self.loaded = ko.observable(false);
     self.loading = ko.observable(false);
     self.hasErrors = ko.observable(false);
-
     self.uploading = ko.observable(false);
     self.uploadComplete = ko.observable(false);
     self.uploadFailed = ko.observable(false);

+ 1 - 0
desktop/core/src/desktop/static/desktop/less/hue-assist.less

@@ -283,6 +283,7 @@
 .assist-errors {
   padding: 4px 5px;
   font-style: italic;
+  white-space: normal;
 }
 
 .assist-tables > li {

+ 9 - 4
desktop/libs/aws/src/aws/s3/s3fs.py

@@ -46,10 +46,12 @@ LOG = logging.getLogger(__name__)
 
 
 class S3FileSystemException(IOError):
-
   def __init__(self, *args, **kwargs):
     super(S3FileSystemException, self).__init__(*args, **kwargs)
 
+class S3ListAllBucketsException(S3FileSystemException):
+  def __init__(self, *args, **kwargs):
+    super(S3FileSystemException, self).__init__(*args, **kwargs)
 
 def auth_error_handler(view_fn):
   def decorator(*args, **kwargs):
@@ -203,8 +205,8 @@ class S3FileSystem(object):
 
   @staticmethod
   def isroot(path):
-    parsed = urlparse(path) 
-    return parsed.path == '/' or parsed.path == ''
+    parsed = urlparse(path)
+    return (parsed.path == '/' or parsed.path == '') and parsed.netloc == ''
 
   @staticmethod
   def join(*comp_list):
@@ -280,7 +282,10 @@ class S3FileSystem(object):
       except S3FileSystemException as e:
         raise e
       except S3ResponseError as e:
-        raise S3FileSystemException(_('Failed to retrieve buckets: %s') % e.reason)
+        if 'Forbidden' in str(e) or (hasattr(e, 'status') and e.status == 403):
+          raise S3ListAllBucketsException(_('You do not have permissions to list all buckets. Please specify a bucket name you have access to.'))
+        else:
+          raise S3FileSystemException(_('Failed to retrieve buckets: %s') % e.reason)
       except Exception as e:
         raise S3FileSystemException(_('Failed to retrieve buckets: %s') % e)
 

Algúns arquivos non se mostraron porque demasiados arquivos cambiaron neste cambio