[ARVADOS] updated: dcf55645168e3842002e7561b3b7749491d3b67b

Git user git at public.curoverse.com
Tue Aug 30 22:14:10 EDT 2016


Summary of changes:
 apps/workbench/app/models/container_work_unit.rb    |  6 ++++++
 apps/workbench/app/models/work_unit.rb              |  4 ++++
 .../test/integration/container_requests_test.rb     |  2 +-
 apps/workbench/test/unit/work_unit_test.rb          | 13 +++++++++++++
 services/api/test/fixtures/container_requests.yml   | 19 +++++++++++++++++++
 services/api/test/fixtures/containers.yml           | 21 +++++++++++++++++++++
 6 files changed, 64 insertions(+), 1 deletion(-)

  discards  6ef309546be01480bee1fe9290398273a0224a53 (commit)
  discards  544222127959aed73c0fd90cb50813fe2c65bceb (commit)
  discards  d980abb3bdde99007f1ebb39c1e6855c72bba833 (commit)
  discards  9d2f9e74b24b1d6245358e13f1381d66a585bf2d (commit)
  discards  555f1f82e2f9ec4db974a69a0db43097da28cc80 (commit)
  discards  cedab072d40380e330396d5cc3c25f7c0d131484 (commit)
  discards  2c54a701af3a696fb063f0e663dec1e66a14141a (commit)
  discards  35145ba13db4a7db0e4ed9c37ef4cc41569b8821 (commit)
  discards  f781ecb0151d9200107c3a37b9e2922d486ac2b9 (commit)
  discards  e93a93410ab375602dec81827d7020dbdc8e6c55 (commit)
  discards  99a4c1a02a23d3fbf809fb0b686b12b648f5b96e (commit)
  discards  3c85d746e3f7f0ef1af6a0380e42c7adbadd2618 (commit)
  discards  2bd7d60ffc5f21bca981ffd2e7698402f3935653 (commit)
  discards  c65b67ceeaea069eb37a57cefadf0ab71795df26 (commit)
  discards  238090391a898a698ee0d5ef89c295e8e4c84570 (commit)
  discards  4fc5864e97750decf4eb90e5fedb3e4f1733651a (commit)
  discards  bdab775e99fbdb4cc4d2903d83be3878829e9193 (commit)
  discards  696c59aac3835675d7fe411c0850d3223e8db538 (commit)
  discards  712cb4bf514215f38b796a54d1fc72cb3a70d207 (commit)
  discards  a502437e2c0833b0fde616e2f8f0e87f4686b953 (commit)
  discards  a4cbf619dba93de29140ddc1ead992e88bd28b3a (commit)
       via  dcf55645168e3842002e7561b3b7749491d3b67b (commit)
       via  3090a8d0b4020b291bf34958680e3cf4cd0b8c21 (commit)
       via  730eb182b2160040a902feb09276b75a3f9c137c (commit)
       via  415cb3b63e8cfafd4c6b92a8971a0cff74097337 (commit)
       via  2cc397021b57dc43449730f4d13ac99d4e6be41d (commit)
       via  a1c3389d7fe54a7311609e7f74b5a9b3ea825c94 (commit)
       via  694836fc68fbe6414d5248b48889ea3be1c33b75 (commit)
       via  203cf7998836c7a00cfad2eeaf59b59f07d8e3ed (commit)
       via  262a16e15c0dcfa9245e9c8fd88d383f54f51471 (commit)
       via  661399e4fd26be1a932d94d0b2c419cd3a33a4f1 (commit)
       via  9fd1f52e97c96f9a0a0fc76b37520828f0d9221d (commit)
       via  5497c52dae7a3832e75d8e414492d48df1192ddc (commit)
       via  3d53281b9e3ba0840e5e3eaeb0371e0f50a345ad (commit)
       via  61ee10791b2b1f3724e6a8736c93161a625b5246 (commit)
       via  87cb6b04df6f71d5bce9b0b3c1257e0b5082668d (commit)
       via  2bc21107e3fa6c4ecea7efb22e4dfc7e30b3233d (commit)
       via  71ec472aa11b47a58beb3b050fee38244674869e (commit)
       via  579195def22d6b02f7484933d6db065bc33088d9 (commit)
       via  08224a6abb60ff61f3967abc9665f50f9157791b (commit)
       via  08262a4e18c0b3b65946878058e9546823b82535 (commit)
       via  95e6adc8ac2c9449aba651ef0d932cd7d27aea5e (commit)
       via  fbb979710d3cf5e2ee8c46936ac81081ef553b5c (commit)
       via  3678eda6ea138d948919944d1b54e680ba20ea81 (commit)
       via  a3b87eea221b1c169fd1e953c8263e63646a2da1 (commit)
       via  8da182df7745caa74c1406af3c458d8cf5532c70 (commit)
       via  24eee13008ef6bd36bf29ac9cecd045663ea1ba6 (commit)
       via  74b5dd2b6f4a33b06b136fd587408ec3d4e42ec0 (commit)

This update added new revisions after undoing existing revisions.  That is
to say, the old revision is not a strict subset of the new revision.  This
situation occurs when you --force push a change and generate a repository
containing something like this:

 * -- * -- B -- O -- O -- O (6ef309546be01480bee1fe9290398273a0224a53)
            \
             N -- N -- N (dcf55645168e3842002e7561b3b7749491d3b67b)

When this happens we assume that you've already had alert emails for all
of the O revisions, and so we here report only the revisions in the N
branch from the common base, B.

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.


commit dcf55645168e3842002e7561b3b7749491d3b67b
Author: Tom Clegg <tom at curoverse.com>
Date:   Tue Aug 30 22:14:04 2016 -0400

    9799: Update test: non-admin user can see container assigned to committed CR.

diff --git a/apps/workbench/test/integration/container_requests_test.rb b/apps/workbench/test/integration/container_requests_test.rb
index cdb5c91..e5e8ed8 100644
--- a/apps/workbench/test/integration/container_requests_test.rb
+++ b/apps/workbench/test/integration/container_requests_test.rb
@@ -75,7 +75,7 @@ class ContainerRequestsTest < ActionDispatch::IntegrationTest
       assert_text 'This workflow does not need any further inputs'
       click_link "Run"
       wait_for_ajax
-      assert_text 'This container is committed'
+      assert_text 'This container is queued'
     end
   end
 

commit 3090a8d0b4020b291bf34958680e3cf4cd0b8c21
Author: Tom Clegg <tom at curoverse.com>
Date:   Tue Aug 30 17:34:42 2016 -0400

    9799: Fix bootstrap markup.

diff --git a/apps/workbench/app/views/work_units/_show_child.html.erb b/apps/workbench/app/views/work_units/_show_child.html.erb
index 1d5ae63..acf19fd 100644
--- a/apps/workbench/app/views/work_units/_show_child.html.erb
+++ b/apps/workbench/app/views/work_units/_show_child.html.erb
@@ -1,7 +1,6 @@
 <div class="panel panel-default">
   <div class="panel-heading">
-    <div class="container-fluid">
-      <div class="row-fluid">
+      <div class="row">
         <div class="col-md-2" style="word-break:break-all;">
           <h4 class="panel-title">
             <a data-toggle="collapse" href="#collapse<%= i %>">
@@ -66,7 +65,6 @@
           </div>
         <% end %>
       </div>
-    </div>
   </div>
 
   <div id="collapse<%= i %>" class="panel-collapse collapse <%= if expanded then 'in' end %>">
diff --git a/apps/workbench/app/views/work_units/_show_component.html.erb b/apps/workbench/app/views/work_units/_show_component.html.erb
index f40170a..89233cf 100644
--- a/apps/workbench/app/views/work_units/_show_component.html.erb
+++ b/apps/workbench/app/views/work_units/_show_component.html.erb
@@ -1,46 +1,35 @@
 <%# Work unit status %>
 
-<div>
-  <div>
-    <%# Need additional handling for main object display  %>
-    <% if @object.uuid == wu.uuid %>
-    <div>
-      <div class="pull-right">
-        <div>
-          <div class="pipeline-instance-spacing">
-            <div class="col-md-7">
-            <% if wu.is_running? and wu.child_summary_str %>
-                <%= wu.child_summary_str %>
-            <% end %>
-            </div>
-            <div class="col-md-3">
-              <%= render partial: 'work_units/progress', locals: {wu: wu} %>
-            </div>
-            <div class="col-md-1">
-              <% if wu.can_cancel? and @object.editable? %>
-                <%= form_tag "#{wu.uri}/cancel", remote: true, style: "display:inline; padding-left: 1em" do |f| %>
-                  <%= hidden_field_tag :return_to, url_for(@object) %>
-                  <%= button_tag "Cancel", {class: 'btn btn-xs btn-danger', id: "cancel-obj-button"} %>
-                <% end %>
-              <% end %>
-            </div>
-          </div>
-        </div>
-      </div>
-    </div>
+<div class="row">
+  <div class="col-md-4">
+    <% if wu.is_paused? %>
+      <p>
+        This <%= wu.title %> is paused. Children that are already running
+        will continue to run, but no new processes will be submitted.
+      </p>
     <% end %>
 
-    <div class="col-md-10" >
-      <% if wu.is_paused? %>
-        <p>
-          This <%= wu.title %> is paused. Children that are already running
-          will continue to run, but no new processes will be submitted.
-        </p>
+    <%= raw(wu.show_runtime) %>
+  </div>
+  <%# Need additional handling for main object display  %>
+  <% if @object.uuid == wu.uuid %>
+    <div class="col-md-3">
+      <% if wu.is_running? and wu.child_summary_str %>
+        <%= wu.child_summary_str %>
       <% end %>
-
-      <%= raw(wu.show_runtime) %>
     </div>
-  </div>
+    <div class="col-md-3">
+      <%= render partial: 'work_units/progress', locals: {wu: wu} %>
+    </div>
+    <div class="col-md-2">
+      <% if wu.can_cancel? and @object.editable? %>
+        <%= form_tag "#{wu.uri}/cancel", remote: true, style: "display:inline; padding-left: 1em" do |f| %>
+          <%= hidden_field_tag :return_to, url_for(@object) %>
+          <%= button_tag "Cancel", {class: 'btn btn-xs btn-danger', id: "cancel-obj-button"} %>
+        <% end %>
+      <% end %>
+    </div>
+  <% end %>
 </div>
 
 <p>

