Эх сурвалжийг харах

HUE-1624 [hbase] Configurable write permissions

Add write switch.
Remove Bulk upload, new row, add column, and edit cell when canWrite is false.
Also remove add table functionality when canWrite is false.
Abraham Elmahrek 11 жил өмнө
parent
commit
579543d7d6

+ 4 - 0
apps/hbase/src/hbase/settings.py

@@ -20,3 +20,7 @@ ICON = '/hbase/static/art/icon_24.png'
 
 REQUIRES_HADOOP = False
 IS_URL_NAMESPACED = True
+
+PERMISSION_ACTIONS = (
+  ("write", "Allow writing in the HBase app."),
+)

+ 9 - 1
apps/hbase/src/hbase/templates/app.mako

@@ -89,7 +89,9 @@ ${ commonheader(None, "hbase", user) | n,unicode }
           % if user.is_superuser:
             <button class="btn" data-bind="enable: $data.selected().length > 0, click: $data.dropSelected, clickBubble: false"><i class="fa fa-trash-o"></i> Drop Columns</button>
           % endif
+          % if can_write:
           <a href="#new_column_modal" data-bind="click:function(){app.focusModel($data);launchModal('new_column_modal', $data);}" class="btn" title="${_('Add New Column/Cell')}"><i class="fa fa-plus"></i></a>
+          % endif
         </span>
       </h5>
       <ul class="smartview-cells" data-bind="event: {scroll: onScroll}">
@@ -102,7 +104,7 @@ ${ commonheader(None, "hbase", user) | n,unicode }
               <a class="corner-btn btn" data-bind="click: $data.drop, clickBubble: false"><i class="fa fa-trash-o"></i></a>
             % endif
             <a class="corner-btn btn" data-bind="visible: $data.editing(), event: { mousedown: function(){launchModal('cell_edit_modal',{content:$data, mime: detectMimeType($data.value())})} }"><i class="fa fa-pencil"></i> ${_('Full Editor')}</a>
-            <pre data-bind="text: ($data.value().length > 146 ? $data.value().substring(0, 144)+'...' : $data.value()).replace(/(\r\n|\n|\r)/gm,''), click: $data.value().length > 146 ? function(){launchModal('cell_edit_modal',{content:$data, mime: detectMimeType($data.value())})} : function(){$data.editing(true)}, clickBubble: false, visible: !$data.isLoading() && !$data.editing()"></pre>
+            <pre data-bind="text: ($data.value().length > 146 ? $data.value().substring(0, 144)+'...' : $data.value()).replace(/(\r\n|\n|\r)/gm,''), click: editCell($data), clickBubble: false, visible: !$data.isLoading() && !$data.editing()"></pre>
             <textarea data-bind="visible: !$data.isLoading() && $data.editing(), hasfocus: $data.editing, value: $data.value, click:function(){}, clickBubble: false"></textarea>
             <img src="/static/art/spinner.gif" data-bind="visible: $data.isLoading() " />
           </div>
@@ -171,9 +173,11 @@ ${ commonheader(None, "hbase", user) | n,unicode }
           </span>
           <button class="btn" data-bind="enable: views.tables.selected().length > 0, click: views.tables.dropSelected"><i class="fa fa-trash-o"></i> ${_('Drop')}</button>
         % endif
+        % if can_write:
         <span class="pull-right">
           <a href="#new_table_modal" role="button" data-bind="click: function(){app.focusModel(app.views.tables);}" class="btn" data-toggle="modal"><i class='fa fa-plus-circle'></i> ${_('New Table')}</a>
         </span>
+        % endif
       </div>
     </div>
 
@@ -278,8 +282,10 @@ ${ commonheader(None, "hbase", user) | n,unicode }
             % if user.is_superuser:
               <a class="btn" data-bind="enable: views.tabledata.selected().length > 0, click: views.tabledata.dropSelected"><i class="fa fa-trash-o"></i> ${_('Drop Rows')}</a>
             % endif
+            % if can_write:
             <a id="bulk-upload-btn" class="btn fileChooserBtn" data-toggle="tooltip" title="${_('.CSV, .TSV, etc...')}" aria-hidden="true"><i class="fa fa-upload"></i> ${_('Bulk Upload')}</a>
             <a href="#new_row_modal" data-bind="click:function(){app.focusModel(app.views.tabledata);launchModal('new_row_modal')}" role="button" class="btn btn-primary" data-callback=""><i class='fa fa-plus-circle'></i> ${_('New Row')}</a>
+            % endif
           </span>
         </div>
     </div>
@@ -442,6 +448,8 @@ function i18n(text) {
     return i18n_cache[text];
   return text;
 };
