Jelajahi Sumber

[oozie] Check read and write permissions for bundles

Romain Rigaux 11 tahun lalu
induk
melakukan
d46c14f

+ 4 - 0
apps/oozie/src/oozie/decorators.py

@@ -46,6 +46,8 @@ def check_document_access_permission():
           doc_id['uuid'] = request.GET.get('uuid')
         elif request.GET.get('coordinator'):
           doc_id['id'] = request.GET.get('coordinator')
+        elif request.GET.get('bundle'):
+          doc_id['id'] = request.GET.get('bundle')          
         elif 'doc_id' in kwargs:
           doc_id['id'] = kwargs['doc_id']
 
@@ -68,6 +70,8 @@ def check_document_modify_permission():
       job = json.loads(request.POST.get('workflow', '{}'))
       if not job:
         job = json.loads(request.POST.get('coordinator', '{}'))
+      elif not job:
+        job = json.loads(request.POST.get('bundle', '{}'))
 
       if job and job.get('id'):
         doc_id = job.get('id')

+ 2 - 2
apps/oozie/src/oozie/models2.py

@@ -1513,7 +1513,7 @@ class Dataset():
     if type(self._data['start']) == unicode: 
       self._data['start'] = parse(self._data['start'])
 
-    self._data['name'] = self._data['workflow_variable'] # Todo Harmonize name for Oozie XML
+    self._data['name'] = self._data['workflow_variable']
 
     return self._data      
       
@@ -1614,7 +1614,7 @@ class Bundle(Job):
     if mapping is None:
       mapping = {}
 