commit 730eb182b2160040a902feb09276b75a3f9c137c
Author: Tom Clegg <tom at curoverse.com>
Date:   Tue Aug 30 16:30:17 2016 -0400

    9799: Fix up live_log_lines so it works for all work units.

diff --git a/apps/workbench/app/models/container_work_unit.rb b/apps/workbench/app/models/container_work_unit.rb
index 42a4f4b..c8af093 100644
--- a/apps/workbench/app/models/container_work_unit.rb
+++ b/apps/workbench/app/models/container_work_unit.rb
@@ -134,13 +134,6 @@ class ContainerWorkUnit < ProxyWorkUnit
     [get_combined(:uuid), get(:uuid)].uniq
   end
 
-  def live_log_lines(limit=2000)
-    event_types = ["stdout", "stderr", "arv-mount", "crunch-run"]
-    log_lines = Log.where(event_type: event_types, object_uuid: log_object_uuids).order("id DESC").limit(limit)
-    log_lines.results.reverse.
-      flat_map { |log| log.properties[:text].split("\n") rescue [] }
-  end
-
   def render_log
     collection = Collection.find(log_collection) rescue nil
     if collection
diff --git a/apps/workbench/app/models/job.rb b/apps/workbench/app/models/job.rb
index 73f1f63..bf202c4 100644
--- a/apps/workbench/app/models/job.rb
+++ b/apps/workbench/app/models/job.rb
@@ -43,8 +43,7 @@ class Job < ArvadosBase
   end
 
   def stderr_log_query(limit=nil)
-    query = Log.where(event_type: "stderr", object_uuid: self.uuid)
-               .order("id DESC")
+    query = Log.where(object_uuid: self.uuid).order("created_at DESC")
     query = query.limit(limit) if limit
     query
   end
diff --git a/apps/workbench/app/models/proxy_work_unit.rb b/apps/workbench/app/models/proxy_work_unit.rb
index feab5d8..11ec0ee 100644
--- a/apps/workbench/app/models/proxy_work_unit.rb
+++ b/apps/workbench/app/models/proxy_work_unit.rb
@@ -332,6 +332,15 @@ class ProxyWorkUnit < WorkUnit
     [uuid]
   end
 
+  def live_log_lines(limit)
+    Log.where(object_uuid: log_object_uuids).
+      order("created_at DESC").
+      limit(limit).
+      select { |log| log.properties[:text].is_a? String }.
+      reverse.
+      flat_map { |log| log.properties[:text].split("\n") }
+  end
+
   protected
 
   def get key, obj=@proxied
diff --git a/apps/workbench/test/integration/websockets_test.rb b/apps/workbench/test/integration/websockets_test.rb
index 3cfd792..54712d3 100644
--- a/apps/workbench/test/integration/websockets_test.rb
+++ b/apps/workbench/test/integration/websockets_test.rb
@@ -201,7 +201,6 @@ class WebsocketTest < ActionDispatch::IntegrationTest
 
   test "test running job with just a few previous log records" do
     job = api_fixture("jobs")['running']
-    visit page_with_token("active", "/jobs/#{job['uuid']}")
 
     # Create just one old log record
     dispatch_log(owner_uuid: job['owner_uuid'],
@@ -209,7 +208,7 @@ class WebsocketTest < ActionDispatch::IntegrationTest
                  event_type: "stderr",
                  properties: {"text" => "Historic log message"})
 
-    click_link("Log")
+    visit page_with_token("active", "/jobs/#{job['uuid']}\#Log")
 
     # Expect "all" historic log records because we have less than
     # default Rails.configuration.running_job_log_records_to_fetch count
@@ -224,25 +223,23 @@ class WebsocketTest < ActionDispatch::IntegrationTest
   end
 
   test "test running job with too many previous log records" do
-    Rails.configuration.running_job_log_records_to_fetch = 5
-
+    max = 5
+    Rails.configuration.running_job_log_records_to_fetch = max
     job = api_fixture("jobs")['running']
-    visit page_with_token("active", "/jobs/#{job['uuid']}")
 
-    # Create Rails.configuration.running_job_log_records_to_fetch + 1 log records
-    (0..Rails.configuration.running_job_log_records_to_fetch).each do |count|
+    # Create max+1 log records
+    (0..max).each do |count|
       dispatch_log(owner_uuid: job['owner_uuid'],
                    object_uuid: job['uuid'],
                    event_type: "stderr",
                    properties: {"text" => "Old log message #{count}"})
     end
 
-    # Go to log tab, which results in subscribing to websockets
-    click_link("Log")
+    visit page_with_token("active", "/jobs/#{job['uuid']}\#Log")
 
     # Expect all but the first historic log records,
     # because that was one too many than fetch count.
-    (1..Rails.configuration.running_job_log_records_to_fetch).each do |count|
+    (1..max).each do |count|
       assert_text "Old log message #{count}"
     end
     assert_no_text 'Old log message 0'

commit 415cb3b63e8cfafd4c6b92a8971a0cff74097337
Author: Tom Clegg <tom at curoverse.com>
Date:   Tue Aug 30 16:35:32 2016 -0400

    9799: Remove bogus bootstrap classes and fix html syntax.

diff --git a/apps/workbench/app/views/work_units/_show_component.html.erb b/apps/workbench/app/views/work_units/_show_component.html.erb
index 43f5692..f40170a 100644
--- a/apps/workbench/app/views/work_units/_show_component.html.erb
+++ b/apps/workbench/app/views/work_units/_show_component.html.erb
@@ -1,13 +1,13 @@
 <%# Work unit status %>
 
-<div class="container-fluid>
-  <div class="row-fluid">
+<div>
+  <div>
     <%# Need additional handling for main object display  %>
     <% if @object.uuid == wu.uuid %>
-    <div class="container-fluid">
+    <div>
       <div class="pull-right">
-        <div class="container-fluid">
-          <div class="row-fulid pipeline-instance-spacing">
+        <div>
+          <div class="pipeline-instance-spacing">
             <div class="col-md-7">
             <% if wu.is_running? and wu.child_summary_str %>
                 <%= wu.child_summary_str %>
@@ -18,10 +18,10 @@
             </div>
             <div class="col-md-1">
               <% if wu.can_cancel? and @object.editable? %>
-                  <%= form_tag "#{wu.uri}/cancel", remote: true, style: "display:inline; padding-left: 1em" do |f| %>
-                    <%= hidden_field_tag :return_to, url_for(@object) %>
-                    <%= button_tag "Cancel", {class: 'btn btn-xs btn-danger', id: "cancel-obj-button"} %>
-                  <% end %>
+                <%= form_tag "#{wu.uri}/cancel", remote: true, style: "display:inline; padding-left: 1em" do |f| %>
+                  <%= hidden_field_tag :return_to, url_for(@object) %>
+                  <%= button_tag "Cancel", {class: 'btn btn-xs btn-danger', id: "cancel-obj-button"} %>
+                <% end %>
               <% end %>
             </div>
           </div>
@@ -41,6 +41,7 @@
       <%= raw(wu.show_runtime) %>
     </div>
   </div>
+</div>
 
 <p>
   <%= render(partial: 'work_units/component_detail', locals: {current_obj: wu}) %>

commit 2cc397021b57dc43449730f4d13ac99d4e6be41d
Author: Tom Clegg <tom at curoverse.com>
Date:   Tue Aug 30 16:23:59 2016 -0400

    9799: Move work unit tests from application_layout_test to work_units_test.

diff --git a/apps/workbench/test/integration/application_layout_test.rb b/apps/workbench/test/integration/application_layout_test.rb
index 81ddda6..93827a9 100644
--- a/apps/workbench/test/integration/application_layout_test.rb
+++ b/apps/workbench/test/integration/application_layout_test.rb
@@ -286,76 +286,4 @@ class ApplicationLayoutTest < ActionDispatch::IntegrationTest
       end
     end
   end
-
-  [
-    ['jobs', 'running_job_with_components', true],
-    ['pipeline_instances', 'components_is_jobspec', false],
-    ['containers', 'running', false],
-    ['container_requests', 'running', true],
-  ].each do |type, fixture, cancelable|
-    test "cancel button for #{type}/#{fixture}" do
-      if cancelable
-        need_selenium 'to cancel'
-      end
-
-      obj = api_fixture(type)[fixture]
-      visit page_with_token "active", "/#{type}/#{obj['uuid']}"
-
-      assert_text 'created_at'
-      if cancelable
-        assert_selector 'button', text: 'Cancel'
-        click_button 'Cancel'
-        wait_for_ajax
-      end
-      assert_no_selector 'button', text: 'Cancel'
-    end
-  end
-
-  [
-    ['jobs', 'running_job_with_components'],
-    ['pipeline_instances', 'has_component_with_completed_jobs'],
-    ['container_requests', 'running'],
-    ['container_requests', 'completed'],
-  ].each do |type, fixture|
-    test "edit description for #{type}/#{fixture}" do
-      obj = api_fixture(type)[fixture]
-      visit page_with_token "active", "/#{type}/#{obj['uuid']}"
-
-      within('.arv-description-as-subtitle') do
-        find('.fa-pencil').click
-        find('.editable-input textarea').set('*Textile description for object*')
-        find('.editable-submit').click
-      end
-      wait_for_ajax
-
-      # verify description
-      assert page.has_no_text? '*Textile description for object*'
-      assert page.has_text? 'Textile description for object'
-    end
-  end
-
-  [
-    ['Two Part Pipeline Template', 'part-one', 'Provide a value for the following'],
-    ['Workflow with input specifications', 'this workflow has inputs specified', 'Provide a value for the following'],
-  ].each do |template_name, preview_txt, process_txt|
-    test "run a process using template #{template_name} from dashboard" do
-      visit page_with_token('admin')
-      assert_text 'Recent pipelines and processes' # seeing dashboard now
-
-      within('.recent-processes-actions') do
-        assert page.has_link?('All processes')
-        find('a', text: 'Run a pipeline').click
-      end
-
-      # in the chooser, verify preview and click Next button
-      within('.modal-dialog') do
-        find('.selectable', text: template_name).click
-        assert_text preview_txt
-        find('.btn', text: 'Next: choose inputs').click
-      end
-
-      # in the process page now
-      assert_text process_txt
-    end
-  end
 end