+
+canWrite = ${ str(can_write).lower() };
 </script>
 <script src="/static/ext/js/datatables-paging-0.1.js" type="text/javascript" charset="utf-8"></script>
 <script src="/static/ext/js/knockout-min.js" type="text/javascript" charset="utf-8"></script>

+ 8 - 3
apps/hbase/src/hbase/views.py

@@ -23,15 +23,15 @@ import re
 import StringIO
 import urllib
 
-from avro import schema, datafile, io
+from avro import datafile, io
 
-from django.core.urlresolvers import reverse
 from django.http import HttpResponse
 from django.utils.translation import ugettext as _
 
 from desktop.lib.django_util import render
 
 from hbase import conf
+from hbase.settings import DJANGO_APPS
 from hbase.api import HbaseApi
 from hbase.management.commands import hbase_setup
 from server.hbase_lib import get_thrift_type
@@ -39,8 +39,13 @@ from server.hbase_lib import get_thrift_type
 LOG = logging.getLogger(__name__)
 
 
+def has_write_access(user):
+  return user.is_superuser or user.has_hue_permission(action="write", app=DJANGO_APPS[0])
+
 def app(request):
-  return render('app.mako', request, {})
+  return render('app.mako', request, {
+    'can_write': has_write_access(request.user)
+  })
 
 # action/cluster/arg1/arg2/arg3...
 def api_router(request, url): # On split, deserialize anything

+ 2 - 2
apps/hbase/static/js/app.js

@@ -49,7 +49,7 @@ var AppViewModel = function() {
           callback();
       });
     }}),
-    tabledata: new SmartViewModel({el: 'views.tabledata', reload: function(callback) //move inside SmartViewModel class?
+    tabledata: new SmartViewModel({'canWrite': canWrite, el: 'views.tabledata', reload: function(callback) //move inside SmartViewModel class?
     {
       var t_self = this;
       function getColumnFamilies() {
@@ -67,7 +67,7 @@ var AppViewModel = function() {
           var keys = Object.keys(data);
           var items = [];
           for(var i=0; i<keys.length; i++) {
-            var row = new SmartViewDataRow({items: [], row:data[keys[i]].row, reload: function(options) {
+            var row = new SmartViewDataRow({'canWrite': canWrite, items: [], row:data[keys[i]].row, reload: function(options) {
               var self = this;
               options = (options == null) ? {} : options;
               options = ko.utils.extend({

+ 1 - 0
apps/hbase/static/js/base.js

@@ -28,6 +28,7 @@ var ListViewModel = function(options) {
   options = ko.utils.extend(_defaults,options);
   BaseModel.apply(this,[options]);
 
+  self.canWrite = ko.observable(options.canWrite);
   self.items = ko.observableArray(options.items);
   self.sortDropDown = new SortDropDownView({sortFields: options.sortFields, target: self.items});
   self.selectAll = function(){

+ 4 - 2
apps/hbase/static/js/controls.js

@@ -157,7 +157,8 @@ var SmartViewModel = function(options) {
           return -1;
         return 0;
       }
-    }
+    },
+    canWrite: false
   }, options);
   ListViewModel.apply(this, [options]); //items: [ListView.items[],ListView.items[]]
 
@@ -413,7 +414,8 @@ var SmartViewDataRow = function(options) {
           return -1;
         return 0;
       }
-    }
+    },
+    canWrite: false
   }, options);
   DataRow.apply(self,[options]);
   ListViewModel.apply(self,[options]);

+ 13 - 0
apps/hbase/static/js/utils.js

@@ -154,6 +154,19 @@ function launchModal(modal, data) {
   logGA(modal.slice(0, modal.indexOf('_modal') != -1 ? modal.indexOf('_modal') : modal.length));
 }
 
+function editCell($data) {
+  if ($data.parent.canWrite()) {
+    if ($data.value().length > 146) {
+      launchModal('cell_edit_modal',{
+        content: $data,
+        mime: detectMimeType($data.value())
+      });
+    } else {
+      $data.editing(true);
+    }
+  }
+}
+
 function parseXML(xml) {
   var parser, xmlDoc;
   if (window.DOMParser) {

+ 2 - 1
apps/useradmin/src/useradmin/models.py

@@ -263,7 +263,8 @@ def update_app_permissions(**kwargs):
     if default_group:
       for new_dp in added:
         if not (new_dp.app == 'useradmin' and new_dp.action == 'access') and \
-           not (new_dp.app == 'metastore' and new_dp.action == 'read_only_access'):
+           not (new_dp.app == 'metastore' and new_dp.action == 'read_only_access') and \
+           not (new_dp.app == 'hbase' and new_dp.action == 'write'):
           GroupPermission.objects.create(group=default_group, hue_permission=new_dp)
 
     available = HuePermission.objects.count()