-    mapping.update(dict(list(Document2.objects.filter(type='oozie-coordinator2', uuid__in=self.data['coordinators']).values('uuid', 'name')))) # TODO perms
+    mapping.update(dict(list(Document2.objects.filter(type='oozie-coordinator2', uuid__in=self.data['coordinators']).values('uuid', 'name'))))
     tmpl = "editor/gen2/bundle.xml.mako"
     return force_unicode(
               re.sub(re.compile('\s*\n+', re.MULTILINE), '\n', django_mako.render_to_string(tmpl, {

+ 44 - 21
apps/oozie/src/oozie/templates/editor/bundle_editor.mako

@@ -14,7 +14,7 @@
 ## See the License for the specific language governing permissions and
 ## limitations under the License.
 <%!
-from desktop.views import commonheader, commonfooter
+from desktop.views import commonheader, commonfooter, commonshare
 from django.utils.translation import ugettext as _
 %>
 
@@ -31,32 +31,45 @@ ${ commonheader(_("Bundle Editor"), "Oozie", user) | n,unicode }
 </script>
 
 
+<div id="editor">
+
 
 <div class="search-bar">
   <div class="pull-right" style="padding-right:50px">
-    <a title="${ _('Submit') }" rel="tooltip" data-placement="bottom" data-bind="click: showSubmitPopup, css: {'btn': true}">
+    <a title="${ _('Submit') }" rel="tooltip" data-placement="bottom" data-bind="click: showSubmitPopup, css: {'btn': true}, visible: bundle.id() != null">
       <i class="fa fa-play"></i>
     </a>
-    <a title="${ _('Edit') }" rel="tooltip" data-placement="bottom" data-bind="click: toggleEditing, css: {'btn': true, 'btn-inverse': isEditing}">
+    <a title="${ _('Edit') }" rel="tooltip" data-placement="bottom" data-bind="click: toggleEditing, css: {'btn': true, 'btn-inverse': isEditing}, visible: canEdit">
       <i class="fa fa-pencil"></i>
     </a>
+
     &nbsp;&nbsp;&nbsp;
-    % if user.is_superuser:
-      <button type="button" title="${ _('Settings') }" rel="tooltip" data-placement="bottom" data-toggle="modal" data-target="#settingsModal" data-bind="css: {'btn': true}">
-        <i class="fa fa-cog"></i>
-      </button>
-      &nbsp;&nbsp;&nbsp;
-      <button type="button" title="${ _('Save') }" rel="tooltip" data-placement="bottom" data-loading-text="${ _("Saving...") }" data-bind="click: $root.save, css: {'btn': true}">
-        <i class="fa fa-save"></i>
-      </button>
-      &nbsp;&nbsp;&nbsp;
-      <a class="btn" href="${ url('oozie:new_bundle') }" title="${ _('New') }" rel="tooltip" data-placement="bottom" data-bind="css: {'btn': true}">
-        <i class="fa fa-file-o"></i>
-      </a>
-      <a class="btn" href="${ url('oozie:list_editor_bundles') }" title="${ _('Bundles') }" rel="tooltip" data-placement="bottom" data-bind="css: {'btn': true}">
-        <i class="fa fa-tags"></i>
-      </a>
-    % endif
+
+    <button type="button" title="${ _('Settings') }" rel="tooltip" data-placement="bottom" data-toggle="modal" data-target="#settingsModal" data-bind="css: {'btn': true}, visible: canEdit">
+      <i class="fa fa-cog"></i>
+    </button>
+
+    &nbsp;&nbsp;&nbsp;
+
+    <button type="button" title="${ _('Save') }" rel="tooltip" data-placement="bottom" data-loading-text="${ _("Saving...") }" data-bind="click: $root.save, css: {'btn': true}, visible: canEdit">
+      <i class="fa fa-save"></i>
+    </button>
+
+    <a class="share-link btn" rel="tooltip" data-placement="bottom" data-bind="click: openShareModal,
+        attr: {'data-original-title': '${ _("Share") } ' + name},
+        css: {'isShared': isShared(), 'btn': true},
+        visible: bundle.id() != null && canEdit()">
+      <i class="fa fa-users"></i>
+    </a>
+
+    &nbsp;&nbsp;&nbsp;
+
+    <a class="btn" href="${ url('oozie:new_bundle') }" title="${ _('New') }" rel="tooltip" data-placement="bottom" data-bind="css: {'btn': true}">
+      <i class="fa fa-file-o"></i>
+    </a>
+    <a class="btn" href="${ url('oozie:list_editor_bundles') }" title="${ _('Bundles') }" rel="tooltip" data-placement="bottom" data-bind="css: {'btn': true}">
+      <i class="fa fa-tags"></i>
+    </a>
   </div>
 
   <form class="form-search">
@@ -159,6 +172,10 @@ ${ commonheader(_("Bundle Editor"), "Oozie", user) | n,unicode }
 
 <div id="submit-modal" class="modal hide"></div>
 
+
+</div>
+
+
 <div id="exposeOverlay"></div>
 
 <link rel="stylesheet" href="/static/ext/css/hue-filetypes.css">
@@ -169,10 +186,13 @@ ${ commonheader(_("Bundle Editor"), "Oozie", user) | n,unicode }
 
 ${ dashboard.import_layout() }
 
+${ commonshare() | n,unicode }
+
 <script src="/static/ext/js/bootstrap-editable.min.js" type="text/javascript" charset="utf-8"></script>
 <script src="/static/js/hue.utils.js"></script>
 <script src="/static/js/ko.editable.js" type="text/javascript" charset="utf-8"></script>
 <script src="/static/ext/chosen/chosen.jquery.min.js" type="text/javascript" charset="utf-8"></script>
+<script src="/static/js/share.vm.js"></script>
 
 ${ dashboard.import_bindings() }
 
@@ -180,8 +200,11 @@ ${ dashboard.import_bindings() }
 
 
 <script type="text/javascript">
-  var viewModel = new BundleEditorViewModel(${ bundle_json | n,unicode }, ${ coordinators_json | n,unicode });
-  ko.applyBindings(viewModel);
+  var viewModel = new BundleEditorViewModel(${ bundle_json | n,unicode }, ${ coordinators_json | n,unicode }, ${ can_edit_json | n,unicode });
+  ko.applyBindings(viewModel, $("#editor")[0]);
+
+  var shareViewModel = setupSharing("#documentShareModal");
+  shareViewModel.setDocId(${ doc1_id });
 
   var tempCoordinator = null;
   function showChooseCoordinator(coord) {

+ 21 - 6
apps/oozie/src/oozie/views/editor2.py

@@ -341,6 +341,8 @@ def save_coordinator(request):
 
   if coordinator_data['properties']['workflow']:
     dependencies = Document2.objects.filter(type='oozie-workflow2', uuid=coordinator_data['properties']['workflow'])
+    for doc in dependencies:
+      doc.doc.get().can_read_or_exception(request.user)
     coordinator_doc.dependencies = dependencies
 
   coordinator_doc.update_data(coordinator_data)
@@ -415,24 +417,32 @@ def _submit_coordinator(request, coordinator, mapping):
     
 
 def list_editor_bundles(request):
-  bundles = Document2.objects.filter(type='oozie-bundle2', owner=request.user)
+  bundles = [d.content_object for d in Document.objects.get_docs(request.user, Document2, extra='bundle2')]
 
   return render('editor/list_editor_bundles.mako', request, {
       'bundles': bundles
   })
 
 
+@check_document_access_permission()
 def edit_bundle(request):
   bundle_id = request.GET.get('bundle')
+  doc = None
   
   if bundle_id:
-    bundle = Bundle(document=Document2.objects.get(id=bundle_id)) # Todo perms
+    doc = Document2.objects.get(id=bundle_id)
+    bundle = Bundle(document=doc)
   else:
     bundle = Bundle()
 
+  coordinators = [dict([('uuid', d.content_object.uuid), ('name', d.content_object.name)])
+                      for d in Document.objects.get_docs(request.user, Document2, extra='coordinator2')]
+
   return render('editor/bundle_editor.mako', request, {
       'bundle_json': bundle.json,
-      'coordinators_json': json.dumps(list(Document2.objects.filter(type='oozie-coordinator2', owner=request.user).values('uuid', 'name'))) # Todo perms
+      'coordinators_json': json.dumps(coordinators),
+      'doc1_id': doc.doc.get().id if doc else -1,
+      'can_edit_json': json.dumps(doc is None or doc.doc.get().is_editable(request.user))      
   })
 
 
@@ -440,18 +450,22 @@ def new_bundle(request):
   return edit_bundle(request)
 
 
+@check_document_modify_permission()
 def save_bundle(request):
   response = {'status': -1}
 
-  bundle_data = json.loads(request.POST.get('bundle', '{}')) # TODO perms
+  bundle_data = json.loads(request.POST.get('bundle', '{}'))
 
   if bundle_data.get('id'):
     bundle_doc = Document2.objects.get(id=bundle_data['id'])
   else:      
     bundle_doc = Document2.objects.create(name=bundle_data['name'], uuid=bundle_data['uuid'], type='oozie-bundle2', owner=request.user)
+    Document.objects.link(bundle_doc, owner=bundle_doc.owner, name=bundle_doc.name, description=bundle_doc.description, extra='bundle2')
 
   if bundle_data['coordinators']:
-    dependencies = Document2.objects.filter(type='oozie-coordinator2', uuid__in=[c['coordinator'] for c in bundle_data['coordinators']]) # TODO perms
+    dependencies = Document2.objects.filter(type='oozie-coordinator2', uuid__in=[c['coordinator'] for c in bundle_data['coordinators']])
+    for doc in dependencies:
+      doc.doc.get().can_read_or_exception(request.user)    
     bundle_doc.dependencies = dependencies
 
   bundle_doc.update_data(bundle_data)
@@ -465,8 +479,9 @@ def save_bundle(request):
   return HttpResponse(json.dumps(response), mimetype="application/json")
 
 
+@check_document_access_permission()
 def submit_bundle(request, doc_id):
-  bundle = Bundle(document=Document2.objects.get(id=doc_id)) # Todo perms  
+  bundle = Bundle(document=Document2.objects.get(id=doc_id))  
   ParametersFormSet = formset_factory(ParameterForm, extra=0)
 
   if request.method == 'POST':

+ 3 - 2
apps/oozie/static/js/bundle-editor.ko.js

@@ -37,10 +37,11 @@ var Bundle = function (vm, bundle) {
 }
 
 
-var BundleEditorViewModel = function (bundle_json, coordinators_json) {
+var BundleEditorViewModel = function (bundle_json, coordinators_json, can_edit_json) {
   var self = this;
 
-  self.isEditing = ko.observable(true);
+  self.canEdit = ko.mapping.fromJS(can_edit_json);
+  self.isEditing = ko.observable(true && self.canEdit());
   self.isEditing.subscribe(function(newVal){
     $(document).trigger("editingToggled");
   });

+ 4 - 2
desktop/core/src/desktop/models.py

@@ -638,7 +638,9 @@ class Document2(models.Model):
     self.data = json.dumps(data_dict)
 
   def get_absolute_url(self):
-    if self.type == 'oozie-workflow2':
-      return reverse('oozie:edit_workflow') + '?workflow=' + str(self.id)
+    if self.type == 'oozie-coordinator2':
+      return reverse('oozie:edit_coordinator') + '?coordinator=' + str(self.id)
+    elif self.type == 'oozie-bundle2':
+      return reverse('oozie:edit_bundle') + '?bundle=' + str(self.id)    
     else:
       return reverse('oozie:edit_workflow') + '?workflow=' + str(self.id)