diff --git a/apps/workbench/test/integration/work_units_test.rb b/apps/workbench/test/integration/work_units_test.rb
index 63ba275..f842d12 100644
--- a/apps/workbench/test/integration/work_units_test.rb
+++ b/apps/workbench/test/integration/work_units_test.rb
@@ -55,4 +55,76 @@ class WorkUnitsTest < ActionDispatch::IntegrationTest
         assert_no_selector "a[href=\"#{link}\"]"
       end
   end
+
+  [
+    ['jobs', 'running_job_with_components', true],
+    ['pipeline_instances', 'components_is_jobspec', false],
+    ['containers', 'running', false],
+    ['container_requests', 'running', true],
+  ].each do |type, fixture, cancelable|
+    test "cancel button for #{type}/#{fixture}" do
+      if cancelable
+        need_selenium 'to cancel'
+      end
+
+      obj = api_fixture(type)[fixture]
+      visit page_with_token "active", "/#{type}/#{obj['uuid']}"
+
+      assert_text 'created_at'
+      if cancelable
+        assert_selector 'button', text: 'Cancel'
+        click_button 'Cancel'
+        wait_for_ajax
+      end
+      assert_no_selector 'button', text: 'Cancel'
+    end
+  end
+
+  [
+    ['jobs', 'running_job_with_components'],
+    ['pipeline_instances', 'has_component_with_completed_jobs'],
+    ['container_requests', 'running'],
+    ['container_requests', 'completed'],
+  ].each do |type, fixture|
+    test "edit description for #{type}/#{fixture}" do
+      obj = api_fixture(type)[fixture]
+      visit page_with_token "active", "/#{type}/#{obj['uuid']}"
+
+      within('.arv-description-as-subtitle') do
+        find('.fa-pencil').click
+        find('.editable-input textarea').set('*Textile description for object*')
+        find('.editable-submit').click
+      end
+      wait_for_ajax
+
+      # verify description
+      assert page.has_no_text? '*Textile description for object*'
+      assert page.has_text? 'Textile description for object'
+    end
+  end
+
+  [
+    ['Two Part Pipeline Template', 'part-one', 'Provide a value for the following'],
+    ['Workflow with input specifications', 'this workflow has inputs specified', 'Provide a value for the following'],
+  ].each do |template_name, preview_txt, process_txt|
+    test "run a process using template #{template_name} from dashboard" do
+      visit page_with_token('admin')
+      assert_text 'Recent pipelines and processes' # seeing dashboard now
+
+      within('.recent-processes-actions') do
+        assert page.has_link?('All processes')
+        find('a', text: 'Run a pipeline').click
+      end
+
+      # in the chooser, verify preview and click Next button
+      within('.modal-dialog') do
+        find('.selectable', text: template_name).click
+        assert_text preview_txt
+        find('.btn', text: 'Next: choose inputs').click
+      end
+
+      # in the process page now
+      assert_text process_txt
+    end
+  end
 end

commit a1c3389d7fe54a7311609e7f74b5a9b3ea825c94
Author: Tom Clegg <tom at curoverse.com>
Date:   Tue Aug 30 11:36:28 2016 -0400

    9799: Fix show/hide "cancel container req" button: check ArvadosBase#editable?, and use CR priority instead of container priority.

diff --git a/apps/workbench/app/models/container_work_unit.rb b/apps/workbench/app/models/container_work_unit.rb
index 944dc02..42a4f4b 100644
--- a/apps/workbench/app/models/container_work_unit.rb
+++ b/apps/workbench/app/models/container_work_unit.rb
@@ -46,13 +46,17 @@ class ContainerWorkUnit < ProxyWorkUnit
   end
 
   def can_cancel?
-    @proxied.is_a?(ContainerRequest) && state_label.in?(["Queued", "Locked", "Running"]) && priority > 0
+    @proxied.is_a?(ContainerRequest) && @proxied.state == "Committed" && @proxied.priority > 0 && @proxied.editable?
   end
 
   def container_uuid
     get(:container_uuid)
   end
 
+  def priority
+    @proxied.priority
+  end
+
   # For the following properties, use value from the @container if exists
   # This applies to a ContainerRequest with container_uuid
 
@@ -92,10 +96,6 @@ class ContainerWorkUnit < ProxyWorkUnit
     get_combined(:runtime_constraints)
   end
 
-  def priority
-    get_combined(:priority)
-  end
-
   def log_collection
     get_combined(:log)
   end
@@ -155,7 +155,7 @@ class ContainerWorkUnit < ProxyWorkUnit
     end
   end
 
-  # End combined propeties
+  # End combined properties
 
   protected
   def get_combined key
diff --git a/apps/workbench/test/integration/application_layout_test.rb b/apps/workbench/test/integration/application_layout_test.rb
index 686b63b..81ddda6 100644
--- a/apps/workbench/test/integration/application_layout_test.rb
+++ b/apps/workbench/test/integration/application_layout_test.rb
@@ -303,13 +303,11 @@ class ApplicationLayoutTest < ActionDispatch::IntegrationTest
 
       assert_text 'created_at'
       if cancelable
-        assert page.has_button?('Cancel'), 'No Cancel button'
+        assert_selector 'button', text: 'Cancel'
         click_button 'Cancel'
         wait_for_ajax
-        assert page.has_no_button?('Cancel'), 'Cancel button not expected after clicking'
-      else
-        assert page.has_no_button?('Cancel'), 'Cancel button not expected'
       end
+      assert_no_selector 'button', text: 'Cancel'
     end
   end
 
diff --git a/apps/workbench/test/test_helper.rb b/apps/workbench/test/test_helper.rb
index 78ef2d2..73bfda6 100644
--- a/apps/workbench/test/test_helper.rb
+++ b/apps/workbench/test/test_helper.rb
@@ -32,14 +32,16 @@ class ActiveSupport::TestCase
   # in integration tests -- they do not yet inherit this setting
   fixtures :all
   def use_token token_name
-    was = Thread.current[:arvados_api_token]
+    user_was = Thread.current[:user]
+    token_was = Thread.current[:arvados_api_token]
     auth = api_fixture('api_client_authorizations')[token_name.to_s]
     Thread.current[:arvados_api_token] = auth['api_token']
     if block_given?
       begin
         yield
       ensure
-        Thread.current[:arvados_api_token] = was
+        Thread.current[:user] = user_was
+        Thread.current[:arvados_api_token] = token_was
       end
     end
   end
diff --git a/apps/workbench/test/unit/work_unit_test.rb b/apps/workbench/test/unit/work_unit_test.rb
index 304dc8b..68bc2fd 100644
--- a/apps/workbench/test/unit/work_unit_test.rb
+++ b/apps/workbench/test/unit/work_unit_test.rb
@@ -104,4 +104,18 @@ class WorkUnitTest < ActiveSupport::TestCase
       end
     end
   end
+
+  test 'can_cancel?' do
+    use_token 'active' do
+      assert find_fixture(Job, 'running').work_unit.can_cancel?
+      refute find_fixture(Container, 'running').work_unit.can_cancel?
+      assert find_fixture(ContainerRequest, 'running').work_unit.can_cancel?
+    end
+    use_token 'spectator' do
+      refute find_fixture(ContainerRequest, 'running_anonymous_accessible').work_unit.can_cancel?
+    end
+    use_token 'admin' do
+      assert find_fixture(ContainerRequest, 'running_anonymous_accessible').work_unit.can_cancel?
+    end
+  end
 end

commit 694836fc68fbe6414d5248b48889ea3be1c33b75
Author: Tom Clegg <tom at curoverse.com>
Date:   Tue Aug 30 11:14:55 2016 -0400

    9799: Add forgotten serialized column.

diff --git a/services/api/app/controllers/arvados/v1/container_requests_controller.rb b/services/api/app/controllers/arvados/v1/container_requests_controller.rb
index fe4696e..6e2848c 100644
--- a/services/api/app/controllers/arvados/v1/container_requests_controller.rb
+++ b/services/api/app/controllers/arvados/v1/container_requests_controller.rb
@@ -3,4 +3,5 @@ class Arvados::V1::ContainerRequestsController < ApplicationController
   accept_attribute_as_json :mounts, Hash
   accept_attribute_as_json :runtime_constraints, Hash
   accept_attribute_as_json :command, Array
+  accept_attribute_as_json :filters, Array
 end

commit 203cf7998836c7a00cfad2eeaf59b59f07d8e3ed
Author: Tom Clegg <tom at curoverse.com>
Date:   Mon Aug 29 23:29:57 2016 -0400

    9799: Use more realistic log entries in Workbench live-logging tests. Remove redundant test.

diff --git a/apps/workbench/test/integration/websockets_test.rb b/apps/workbench/test/integration/websockets_test.rb
index e302a39..3cfd792 100644
--- a/apps/workbench/test/integration/websockets_test.rb
+++ b/apps/workbench/test/integration/websockets_test.rb
@@ -3,6 +3,13 @@ require 'integration_helper'
 class WebsocketTest < ActionDispatch::IntegrationTest
   setup do
     need_selenium "to make websockets work"
+    @dispatch_client = ArvadosApiClient.new
+  end
+
+  def dispatch_log body
+    use_token :dispatch1 do
+      @dispatch_client.api('logs', '', log: body)
+    end
   end
 
   test "test page" do
@@ -12,58 +19,39 @@ class WebsocketTest < ActionDispatch::IntegrationTest
     assert_text '"status":400'
   end
 
