Browse Source

HUE-93. The chown form of filebrowser contains useless fields

Aaron T. Myers 15 years ago
parent
commit
bfd0e35f89

+ 33 - 12
apps/filebrowser/src/filebrowser/templates/chown.mako

@@ -18,8 +18,13 @@
 ${comps.header('Change Owner / Group: ' + path.split('/')[-1])}
 ${comps.header('Change Owner / Group: ' + path.split('/')[-1])}
 <%! from desktop.lib.django_util import extract_field_data %>
 <%! from desktop.lib.django_util import extract_field_data %>
 
 
+<%
+  is_superuser = extra_params['current_user'].username == extra_params['superuser']
+  select_class = is_superuser and 'ccs-select-with-other' or ''
+%>
+
 ## Puts together a selection list with an "other" field as well.
 ## Puts together a selection list with an "other" field as well.
-<%def name="selection(name, choices, current_value, other_key)">
+<%def name="selection(name, choices, current_value, other_key=None)">
     <% seen = False %>
     <% seen = False %>
     % if len(choices) == 0:
     % if len(choices) == 0:
       <select name="${name}" class="ccs-hidden">
       <select name="${name}" class="ccs-hidden">
@@ -34,21 +39,24 @@ ${comps.header('Change Owner / Group: ' + path.split('/')[-1])}
         <option>${choice}</option>
         <option>${choice}</option>
       % endif
       % endif
     % endfor
     % endfor
-    % if seen or not current_value:
-      <option value="__other__">Other</option>
-    % else:
-      <option value="__other__" selected="true">Other</option>
+    % if is_superuser:
+      % if seen or not current_value:
+        <option value="__other__">Other</option>
+      % else:
+        <option value="__other__" selected="true">Other</option>
+      % endif
     % endif
     % endif
 
 
     </select>
     </select>
-    % if seen or not current_value:
-      <input name="${other_key}" class="ccs-hidden">
-    % else:
-      <input name="${other_key}" value="${current_value}">
+    % if is_superuser:
+      % if seen or not current_value:
+        <input name="${other_key}" class="ccs-hidden">
+      % else:
+        <input name="${other_key}" value="${current_value}">
+      % endif
     % endif
     % endif
 </%def>
 </%def>
 
 
-
 <div class="prompt_popup">
 <div class="prompt_popup">
 <form action="/filebrowser/chown?next=${next|u}" method="POST" enctype="multipart/form-data">
 <form action="/filebrowser/chown?next=${next|u}" method="POST" enctype="multipart/form-data">
   <h4 class="ccs-hidden">Change Owner / Group: ${path}</h4>
   <h4 class="ccs-hidden">Change Owner / Group: ${path}</h4>
@@ -56,12 +64,25 @@ ${comps.header('Change Owner / Group: ' + path.split('/')[-1])}
     ${edit.render_field(form["path"], hidden=True)}
     ${edit.render_field(form["path"], hidden=True)}
 
 
     <dt><label>User</label></dt>
     <dt><label>User</label></dt>
-    <dd class="ccs-select-with-other">${ selection("user", form.all_users, extract_field_data(form["user"]), "user_other") }</dd>
+    <dd class="${select_class}">
+      % if is_superuser:
+        ${ selection("user", form.all_users, extract_field_data(form["user"]), "user_other") }
+      % else:
+        ${ selection("user", [extract_field_data(form['user'])], extract_field_data(form["user"])) }
+      % endif
+    </dd>
     <dt><label>Group</label></dt>
     <dt><label>Group</label></dt>
-    <dd class="ccs-select-with-other">${ selection("group", form.all_groups, extract_field_data(form["group"]), "group_other") }</dd>
+    <dd class="${select_class}">
+      % if is_superuser:
+        ${ selection("group", form.all_groups, extract_field_data(form["group"]), "group_other") }
+      % else:
+        ${ selection("group", [group for group in form.all_groups if group in extra_params['current_user'].get_groups()], extract_field_data(form["group"])) }
+      % endif
+    </dd>
   </dl>
   </dl>
   <input class="ccs-hidden" type="submit" value="Submit" />
   <input class="ccs-hidden" type="submit" value="Submit" />
 </form>
 </form>