-  test "test live logging" do
-    visit(page_with_token("active", "/pipeline_instances/zzzzz-d1hrv-9fm8l10i9z2kqc6"))
-    click_link("Log")
-    assert_no_text '123 hello'
-
-    api = ArvadosApiClient.new
-
-    use_token :active
-    api.api("logs", "", {log: {
-                object_uuid: "zzzzz-d1hrv-9fm8l10i9z2kqc6",
-                event_type: "stderr",
-                properties: {"text" => "123 hello"}}})
-    assert_text '123 hello'
-  end
-
   [
-   ["pipeline_instances", api_fixture("pipeline_instances")['pipeline_with_newer_template']['uuid']],
-   ["jobs", api_fixture("jobs")['running']['uuid']],
-   ["containers", api_fixture("containers")['running']['uuid']],
-   ["container_requests", api_fixture("container_requests")['running']['uuid'], api_fixture("containers")['running']['uuid']],
-  ].each do |controller, uuid, log_uuid|
-    log_uuid = log_uuid || uuid
+   ['pipeline_instances', 'pipeline_in_running_state', api_fixture('jobs')['running']],
+   ['jobs', 'running'],
+   ['containers', 'running'],
+   ['container_requests', 'running', api_fixture('containers')['running']],
+  ].each do |controller, view_fixture_name, log_target_fixture|
+    view_fixture = api_fixture(controller)[view_fixture_name]
+    log_target_fixture ||= view_fixture
 
-    test "test live logging scrolling for #{controller}" do
+    test "test live logging and scrolling for #{controller}" do
 
-      visit(page_with_token("active", "/#{controller}/#{uuid}"))
-      click_link("Log")
+      visit(page_with_token("active", "/#{controller}/#{view_fixture['uuid']}\#Log"))
       assert_no_text '123 hello'
 
-      api = ArvadosApiClient.new
-
       text = ""
       (1..1000).each do |i|
         text << "#{i} hello\n"
       end
 
-      use_token :dispatch1 do
-        api.api("logs", "", {log: {
-                    object_uuid: log_uuid,
-                    event_type: "stderr",
-                    properties: {"text" => text}}})
-      end
+      dispatch_log(owner_uuid: log_target_fixture['owner_uuid'],
+                   object_uuid: log_target_fixture['uuid'],
+                   event_type: "stderr",
+                   properties: {"text" => text})
       assert_text '1000 hello'
 
       # First test that when we're already at the bottom of the page, it scrolls down
       # when a new line is added.
       old_top = page.evaluate_script("$('#event_log_div').scrollTop()")
 
-      api.api("logs", "", {log: {
-                  object_uuid: log_uuid,
-                  event_type: "stderr",
-                  properties: {"text" => "1001 hello\n"}}})
+      dispatch_log(owner_uuid: log_target_fixture['owner_uuid'],
+                   object_uuid: log_target_fixture['uuid'],
+                   event_type: "dispatch",
+                   properties: {"text" => "1001 hello\n"})
       assert_text '1001 hello'
 
       # Check that new value of scrollTop is greater than the old one
@@ -74,10 +62,10 @@ class WebsocketTest < ActionDispatch::IntegrationTest
       page.execute_script "$('#event_log_div').scrollTop(30)"
       assert_equal 30, page.evaluate_script("$('#event_log_div').scrollTop()")
 
-      api.api("logs", "", {log: {
-                  object_uuid: log_uuid,
-                  event_type: "stderr",
-                  properties: {"text" => "1002 hello\n"}}})
+      dispatch_log(owner_uuid: log_target_fixture['owner_uuid'],
+                   object_uuid: log_target_fixture['uuid'],
+                   event_type: "stdout",
+                   properties: {"text" => "1002 hello\n"})
       assert_text '1002 hello'
 
       # Check that we haven't changed scroll position
@@ -86,17 +74,16 @@ class WebsocketTest < ActionDispatch::IntegrationTest
   end
 
   test "pipeline instance arv-refresh-on-log-event" do
-    use_token :active
     # Do something and check that the pane reloads.
-    p = PipelineInstance.create({state: "RunningOnServer",
-                                  components: {
-                                    c1: {
-                                      script: "test_hash.py",
-                                      script_version: "1de84a854e2b440dc53bf42f8548afa4c17da332"
-                                    }
-                                  }
-                                })
-
+    p = use_token :active do
+      PipelineInstance.create(state: "RunningOnServer",
+                              components: {
+                                c1: {
+                                  script: "test_hash.py",
+                                  script_version: "1de84a854e2b440dc53bf42f8548afa4c17da332"
+                                }
+                              })
+    end
     visit(page_with_token("active", "/pipeline_instances/#{p.uuid}"))
 
     assert_text 'Active'
@@ -104,9 +91,8 @@ class WebsocketTest < ActionDispatch::IntegrationTest
     assert_no_text 'Complete'
     assert page.has_no_link? 'Re-run with latest'
 
-    use_token :admin do
-      p.state = "Complete"
-      p.save!
+    use_token :dispatch1 do
+      p.update_attributes!(state: 'Complete')
     end
 
     assert_no_text 'Active'
@@ -116,18 +102,15 @@ class WebsocketTest < ActionDispatch::IntegrationTest
   end
 
   test "job arv-refresh-on-log-event" do
-    use_token :active
     # Do something and check that the pane reloads.
-    p = Job.where(uuid: api_fixture('jobs')['running_will_be_completed']['uuid']).results.first
-
-    visit(page_with_token("active", "/jobs/#{p.uuid}"))
+    uuid = api_fixture('jobs')['running_will_be_completed']['uuid']
+    visit(page_with_token("active", "/jobs/#{uuid}"))
 
     assert_no_text 'complete'
     assert_no_text 'Re-run job'
 
-    use_token :admin do
-      p.state = "Complete"
-      p.save!
+    use_token :dispatch1 do
+      Job.find(uuid).update_attributes!(state: 'Complete')
     end
 
     assert_text 'complete'
@@ -135,18 +118,18 @@ class WebsocketTest < ActionDispatch::IntegrationTest
   end
 
   test "dashboard arv-refresh-on-log-event" do
-    use_token :active
-
     visit(page_with_token("active", "/"))
 
     assert_no_text 'test dashboard arv-refresh-on-log-event'
 
     # Do something and check that the pane reloads.
-    p = PipelineInstance.create({state: "RunningOnServer",
-                                  name: "test dashboard arv-refresh-on-log-event",
-                                  components: {
-                                  }
-                                })
+    use_token :active do
+      p = PipelineInstance.create({state: "RunningOnServer",
+                                    name: "test dashboard arv-refresh-on-log-event",
+                                    components: {
+                                    }
+                                  })
+    end
 
     assert_text 'test dashboard arv-refresh-on-log-event'
   end
@@ -182,13 +165,10 @@ class WebsocketTest < ActionDispatch::IntegrationTest
     text = "2014-11-07_23:33:51 #{uuid} 31708 1 stderr crunchstat: cpu 1970.8200 user 60.2700 sys 8 cpus -- interval 10.0002 seconds 35.3900 user 0.8600 sys"
 
     assert_triggers_dom_event 'arv-log-event' do
-      use_token :active do
-        api = ArvadosApiClient.new
-        api.api("logs", "", {log: {
-                    object_uuid: uuid,
-                    event_type: "stderr",
-                    properties: {"text" => text}}})
-      end
+      dispatch_log(owner_uuid: api_fixture('jobs')['running']['owner_uuid'],
+                   object_uuid: uuid,
+                   event_type: "stderr",
+                   properties: {"text" => text})
     end
 
     # Graph should have appeared (even if it hadn't above). It's
@@ -220,17 +200,14 @@ class WebsocketTest < ActionDispatch::IntegrationTest
   end
 
   test "test running job with just a few previous log records" do
-    use_token :active
-    job = Job.where(uuid: api_fixture("jobs")['running']['uuid']).results.first
-    visit page_with_token("active", "/jobs/#{job.uuid}")
-
-    api = ArvadosApiClient.new
+    job = api_fixture("jobs")['running']
+    visit page_with_token("active", "/jobs/#{job['uuid']}")
 
     # Create just one old log record
-    api.api("logs", "", {log: {
-                object_uuid: job.uuid,
-                event_type: "stderr",
-                properties: {"text" => "Historic log message"}}})
+    dispatch_log(owner_uuid: job['owner_uuid'],
+                 object_uuid: job['uuid'],
+                 event_type: "stderr",
+                 properties: {"text" => "Historic log message"})
 
     click_link("Log")
 
@@ -239,29 +216,25 @@ class WebsocketTest < ActionDispatch::IntegrationTest
     assert_text 'Historic log message'
 
     # Create new log record and expect it to show up in log tab
-    api.api("logs", "", {log: {
-                object_uuid: job.uuid,
-                event_type: "stderr",
-                properties: {"text" => "Log message after subscription"}}})
+    dispatch_log(owner_uuid: job['owner_uuid'],
+                 object_uuid: job['uuid'],
+                 event_type: "stderr",
+                 properties: {"text" => "Log message after subscription"})
     assert_text 'Log message after subscription'
   end
 
   test "test running job with too many previous log records" do
     Rails.configuration.running_job_log_records_to_fetch = 5
 
-    use_token :active
-    job = Job.where(uuid: api_fixture("jobs")['running']['uuid']).results.first
-
-    visit page_with_token("active", "/jobs/#{job.uuid}")
-
-    api = ArvadosApiClient.new
+    job = api_fixture("jobs")['running']
+    visit page_with_token("active", "/jobs/#{job['uuid']}")
 
     # Create Rails.configuration.running_job_log_records_to_fetch + 1 log records
     (0..Rails.configuration.running_job_log_records_to_fetch).each do |count|
-      api.api("logs", "", {log: {
-                object_uuid: job.uuid,
-                event_type: "stderr",
-                properties: {"text" => "Old log message #{count}"}}})
+      dispatch_log(owner_uuid: job['owner_uuid'],
+                   object_uuid: job['uuid'],
+                   event_type: "stderr",
+                   properties: {"text" => "Old log message #{count}"})
     end
 
     # Go to log tab, which results in subscribing to websockets
@@ -275,10 +248,11 @@ class WebsocketTest < ActionDispatch::IntegrationTest
     assert_no_text 'Old log message 0'
 
     # Create one more log record after subscription
-    api.api("logs", "", {log: {
-                object_uuid: job.uuid,
-                event_type: "stderr",
-                properties: {"text" => "Life goes on!"}}})
+    dispatch_log(owner_uuid: job['owner_uuid'],
+                 object_uuid: job['uuid'],
+                 event_type: "stderr",
+                 properties: {"text" => "Life goes on!"})
+
     # Expect it to show up in log tab
     assert_text 'Life goes on!'
   end

commit 262a16e15c0dcfa9245e9c8fd88d383f54f51471
Author: Tom Clegg <tom at curoverse.com>
Date:   Sat Aug 27 23:31:37 2016 -0400

    9799: Add missing container request, so container fixture is visible to test user.

diff --git a/services/api/test/fixtures/container_requests.yml b/services/api/test/fixtures/container_requests.yml
index c754de1..dcaf657 100644
--- a/services/api/test/fixtures/container_requests.yml
+++ b/services/api/test/fixtures/container_requests.yml
@@ -93,6 +93,25 @@ completed-older:
     vcpus: 1
     ram: 123
 
+requester:
+  uuid: zzzzz-xvhdp-9zacv3o1xw6sxz5
+  owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz
+  name: requester
+  state: Committed
+  priority: 1
+  created_at: 2016-01-11 11:11:11.111111111 Z
+  updated_at: 2016-01-11 11:11:11.111111111 Z
+  modified_at: 2016-01-11 11:11:11.111111111 Z
+  modified_by_user_uuid: zzzzz-tpzed-xurymjxw79nv3jz
+  container_image: test
+  cwd: /
+  output_path: /output
+  command: ["request-another-container", "echo", "hello"]
+  container_uuid: zzzzz-dz642-requestingcntnr
+  runtime_constraints:
+    vcpus: 1
+    ram: 123
+
 cr_for_requester:
   uuid: zzzzz-xvhdp-cr4requestercnt
   owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz

commit 661399e4fd26be1a932d94d0b2c419cd3a33a4f1
Author: Tom Clegg <tom at curoverse.com>
Date:   Fri Aug 26 23:34:14 2016 -0400

    9799: Clean up permission code and comments.

diff --git a/services/api/app/models/arvados_model.rb b/services/api/app/models/arvados_model.rb
index d8c99ec..8ae3e43 100644
--- a/services/api/app/models/arvados_model.rb
+++ b/services/api/app/models/arvados_model.rb
@@ -191,44 +191,42 @@ class ArvadosModel < ActiveRecord::Base
       return self
     end
 
-    # Collect the uuids for each user and any groups readable by each user.
+    # Collect the UUIDs of the authorized users.
     user_uuids = users_list.map { |u| u.uuid }
+
+    # Collect the UUIDs of all groups readable by any of the
+    # authorized users. If one of these (or the UUID of one of the
+    # authorized users themselves) is an object's owner_uuid, that
+    # object is readable.
     owner_uuids = user_uuids + users_list.flat_map { |u| u.groups_i_can(:read) }
+
     sql_conds = []
     sql_table = kwargs.fetch(:table_name, table_name)
-    or_object_uuid = ''
-
-    # This row is owned by a member of users_list, or owned by a group
-    # readable by a member of users_list
-    # or
-    # This row uuid is the uuid of a member of users_list
-    # or
-    # A permission link exists ('write' and 'manage' implicitly include
-    # 'read') from a member of users_list, or a group readable by users_list,
-    # to this row, or to the owner of this row (see join() below).
+
+    # Match any object (evidently a group or user) whose UUID is
+    # listed explicitly in owner_uuids.
     sql_conds += ["#{sql_table}.uuid in (:owner_uuids)"]
 
-    if owner_uuids.any?
-      permitted = "(SELECT head_uuid FROM links WHERE link_class='permission' AND tail_uuid IN (:owner_uuids))"
-      sql_conds += ["#{sql_table}.owner_uuid IN (:owner_uuids)",
-                    "#{sql_table}.uuid IN #{permitted}"]
-    end
+    # Match any object whose owner is listed explicitly in
+    # owner_uuids.
+    sql_conds += ["#{sql_table}.owner_uuid IN (:owner_uuids)"]
+
+    # Match the head of any permission link whose tail is listed
+    # explicitly in owner_uuids.
+    sql_conds += ["#{sql_table}.uuid IN (SELECT head_uuid FROM links WHERE link_class='permission' AND tail_uuid IN (:owner_uuids))"]
 
-    if sql_table == "links" and user_uuids.any?
-      # This row is a 'permission' or 'resources' link whose head or
-      # tail _is_ the acting user.
-      sql_conds += ["(#{sql_table}.link_class in (#{sanitize 'permission'}, #{sanitize 'resources'}) AND (#{sql_table}.head_uuid IN (:user_uuids) OR #{sql_table}.tail_uuid IN (:user_uuids)))"]
+    if sql_table == "links"
+      # Match any permission link that gives one of the authorized
+      # users some permission _or_ gives anyone else permission to
+      # view one of the authorized users.
+      sql_conds += ["(#{sql_table}.link_class in (:permission_link_classes) AND "+
+                    "(#{sql_table}.head_uuid IN (:user_uuids) OR #{sql_table}.tail_uuid IN (:user_uuids)))"]
     end
 
-    # Link head points to this row, or to the owner of this row (the
-    # thing to be read)
-    #
-    # Link tail originates from this user, or a group that is readable
-    # by this user (the identity with authorization to read)
-    #
-    # Link class is 'permission' ('write' and 'manage' implicitly
-    # include 'read')
-    where(sql_conds.join(' OR '), owner_uuids: owner_uuids, user_uuids: user_uuids)
+    where(sql_conds.join(' OR '),
+          owner_uuids: owner_uuids,
+          user_uuids: user_uuids,
+          permission_link_classes: ['permission', 'resources'])
   end
 
   def logged_attributes

commit 9fd1f52e97c96f9a0a0fc76b37520828f0d9221d
Author: Tom Clegg <tom at curoverse.com>
Date:   Fri Aug 26 23:16:15 2016 -0400

    9799: Fix test order dependency.

diff --git a/services/api/test/integration/permissions_test.rb b/services/api/test/integration/permissions_test.rb
index 723aa1b..e4db862 100644
--- a/services/api/test/integration/permissions_test.rb
+++ b/services/api/test/integration/permissions_test.rb
@@ -1,9 +1,14 @@
 require 'test_helper'
 
 class PermissionsTest < ActionDispatch::IntegrationTest
+  include DbCurrentTime
   include CurrentApiClient  # for empty_collection
   fixtures :users, :groups, :api_client_authorizations, :collections
 
+  teardown do
+    User.invalidate_permissions_cache db_current_time.to_i
+  end
+
   test "adding and removing direct can_read links" do
     # try to read collection as spectator
     get "/arvados/v1/collections/#{collections(:foo_file).uuid}", {:format => :json}, auth(:spectator)

commit 5497c52dae7a3832e75d8e414492d48df1192ddc
Author: Tom Clegg <tom at curoverse.com>
Date:   Fri Aug 26 23:06:11 2016 -0400

    9799: Remove redundant test.

diff --git a/services/api/test/integration/permissions_test.rb b/services/api/test/integration/permissions_test.rb
index 44b5e6e..723aa1b 100644
--- a/services/api/test/integration/permissions_test.rb
+++ b/services/api/test/integration/permissions_test.rb
@@ -341,11 +341,6 @@ class PermissionsTest < ActionDispatch::IntegrationTest
     assert_response 404
   end
 