+<p>Note: Only the Hadoop superuser, on this FS "${extra_params['superuser']}", may change the owner of a file.</p>
 </div>
 </div>
 
 
 <div class="ccs-hidden">Go back to where you were: <a href="${next|u}">${next}</a>.</div>
 <div class="ccs-hidden">Go back to where you were: <a href="${next|u}">${next}</a>.</div>

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

@@ -497,7 +497,7 @@ def _calculate_navigation(offset, length, size):
 
 
   return first, prev, next, last
   return first, prev, next, last
 
 
-def generic_op(form_class, request, op, parameter_names, piggyback=None, template="fileop.mako"):
+def generic_op(form_class, request, op, parameter_names, piggyback=None, template="fileop.mako", extra_params=None):
   """
   """
   Generic implementation for several operations.
   Generic implementation for several operations.
 
 
@@ -506,6 +506,7 @@ def generic_op(form_class, request, op, parameter_names, piggyback=None, templat
   @param op callable with the filesystem operation
   @param op callable with the filesystem operation
   @param parameter_names list of form parameters that are extracted and then passed to op
   @param parameter_names list of form parameters that are extracted and then passed to op
   @param piggyback list of form parameters whose file stats to look up after the operation
   @param piggyback list of form parameters whose file stats to look up after the operation
+  @param extra_params dictionary of extra parameters to send to the template for rendering
   """
   """
   # Use next for non-ajax requests, when available.
   # Use next for non-ajax requests, when available.
   next = request.GET.get("next")
   next = request.GET.get("next")
@@ -515,12 +516,15 @@ def generic_op(form_class, request, op, parameter_names, piggyback=None, templat
   ret = dict({
   ret = dict({
     'next':next
     'next':next
   })
   })
+
+  if extra_params is not None:
+    ret['extra_params'] = extra_params
+
   for p in parameter_names:
   for p in parameter_names:
     val = request.REQUEST.get(p)
     val = request.REQUEST.get(p)
     if val:
     if val:
       ret[p] = val
       ret[p] = val
 
 
-
   if request.method == 'POST':
   if request.method == 'POST':
     form = form_class(request.POST)
     form = form_class(request.POST)
     # TODO(philip): How best to do error handling?  fs will throw
     # TODO(philip): How best to do error handling?  fs will throw
@@ -599,7 +603,8 @@ def chown(request):
   if request.POST.get("group") == "__other__":
   if request.POST.get("group") == "__other__":
     args[2] = "group_other"
     args[2] = "group_other"
 
 
-  return generic_op(ChownForm, request, request.fs.chown, args, "path", template="chown.mako")
+  return generic_op(ChownForm, request, request.fs.chown, args, "path", template="chown.mako",
+    extra_params=dict(current_user=request.user, superuser=request.fs.superuser))
 
 
 def upload_flash(request):
 def upload_flash(request):
   """
   """

+ 11 - 0
apps/filebrowser/src/filebrowser/views_test.py

@@ -41,6 +41,17 @@ def test_chown():
     assert_equal("y", cluster.fs.stats(PATH)["group"])
     assert_equal("y", cluster.fs.stats(PATH)["group"])
     c.post("/filebrowser/chown", dict(path=PATH, user="__other__", user_other="z", group="y"))
     c.post("/filebrowser/chown", dict(path=PATH, user="__other__", user_other="z", group="y"))
     assert_equal("z", cluster.fs.stats(PATH)["user"])
     assert_equal("z", cluster.fs.stats(PATH)["user"])
+
+    # Make sure that the regular user chown form doesn't have useless fields,
+    # and that the superuser's form has all the fields it could dream of.
+    PATH = '/filebrowser/chown-regular-user'
+    cluster.fs.mkdir(PATH)
+    cluster.fs.chown(PATH, 'chown_test', 'chown_test')
+    response = c.get('/filebrowser/chown', dict(path=PATH, user='chown_test', group='chown_test'))
+    assert_true('<option value="__other__"' in response.content)
+    c = make_logged_in_client('chown_test')
+    response = c.get('/filebrowser/chown', dict(path=PATH, user='chown_test', group='chown_test'))
+    assert_false('<option value="__other__"' in response.content)
   finally:
   finally:
     cluster.shutdown()
     cluster.shutdown()