-  test "get_permissions returns 404 for unreadable uuid" do
-    get "/arvados/v1/permissions/#{groups(:public).uuid}", nil, auth(:active)
-    assert_response 404
-  end
-
   test "get_permissions returns 403 if user can read but not manage" do
     post "/arvados/v1/links", {
       :link => {

commit 3d53281b9e3ba0840e5e3eaeb0371e0f50a345ad
Author: Tom Clegg <tom at curoverse.com>
Date:   Mon Aug 29 23:11:34 2016 -0400

    9799: Restore permission on Log entries via owner_uuid.

diff --git a/services/api/app/models/log.rb b/services/api/app/models/log.rb
index 5a58a55..5b3f544 100644
--- a/services/api/app/models/log.rb
+++ b/services/api/app/models/log.rb
@@ -65,6 +65,7 @@ class Log < ArvadosModel
             "container_requests.uuid IN (:uuids) OR "+
             "container_requests.owner_uuid IN (:uuids) OR "+
             "logs.object_uuid IN (:uuids) OR "+
+            "logs.owner_uuid IN (:uuids) OR "+
             "logs.object_owner_uuid IN (:uuids)",
             uuids: uuid_list)
   end

commit 61ee10791b2b1f3724e6a8736c93161a625b5246
Author: Tom Clegg <tom at curoverse.com>
Date:   Fri Aug 26 23:06:01 2016 -0400

    9799: Dry up SQL statements using named bind parameters.

diff --git a/services/api/app/models/arvados_model.rb b/services/api/app/models/arvados_model.rb
index 304be0b..d8c99ec 100644
--- a/services/api/app/models/arvados_model.rb
+++ b/services/api/app/models/arvados_model.rb
@@ -193,9 +193,8 @@ class ArvadosModel < ActiveRecord::Base
 
     # Collect the uuids for each user and any groups readable by each user.
     user_uuids = users_list.map { |u| u.uuid }
-    uuid_list = user_uuids + users_list.flat_map { |u| u.groups_i_can(:read) }
+    owner_uuids = user_uuids + users_list.flat_map { |u| u.groups_i_can(:read) }
     sql_conds = []
-    sql_params = []
     sql_table = kwargs.fetch(:table_name, table_name)
     or_object_uuid = ''
 
@@ -207,25 +206,18 @@ class ArvadosModel < ActiveRecord::Base
     # A permission link exists ('write' and 'manage' implicitly include
     # 'read') from a member of users_list, or a group readable by users_list,
     # to this row, or to the owner of this row (see join() below).
-    sql_conds += ["#{sql_table}.uuid in (?)"]
-    sql_params += [user_uuids]
+    sql_conds += ["#{sql_table}.uuid in (:owner_uuids)"]
 
-    if uuid_list.any?
-      sql_conds += ["#{sql_table}.owner_uuid in (?)"]
-      sql_params += [uuid_list]
-
-      sanitized_uuid_list = uuid_list.
-        collect { |uuid| sanitize(uuid) }.join(', ')
-      permitted_uuids = "(SELECT head_uuid FROM links WHERE link_class='permission' AND tail_uuid IN (#{sanitized_uuid_list}))"
-      sql_conds += ["#{sql_table}.uuid IN #{permitted_uuids}"]
+    if owner_uuids.any?
+      permitted = "(SELECT head_uuid FROM links WHERE link_class='permission' AND tail_uuid IN (:owner_uuids))"
+      sql_conds += ["#{sql_table}.owner_uuid IN (:owner_uuids)",
+                    "#{sql_table}.uuid IN #{permitted}"]
     end
 
-    if sql_table == "links" and users_list.any?
-      # This row is a 'permission' or 'resources' link class
-      # The uuid for a member of users_list is referenced in either the head
-      # or tail of the link
-      sql_conds += ["(#{sql_table}.link_class in (#{sanitize 'permission'}, #{sanitize 'resources'}) AND (#{sql_table}.head_uuid IN (?) OR #{sql_table}.tail_uuid IN (?)))"]
-      sql_params += [user_uuids, user_uuids]
+    if sql_table == "links" and user_uuids.any?
+      # This row is a 'permission' or 'resources' link whose head or
+      # tail _is_ the acting user.
+      sql_conds += ["(#{sql_table}.link_class in (#{sanitize 'permission'}, #{sanitize 'resources'}) AND (#{sql_table}.head_uuid IN (:user_uuids) OR #{sql_table}.tail_uuid IN (:user_uuids)))"]
     end
 
     # Link head points to this row, or to the owner of this row (the
@@ -236,7 +228,7 @@ class ArvadosModel < ActiveRecord::Base
     #
     # Link class is 'permission' ('write' and 'manage' implicitly
     # include 'read')
-    where(sql_conds.join(' OR '), *sql_params)
+    where(sql_conds.join(' OR '), owner_uuids: owner_uuids, user_uuids: user_uuids)
   end
 
   def logged_attributes
diff --git a/services/api/app/models/container.rb b/services/api/app/models/container.rb
index ae4d983..f73c8b7 100644
--- a/services/api/app/models/container.rb
+++ b/services/api/app/models/container.rb
@@ -82,9 +82,11 @@ class Container < ArvadosModel
     end
     user_uuids = users_list.map { |u| u.uuid }
     uuid_list = user_uuids + users_list.flat_map { |u| u.groups_i_can(:read) }
-    permitted_uuids = "(SELECT head_uuid FROM links WHERE link_class='permission' AND tail_uuid IN (?))"
-    joins(:container_requests).where("container_requests.uuid IN #{permitted_uuids} OR container_requests.owner_uuid IN (?)",
-                                     uuid_list, uuid_list)
+    permitted = "(SELECT head_uuid FROM links WHERE link_class='permission' AND tail_uuid IN (:uuids))"
+    joins(:container_requests).
+      where("container_requests.uuid IN #{permitted} OR "+
+            "container_requests.owner_uuid IN (:uuids)",
+            uuids: uuid_list)
   end
 
   protected
diff --git a/services/api/app/models/log.rb b/services/api/app/models/log.rb
index 7a8b50a..5a58a55 100644
--- a/services/api/app/models/log.rb
+++ b/services/api/app/models/log.rb
@@ -59,10 +59,14 @@ class Log < ArvadosModel
     end
     user_uuids = users_list.map { |u| u.uuid }
     uuid_list = user_uuids + users_list.flat_map { |u| u.groups_i_can(:read) }
-    permitted_uuids = "(SELECT head_uuid FROM links WHERE link_class='permission' AND tail_uuid IN (?))"
+    permitted = "(SELECT head_uuid FROM links WHERE link_class='permission' AND tail_uuid IN (:uuids))"
     joins("LEFT JOIN container_requests ON container_requests.container_uuid=logs.object_uuid").
-      where("logs.object_uuid IN #{permitted_uuids} OR container_requests.uuid IN (?)  OR container_requests.owner_uuid IN (?) OR logs.object_uuid IN (?) OR logs.object_owner_uuid IN (?)",
-            uuid_list, uuid_list, uuid_list, uuid_list, uuid_list)
+      where("logs.object_uuid IN #{permitted} OR "+
+            "container_requests.uuid IN (:uuids) OR "+
+            "container_requests.owner_uuid IN (:uuids) OR "+
+            "logs.object_uuid IN (:uuids) OR "+
+            "logs.object_owner_uuid IN (:uuids)",
+            uuids: uuid_list)
   end
 
   protected

commit 87cb6b04df6f71d5bce9b0b3c1257e0b5082668d
Author: Tom Clegg <tom at curoverse.com>
Date:   Fri Aug 26 21:46:10 2016 -0400

    9799: Update test: "spectator" user is now allowed to read log entries about itself.

diff --git a/services/api/test/fixtures/logs.yml b/services/api/test/fixtures/logs.yml
index 9179e6d..2f45d69 100644
--- a/services/api/test/fixtures/logs.yml
+++ b/services/api/test/fixtures/logs.yml
@@ -1,7 +1,9 @@
-noop:
+noop: # nothing happened ...to the 'spectator' user
   id: 1
   uuid: zzzzz-xxxxx-pshmckwoma9plh7
+  owner_uuid: zzzzz-tpzed-000000000000000
   object_uuid: zzzzz-tpzed-l1s2piq4t4mps8r
+  object_owner_uuid: zzzzz-tpzed-000000000000000
   event_at: <%= 1.minute.ago.to_s(:db) %>
 
 admin_changes_repository2: # admin changes repository2, which is owned by active user
diff --git a/services/api/test/unit/log_test.rb b/services/api/test/unit/log_test.rb
index fd71576..632271e 100644
--- a/services/api/test/unit/log_test.rb
+++ b/services/api/test/unit/log_test.rb
@@ -253,7 +253,8 @@ class LogTest < ActiveSupport::TestCase
                                       :crunchstat_for_running_job] # log & job owned by active
 
     c = Log.readable_by(users(:spectator)).order("id asc").each.to_a
-    assert_log_result c, known_logs, [:admin_changes_specimen, # owned by spectator
+    assert_log_result c, known_logs, [:noop,                   # object_uuid is spectator
+                                      :admin_changes_specimen, # object_uuid is a specimen owned by spectator
                                       :system_adds_baz] # readable via 'all users' group
   end
 

commit 2bc21107e3fa6c4ecea7efb22e4dfc7e30b3233d
Author: Tom Clegg <tom at curoverse.com>
Date:   Fri Aug 26 21:45:17 2016 -0400

    9799: Permit read access to containers via container requests. Move Log- and Container-specific permission queries to log.rb and container.rb.

diff --git a/services/api/app/models/arvados_model.rb b/services/api/app/models/arvados_model.rb
index 16f0343..304be0b 100644
--- a/services/api/app/models/arvados_model.rb
+++ b/services/api/app/models/arvados_model.rb
@@ -228,15 +228,6 @@ class ArvadosModel < ActiveRecord::Base
       sql_params += [user_uuids, user_uuids]
     end
 
-    if sql_table == "logs" and users_list.any?
-      # Link head points to the object described by this row
-      sql_conds += ["#{sql_table}.object_uuid IN #{permitted_uuids}"]
-
-      # This object described by this row is owned by this user, or owned by a group readable by this user
-      sql_conds += ["#{sql_table}.object_owner_uuid in (?)"]
-      sql_params += [uuid_list]
-    end
-
     # Link head points to this row, or to the owner of this row (the
     # thing to be read)
     #
diff --git a/services/api/app/models/container.rb b/services/api/app/models/container.rb
index 4c77008..ae4d983 100644
--- a/services/api/app/models/container.rb
+++ b/services/api/app/models/container.rb
@@ -76,6 +76,17 @@ class Container < ArvadosModel
     end
   end
 
+  def self.readable_by *users_list
+    if users_list.select { |u| u.is_admin }.any?
+      return self
+    end
+    user_uuids = users_list.map { |u| u.uuid }
+    uuid_list = user_uuids + users_list.flat_map { |u| u.groups_i_can(:read) }
+    permitted_uuids = "(SELECT head_uuid FROM links WHERE link_class='permission' AND tail_uuid IN (?))"
+    joins(:container_requests).where("container_requests.uuid IN #{permitted_uuids} OR container_requests.owner_uuid IN (?)",
+                                     uuid_list, uuid_list)
+  end
+
   protected
 
   def fill_field_defaults
diff --git a/services/api/app/models/log.rb b/services/api/app/models/log.rb
index b10a491..7a8b50a 100644
--- a/services/api/app/models/log.rb
+++ b/services/api/app/models/log.rb
@@ -53,6 +53,18 @@ class Log < ArvadosModel
     self
   end
 
+  def self.readable_by *users_list
+    if users_list.select { |u| u.is_admin }.any?
+      return self
+    end
+    user_uuids = users_list.map { |u| u.uuid }
+    uuid_list = user_uuids + users_list.flat_map { |u| u.groups_i_can(:read) }
+    permitted_uuids = "(SELECT head_uuid FROM links WHERE link_class='permission' AND tail_uuid IN (?))"
+    joins("LEFT JOIN container_requests ON container_requests.container_uuid=logs.object_uuid").
+      where("logs.object_uuid IN #{permitted_uuids} OR container_requests.uuid IN (?)  OR container_requests.owner_uuid IN (?) OR logs.object_uuid IN (?) OR logs.object_owner_uuid IN (?)",
+            uuid_list, uuid_list, uuid_list, uuid_list, uuid_list)
+  end
+
   protected
 
   def permission_to_create
diff --git a/services/api/lib/eventbus.rb b/services/api/lib/eventbus.rb
index e7f2bb1..16bb030 100644
--- a/services/api/lib/eventbus.rb
+++ b/services/api/lib/eventbus.rb
@@ -143,7 +143,7 @@ class EventBus
         #
         # Note: find_each implies order('id asc'), which is what we
         # want.
-        logs.select(:id).find_each do |l|
+        logs.select('logs.id').find_each do |l|
           if not ws.sent_ids.include?(l.id)
             # only send if not a duplicate
             ws.send(Log.find(l.id).as_api_response.to_json)

commit 71ec472aa11b47a58beb3b050fee38244674869e
Author: Tom Clegg <tom at curoverse.com>
Date:   Fri Aug 26 21:03:57 2016 -0400

    9799: Add tests for container permissions.

diff --git a/services/api/test/unit/container_request_test.rb b/services/api/test/unit/container_request_test.rb
index 3ab4a89..ebd6a5a 100644
--- a/services/api/test/unit/container_request_test.rb
+++ b/services/api/test/unit/container_request_test.rb
@@ -389,4 +389,10 @@ class ContainerRequestTest < ActiveSupport::TestCase
       end
     end
   end
+
+  test "requestor can retrieve container owned by dispatch" do
+    assert_not_empty Container.readable_by(users(:admin)).where(uuid: containers(:running).uuid)
+    assert_not_empty Container.readable_by(users(:active)).where(uuid: containers(:running).uuid)
+    assert_empty Container.readable_by(users(:spectator)).where(uuid: containers(:running).uuid)
+  end
 end

commit 579195def22d6b02f7484933d6db065bc33088d9
Author: Tom Clegg <tom at curoverse.com>
Date:   Fri Aug 26 17:34:25 2016 -0400

    9799: Add tests for container log permissions.

diff --git a/services/api/test/fixtures/container_requests.yml b/services/api/test/fixtures/container_requests.yml
index 433aff2..c754de1 100644
--- a/services/api/test/fixtures/container_requests.yml
+++ b/services/api/test/fixtures/container_requests.yml
@@ -36,7 +36,7 @@ running:
     vcpus: 1
     ram: 123
 
-running-older:
+running_older:
   uuid: zzzzz-xvhdp-cr4runningcntn2
   owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz
   name: running
diff --git a/services/api/test/fixtures/containers.yml b/services/api/test/fixtures/containers.yml
index bf9f84e..2e3021d 100644
--- a/services/api/test/fixtures/containers.yml
+++ b/services/api/test/fixtures/containers.yml
@@ -31,7 +31,7 @@ running:
     vcpus: 4
   auth_uuid: zzzzz-gj3su-077z32aux8dg2s1
 
-running-older:
+running_older:
   uuid: zzzzz-dz642-runningcontain2
   owner_uuid: zzzzz-tpzed-000000000000000
   state: Running
diff --git a/services/api/test/unit/permission_test.rb b/services/api/test/unit/permission_test.rb
index 4a6ddc6..5bc296a 100644
--- a/services/api/test/unit/permission_test.rb
+++ b/services/api/test/unit/permission_test.rb
@@ -353,4 +353,27 @@ class PermissionTest < ActiveSupport::TestCase
       ob.update_attributes!(owner_uuid: groups(:aproject).uuid)
     end
   end
+
+  def container_logs container, user
+    Log.readable_by(users(user)).
+      where(object_uuid: containers(container).uuid, event_type: "test")
+  end
+
+  test "container logs created by dispatch are visible to container requestor" do
+    set_user_from_auth :dispatch1
+    Log.create!(object_uuid: containers(:running).uuid,
+                event_type: "test")
+
+    assert_not_empty container_logs(:running, :admin)
+    assert_not_empty container_logs(:running, :active)
+    assert_empty container_logs(:running, :spectator)
+  end
+
+  test "container logs created by dispatch are public if container request is public" do
+    set_user_from_auth :dispatch1
+    Log.create!(object_uuid: containers(:running_older).uuid,
+                event_type: "test")
+
+    assert_not_empty container_logs(:running_older, :anonymous)
+  end
 end

commit 08224a6abb60ff61f3967abc9665f50f9157791b
Author: Tom Clegg <tom at curoverse.com>
Date:   Fri Aug 26 17:09:42 2016 -0400

    9799: Fix container fixture owner_uuid attributes to look like real-life containers.

diff --git a/services/api/test/fixtures/containers.yml b/services/api/test/fixtures/containers.yml
index 049cd3c..bf9f84e 100644
--- a/services/api/test/fixtures/containers.yml
+++ b/services/api/test/fixtures/containers.yml
@@ -1,6 +1,6 @@
 queued:
   uuid: zzzzz-dz642-queuedcontainer
-  owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz
+  owner_uuid: zzzzz-tpzed-000000000000000
   state: Queued
   priority: 1
   created_at: 2016-01-11 11:11:11.111111111 Z
@@ -16,8 +16,7 @@ queued:
 
 running:
   uuid: zzzzz-dz642-runningcontainr
-  owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz
-  state: Running
+  owner_uuid: zzzzz-tpzed-000000000000000
   priority: 1
   created_at: <%= 1.minute.ago.to_s(:db) %>
   updated_at: <%= 1.minute.ago.to_s(:db) %>
@@ -34,7 +33,7 @@ running:
 
 running-older:
   uuid: zzzzz-dz642-runningcontain2
-  owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz
+  owner_uuid: zzzzz-tpzed-000000000000000
   state: Running
   priority: 1
   created_at: <%= 2.minute.ago.to_s(:db) %>
@@ -51,7 +50,7 @@ running-older:
 
 locked:
   uuid: zzzzz-dz642-lockedcontainer
-  owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz
+  owner_uuid: zzzzz-tpzed-000000000000000
   state: Locked
   priority: 2
   created_at: <%= 2.minute.ago.to_s(:db) %>
@@ -67,7 +66,7 @@ locked:
 
 completed:
   uuid: zzzzz-dz642-compltcontainer
-  owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz
+  owner_uuid: zzzzz-tpzed-000000000000000
   state: Complete
   exit_code: 0
   priority: 1
@@ -87,7 +86,7 @@ completed:
 
 completed_older:
   uuid: zzzzz-dz642-compltcontainr2
-  owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz
+  owner_uuid: zzzzz-tpzed-000000000000000
   state: Complete
   exit_code: 0
   priority: 1
@@ -106,7 +105,7 @@ completed_older:
 
 requester:
   uuid: zzzzz-dz642-requestingcntnr
-  owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz
+  owner_uuid: zzzzz-tpzed-000000000000000
   state: Complete
   exit_code: 0
   priority: 1
@@ -123,7 +122,7 @@ requester:
 
 requester_container:
   uuid: zzzzz-dz642-requestercntnr1
-  owner_uuid: zzzzz-tpzed-xurymjxw79nv3jz
+  owner_uuid: zzzzz-tpzed-000000000000000
   state: Complete
   exit_code: 0
   priority: 1

commit 08262a4e18c0b3b65946878058e9546823b82535
Author: Tom Clegg <tom at curoverse.com>
Date:   Fri Aug 19 11:14:03 2016 -0400

    9799: Use regular (non-admin) user in Workbench websocket tests.

diff --git a/apps/workbench/test/integration/websockets_test.rb b/apps/workbench/test/integration/websockets_test.rb
index e9f5a79..e302a39 100644
--- a/apps/workbench/test/integration/websockets_test.rb
+++ b/apps/workbench/test/integration/websockets_test.rb
@@ -6,20 +6,20 @@ class WebsocketTest < ActionDispatch::IntegrationTest
   end
 
   test "test page" do
-    visit(page_with_token("admin", "/websockets"))
+    visit(page_with_token("active", "/websockets"))
     fill_in("websocket-message-content", :with => "Stuff")
     click_button("Send")
     assert_text '"status":400'
   end
 
   test "test live logging" do
-    visit(page_with_token("admin", "/pipeline_instances/zzzzz-d1hrv-9fm8l10i9z2kqc6"))
+    visit(page_with_token("active", "/pipeline_instances/zzzzz-d1hrv-9fm8l10i9z2kqc6"))
     click_link("Log")
     assert_no_text '123 hello'
 
     api = ArvadosApiClient.new
 
-    Thread.current[:arvados_api_token] = @@API_AUTHS["admin"]['api_token']
+    use_token :active
     api.api("logs", "", {log: {
                 object_uuid: "zzzzz-d1hrv-9fm8l10i9z2kqc6",
                 event_type: "stderr",
@@ -32,14 +32,12 @@ class WebsocketTest < ActionDispatch::IntegrationTest
    ["jobs", api_fixture("jobs")['running']['uuid']],
    ["containers", api_fixture("containers")['running']['uuid']],
    ["container_requests", api_fixture("container_requests")['running']['uuid'], api_fixture("containers")['running']['uuid']],
-  ].each do |c|
-    test "test live logging scrolling #{c[0]}" do
+  ].each do |controller, uuid, log_uuid|
+    log_uuid = log_uuid || uuid
 
-      controller = c[0]
-      uuid = c[1]
-      log_uuid = c[2] || c[1]
+    test "test live logging scrolling for #{controller}" do
 
-      visit(page_with_token("admin", "/#{controller}/#{uuid}"))
+      visit(page_with_token("active", "/#{controller}/#{uuid}"))
       click_link("Log")
       assert_no_text '123 hello'
 
@@ -50,11 +48,12 @@ class WebsocketTest < ActionDispatch::IntegrationTest
         text << "#{i} hello\n"
       end
 
-      Thread.current[:arvados_api_token] = @@API_AUTHS["admin"]['api_token']
-      api.api("logs", "", {log: {
-                  object_uuid: log_uuid,
-                  event_type: "stderr",
-                  properties: {"text" => text}}})
+      use_token :dispatch1 do
+        api.api("logs", "", {log: {
+                    object_uuid: log_uuid,
+                    event_type: "stderr",
+                    properties: {"text" => text}}})
+      end
       assert_text '1000 hello'
 
       # First test that when we're already at the bottom of the page, it scrolls down
@@ -87,7 +86,7 @@ class WebsocketTest < ActionDispatch::IntegrationTest
   end
 
   test "pipeline instance arv-refresh-on-log-event" do
-    Thread.current[:arvados_api_token] = @@API_AUTHS["admin"]['api_token']
+    use_token :active
     # Do something and check that the pane reloads.
     p = PipelineInstance.create({state: "RunningOnServer",
                                   components: {
@@ -98,15 +97,17 @@ class WebsocketTest < ActionDispatch::IntegrationTest
                                   }
                                 })
 
-    visit(page_with_token("admin", "/pipeline_instances/#{p.uuid}"))
+    visit(page_with_token("active", "/pipeline_instances/#{p.uuid}"))
 
     assert_text 'Active'
     assert page.has_link? 'Pause'
     assert_no_text 'Complete'
     assert page.has_no_link? 'Re-run with latest'
 
-    p.state = "Complete"
-    p.save!
+    use_token :admin do
+      p.state = "Complete"
+      p.save!
+    end
 
     assert_no_text 'Active'
     assert page.has_no_link? 'Pause'
@@ -115,26 +116,28 @@ class WebsocketTest < ActionDispatch::IntegrationTest
   end
 
   test "job arv-refresh-on-log-event" do
-    Thread.current[:arvados_api_token] = @@API_AUTHS["admin"]['api_token']
+    use_token :active
     # Do something and check that the pane reloads.
     p = Job.where(uuid: api_fixture('jobs')['running_will_be_completed']['uuid']).results.first
 
-    visit(page_with_token("admin", "/jobs/#{p.uuid}"))
+    visit(page_with_token("active", "/jobs/#{p.uuid}"))
 
     assert_no_text 'complete'
     assert_no_text 'Re-run job'
 
-    p.state = "Complete"
-    p.save!
+    use_token :admin do
+      p.state = "Complete"
+      p.save!
+    end
 
     assert_text 'complete'
     assert_text 'Re-run job'
   end
 
   test "dashboard arv-refresh-on-log-event" do
-    Thread.current[:arvados_api_token] = @@API_AUTHS["admin"]['api_token']
+    use_token :active
 
-    visit(page_with_token("admin", "/"))
+    visit(page_with_token("active", "/"))
 
     assert_no_text 'test dashboard arv-refresh-on-log-event'
 
@@ -217,9 +220,9 @@ class WebsocketTest < ActionDispatch::IntegrationTest
   end
 
   test "test running job with just a few previous log records" do
-    Thread.current[:arvados_api_token] = @@API_AUTHS["admin"]['api_token']
+    use_token :active
     job = Job.where(uuid: api_fixture("jobs")['running']['uuid']).results.first
-    visit page_with_token("admin", "/jobs/#{job.uuid}")
+    visit page_with_token("active", "/jobs/#{job.uuid}")
 
     api = ArvadosApiClient.new
 
@@ -246,10 +249,10 @@ class WebsocketTest < ActionDispatch::IntegrationTest
   test "test running job with too many previous log records" do
     Rails.configuration.running_job_log_records_to_fetch = 5
 
-    Thread.current[:arvados_api_token] = @@API_AUTHS["admin"]['api_token']
+    use_token :active
     job = Job.where(uuid: api_fixture("jobs")['running']['uuid']).results.first
 
-    visit page_with_token("admin", "/jobs/#{job.uuid}")
+    visit page_with_token("active", "/jobs/#{job.uuid}")
 
     api = ArvadosApiClient.new
 

commit 95e6adc8ac2c9449aba651ef0d932cd7d27aea5e
Author: Tom Clegg <tom at curoverse.com>
Date:   Fri Aug 19 09:29:58 2016 -0400

    9799: Use regular (non-admin) user in websocket integration tests.

diff --git a/services/api/test/integration/websocket_test.rb b/services/api/test/integration/websocket_test.rb
index 0c99fcc..99ca7ac 100644
--- a/services/api/test/integration/websocket_test.rb
+++ b/services/api/test/integration/websocket_test.rb
@@ -69,7 +69,7 @@ class WebsocketTest < ActionDispatch::IntegrationTest
   test "connect, subscribe and get response" do
     status = nil
 
-    ws_helper :admin do |ws|
+    ws_helper :active do |ws|
       ws.on :open do |event|
         ws.send ({method: 'subscribe'}.to_json)
       end
@@ -89,9 +89,9 @@ class WebsocketTest < ActionDispatch::IntegrationTest
     spec = nil
     ev_uuid = nil
 
-    authorize_with :admin
+    authorize_with :active
 
-    ws_helper :admin do |ws|
+    ws_helper :active do |ws|
       ws.on :open do |event|
         ws.send ({method: 'subscribe'}.to_json)
       end
@@ -126,9 +126,9 @@ class WebsocketTest < ActionDispatch::IntegrationTest
     spec_ev_uuid = nil
     human_ev_uuid = nil
 
-    authorize_with :admin
+    authorize_with :active
 
-    ws_helper :admin do |ws|
+    ws_helper :active do |ws|
       ws.on :open do |event|
         ws.send ({method: 'subscribe'}.to_json)
       end
@@ -166,9 +166,9 @@ class WebsocketTest < ActionDispatch::IntegrationTest
     human = nil
     human_ev_uuid = nil
 
-    authorize_with :admin
+    authorize_with :active
 
-    ws_helper :admin do |ws|
+    ws_helper :active do |ws|
       ws.on :open do |event|
         ws.send ({method: 'subscribe', filters: [['object_uuid', 'is_a', 'arvados#human']]}.to_json)
       end
@@ -204,9 +204,9 @@ class WebsocketTest < ActionDispatch::IntegrationTest
     spec_ev_uuid = nil
     human_ev_uuid = nil
 
-    authorize_with :admin
+    authorize_with :active
 
-    ws_helper :admin do |ws|
+    ws_helper :active do |ws|
       ws.on :open do |event|
         ws.send ({method: 'subscribe', filters: [['object_uuid', 'is_a', 'arvados#human']]}.to_json)
         ws.send ({method: 'subscribe', filters: [['object_uuid', 'is_a', 'arvados#specimen']]}.to_json)
@@ -249,9 +249,9 @@ class WebsocketTest < ActionDispatch::IntegrationTest
     state = 1
     t1 = nil
 
-    authorize_with :admin
+    authorize_with :active
 
-    ws_helper :admin do |ws|
+    ws_helper :active do |ws|
       ws.on :open do |event|
         ws.send ({method: 'subscribe', filters: [['object_uuid', 'is_a', 'arvados#trait'], ['event_type', '=', 'update']]}.to_json)
       end
@@ -285,13 +285,13 @@ class WebsocketTest < ActionDispatch::IntegrationTest
     human = nil
     human_ev_uuid = nil
 
-    authorize_with :admin
+    authorize_with :active
 
     lastid = logs(:admin_changes_specimen).id
     l1 = nil
     l2 = nil
 
-    ws_helper :admin do |ws|
+    ws_helper :active do |ws|
       ws.on :open do |event|
         ws.send ({method: 'subscribe', last_log_id: lastid}.to_json)
       end
@@ -329,9 +329,9 @@ class WebsocketTest < ActionDispatch::IntegrationTest
     spec_ev_uuid = nil
     filter_id = nil
 
-    authorize_with :admin
+    authorize_with :active
 
-    ws_helper :admin, false do |ws|
+    ws_helper :active, false do |ws|
       ws.on :open do |event|
         ws.send ({method: 'subscribe'}.to_json)
         EM::Timer.new 3 do
@@ -378,9 +378,9 @@ class WebsocketTest < ActionDispatch::IntegrationTest
     spec = nil
     spec_ev_uuid = nil
 
-    authorize_with :admin
+    authorize_with :active
 
-    ws_helper :admin, false do |ws|
+    ws_helper :active, false do |ws|
       ws.on :open do |event|
         ws.send ({method: 'subscribe', filters: [['object_uuid', 'is_a', 'arvados#human']]}.to_json)
         EM::Timer.new 6 do
@@ -430,9 +430,9 @@ class WebsocketTest < ActionDispatch::IntegrationTest
     human = nil
     human_ev_uuid = nil
 
-    authorize_with :admin
+    authorize_with :active
 
-    ws_helper :admin do |ws|
+    ws_helper :active do |ws|
       ws.on :open do |event|
         ws.send ({method: 'subscribe'}.to_json)
       end
@@ -477,9 +477,9 @@ class WebsocketTest < ActionDispatch::IntegrationTest
 
   test "connected, not subscribed, no event" do
     slow_test
-    authorize_with :admin
+    authorize_with :active
 
-    ws_helper :admin, false do |ws|
+    ws_helper :active, false do |ws|
       ws.on :open do |event|
         EM::Timer.new 1 do
           Specimen.create
@@ -530,7 +530,7 @@ class WebsocketTest < ActionDispatch::IntegrationTest
   test "connect, try bogus method" do
     status = nil
 
-    ws_helper :admin do |ws|
+    ws_helper :active do |ws|
       ws.on :open do |event|
         ws.send ({method: 'frobnabble'}.to_json)
       end
@@ -548,7 +548,7 @@ class WebsocketTest < ActionDispatch::IntegrationTest
   test "connect, missing method" do
     status = nil
 
-    ws_helper :admin do |ws|
+    ws_helper :active do |ws|
       ws.on :open do |event|
         ws.send ({fizzbuzz: 'frobnabble'}.to_json)
       end
@@ -566,7 +566,7 @@ class WebsocketTest < ActionDispatch::IntegrationTest
   test "connect, send malformed request" do
     status = nil
 
-    ws_helper :admin do |ws|
+    ws_helper :active do |ws|
       ws.on :open do |event|
         ws.send '<XML4EVER></XML4EVER>'
       end
@@ -585,9 +585,9 @@ class WebsocketTest < ActionDispatch::IntegrationTest
   test "connect, try subscribe too many filters" do
     state = 1
 
-    authorize_with :admin
+    authorize_with :active
 
-    ws_helper :admin do |ws|
+    ws_helper :active do |ws|
       ws.on :open do |event|
         (1..17).each do |i|
           ws.send ({method: 'subscribe', filters: [['object_uuid', '=', i]]}.to_json)
@@ -618,9 +618,9 @@ class WebsocketTest < ActionDispatch::IntegrationTest
     event_count = 0
     log_start = Log.order(:id).last.id
 
-    authorize_with :admin
+    authorize_with :active
 
-    ws_helper :admin, false do |ws|
+    ws_helper :active, false do |ws|
       EM::Timer.new 45 do
         # Needs a longer timeout than the default
         ws.close
@@ -661,9 +661,9 @@ class WebsocketTest < ActionDispatch::IntegrationTest
     human = nil
     human_ev_uuid = nil
 
-    authorize_with :admin
+    authorize_with :active
 
-    ws_helper :admin do |ws|
+    ws_helper :active do |ws|
       ws.on :open do |event|
         # test that #6451 is fixed (invalid filter crashes websockets)
         ws.send ({method: 'subscribe', filters: [['object_blarg', 'is_a', 'arvados#human']]}.to_json)

-----------------------------------------------------------------------


hooks/post-receive
-- 




More information about the arvados-commits mailing list