Merge branch 'master' into 2375-log-table
authorBrett Smith <brett@curoverse.com>
Thu, 10 Apr 2014 14:05:28 +0000 (10:05 -0400)
committerBrett Smith <brett@curoverse.com>
Thu, 10 Apr 2014 14:05:28 +0000 (10:05 -0400)
22 files changed:
apps/workbench/Gemfile
apps/workbench/Gemfile.lock
apps/workbench/README.textile
apps/workbench/app/assets/javascripts/application.js
apps/workbench/app/controllers/users_controller.rb
apps/workbench/app/models/user.rb
apps/workbench/app/views/application/index.html.erb
apps/workbench/app/views/layouts/application.html.erb
apps/workbench/app/views/users/_setup_popup.html.erb [new file with mode: 0644]
apps/workbench/app/views/users/_show_admin.html.erb
apps/workbench/app/views/users/setup.js.erb [new file with mode: 0644]
apps/workbench/app/views/users/setup_popup.js.erb [new file with mode: 0644]
apps/workbench/config/application.default.yml
apps/workbench/config/routes.rb
apps/workbench/test/integration/users_test.rb [new file with mode: 0644]
sdk/cli/bin/crunch-job
services/api/app/controllers/arvados/v1/users_controller.rb
services/api/app/models/user.rb
services/api/config/database.yml.sample
services/api/test/fixtures/jobs.yml
services/api/test/functional/arvados/v1/users_controller_test.rb
services/api/test/unit/user_test.rb

index b273d9191c875417a9edd5cf90f8ffdf305a007a..1e43d1c522190d7599f5fe4bf9c4c6a1caa193df 100644 (file)
@@ -28,6 +28,7 @@ group :test do
   gem 'selenium-webdriver'
   gem 'capybara'
   gem 'poltergeist'
+  gem 'capybara-webkit'
 end
 
 gem 'jquery-rails'
@@ -59,4 +60,4 @@ gem 'RedCloth'
 gem 'piwik_analytics'
 gem 'httpclient'
 gem 'themes_for_rails'
-gem "deep_merge", :require => 'deep_merge/rails_compat'
\ No newline at end of file
+gem "deep_merge", :require => 'deep_merge/rails_compat'
index 0c65ca80ffb3d764d6446d4ce714e551a90eb3b1..0795f752db7ee4d40a94f47d6addd27382fb75b2 100644 (file)
@@ -48,6 +48,9 @@ GEM
       rack (>= 1.0.0)
       rack-test (>= 0.5.4)
       xpath (~> 2.0)
+    capybara-webkit (1.1.0)
+      capybara (~> 2.0, >= 2.0.2)
+      json
     childprocess (0.5.1)
       ffi (~> 1.0, >= 1.0.11)
     cliver (0.3.2)
@@ -182,6 +185,7 @@ DEPENDENCIES
   bootstrap-sass (~> 3.1.0)
   bootstrap-x-editable-rails
   capybara
+  capybara-webkit
   coffee-rails (~> 3.2.0)
   deep_merge
   httpclient
index ea01724b075befb352c6e7ccc9950ce7436a6ec5..00588e8e8a79bd46bb6c5b785cce21694a3eff0f 100644 (file)
@@ -6,8 +6,22 @@ h2. Running tests
 
 The Workbench application includes a series of integration tests.  When you run these, it starts the API server in a test environment, with all of its fixtures loaded, then tests Workbench by starting that server and making requests against it.
 
+Before running @bundle install@, make sure you install QT development dependencies (otherwise, capybara-webkit installation will fail). For example, on a Debian or Ubuntu system:
+
+<pre>
+arvados/apps/workbench$ sudo apt-get install qt4-qmake libqt4-dev
+arvados/apps/workbench$ RAILS_ENV=test bundle install
+</pre>
+
 In addition to bundled gems, running the integration tests requires "PhantomJS":http://phantomjs.org/download.html to test JavaScript elements.  The simplest way to get started is to download one of the binary builds provided, and install the executable into one of the directories in your @$PATH@.
 
+<pre>
+$ cd /tmp
+/tmp$ wget https://bitbucket.org/ariya/phantomjs/downloads/phantomjs-1.9.7-linux-x86_64.tar.bz2
+/tmp$ tar xjf phantomjs-1.9.7-linux-x86_64.tar.bz2
+/tmp$ sudo cp -ip phantomjs-1.9.7-linux-x86_64/bin/phantomjs /usr/local/bin/
+</pre>
+
 If you install the Workbench Bundle in deployment mode, you must also install the API server Bundle in deployment mode, and vice versa.  If your Bundle installs have mismatched modes, the integration tests will fail with "Gem not found" errors.
 
 h2. Writing tests
index e7884b95165173bdce213624172957085e05c737..3ad7944385b82a6f2a7a668334b0cc41107a7411 100644 (file)
@@ -18,6 +18,7 @@
 //= require bootstrap/tooltip
 //= require bootstrap/popover
 //= require bootstrap/collapse
+//= require bootstrap/modal
 //= require bootstrap3-editable/bootstrap-editable
 //= require_tree .
 
index 1610653b87c3f16f98110b5f8a12e0dcf7935ab2..5ace8d68193d50cd278d87167fdfaede3194c8c5 100644 (file)
@@ -1,7 +1,7 @@
 class UsersController < ApplicationController
   skip_before_filter :find_object_by_uuid, :only => [:welcome, :activity]
   skip_around_filter :thread_with_mandatory_api_token, :only => :welcome
-  before_filter :ensure_current_user_is_admin, only: [:sudo, :unsetup]
+  before_filter :ensure_current_user_is_admin, only: [:sudo, :unsetup, :setup]
 
   def welcome
     if current_user
@@ -145,4 +145,94 @@ class UsersController < ApplicationController
     show
   end
 
+  def setup
+    respond_to do |format|
+      if current_user.andand.is_admin
+        setup_params = {}
+        if params['user_uuid'] && params['user_uuid'].size>0
+          setup_params[:uuid] = params['user_uuid']
+        end
+        if params['email'] && params['email'].size>0
+          user = {email: params['email']}
+          setup_params[:user] = user
+        end
+        if params['openid_prefix'] && params['openid_prefix'].size>0
+          setup_params[:openid_prefix] = params['openid_prefix']
+        end
+        if params['repo_name'] && params['repo_name'].size>0
+          setup_params[:repo_name] = params['repo_name']
+        end
+        if params['vm_uuid'] && params['vm_uuid'].size>0
+          setup_params[:vm_uuid] = params['vm_uuid']
+        end
+
+        if User.setup setup_params
+          format.js
+        else
+          self.render_error status: 422
+        end
+      else
+        self.render_error status: 422
+      end
+    end
+  end
+
+  def setup_popup
+    @vms = VirtualMachine.all.results
+
+    @current_selections = find_current_links @object
+
+    respond_to do |format|
+      format.html
+      format.js
+    end
+  end
+
+  protected
+
+  def find_current_links user
+    current_selections = {}
+
+    if !user
+      return current_selections
+    end
+
+    # oid login perm
+    oid_login_perms = Link.where(tail_uuid: user.email,
+                                   head_kind: 'arvados#user',
+                                   link_class: 'permission',
+                                   name: 'can_login')
+
+    if oid_login_perms.any?
+      prefix_properties = oid_login_perms.first.properties
+      current_selections[:identity_url_prefix] = prefix_properties[:identity_url_prefix]
+    end
+
+    # repo perm
+    repo_perms = Link.where(tail_uuid: user.uuid,
+                            head_kind: 'arvados#repository',
+                            link_class: 'permission',
+                            name: 'can_write')
+    if repo_perms.any?
+      repo_uuid = repo_perms.first.head_uuid
+      repos = Repository.where(head_uuid: repo_uuid)
+      if repos.any?
+        repo_name = repos.first.name
+        current_selections[:repo_name] = repo_name
+      end
+    end
+
+    # vm login perm
+    vm_login_perms = Link.where(tail_uuid: user.uuid,
+                              head_kind: 'arvados#virtualMachine',
+                              link_class: 'permission',
+                              name: 'can_login')
+    if vm_login_perms.any?
+      vm_uuid = vm_login_perms.first.head_uuid
+      current_selections[:vm_uuid] = vm_uuid
+    end
+
+    return current_selections
+  end
+
 end
index 6c889e602d1e8e31c5746d0625131b516da8ea90..44d615b89fecf117dcc618e01627e1beb74e38f2 100644 (file)
@@ -45,4 +45,8 @@ class User < ArvadosBase
                                                 {}))
   end
 
+  def self.setup params
+    $arvados_api_client.api(self, "/setup", params)
+  end
+
 end
index 67b50040a49702266f37c09e28b30a3ef05b743a..3f312405b509813bb88aa3e418c35a32c05ff75a 100644 (file)
@@ -4,11 +4,20 @@
 
 <% content_for :tab_line_buttons do %>
 
-<% if controller.model_class.creatable? %>
-<%= button_to "Add a new #{controller.model_class.to_s.underscore.gsub '_', ' '}", 
-    { action: 'create', return_to: request.url }, 
-    { class: 'btn btn-primary pull-right' } %>
-<% end %>
+  <% if controller.model_class.creatable? %>
+
+    <% if controller.model_class.name == 'User' %>
+      <%= link_to "Add a new #{controller.model_class.to_s.underscore.gsub '_', ' '}", setup_user_popup_path,
+        {class: 'btn btn-primary pull-right', :remote => true, 'data-toggle' =>  "modal",
+          'data-target' => '#user-setup-modal-window', return_to: request.url}  %>
+      <div id="user-setup-modal-window" class="modal fade" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true"></div>
+    <% else %>
+      <%= button_to "Add a new #{controller.model_class.to_s.underscore.gsub '_', ' '}",
+        { action: 'create', return_to: request.url },
+        { class: 'btn btn-primary pull-right' } %>
+    <% end %>
+
+  <% end %>
 
 <% end %>
 
index 63cf67c263f8b0f5eeb20be7c5add52e3acf0a31..724fa9bd9ffb52a0d71a961041fdf1181eaea353 100644 (file)
         </div>
   </div>
 
+  <%= yield :footer_html %>
   <%= piwik_tracking_tag %>
   <%= javascript_tag do %>
   <%= yield :footer_js %>
diff --git a/apps/workbench/app/views/users/_setup_popup.html.erb b/apps/workbench/app/views/users/_setup_popup.html.erb
new file mode 100644 (file)
index 0000000..f7f7914
--- /dev/null
@@ -0,0 +1,69 @@
+<div class="modal-dialog">
+  <div class="modal-content">
+
+    <%= form_tag setup_user_path, {id: 'setup_form', name: 'setup_form', method: 'get',
+        class: 'form-search', remote: true} do %>
+
+    <div class="modal-header">
+      <button type="button" class="close" onClick="reset_form()" data-dismiss="modal" aria-hidden="true">&times;</button>
+      <h4 class="modal-title">Setup User</h4>
+    </div>
+
+    <div class="modal-body">
+      <% if @object%>
+        <% uuid = @object.uuid %>
+        <% email = @object.email %>
+      <% end %>
+      <% disable_email = uuid != nil %>
+      <% identity_url_prefix = @current_selections[:identity_url_prefix] %>
+      <% disable_url_prefix = identity_url_prefix != nil %>
+      <% selected_repo = @current_selections[:repo_name] %>
+      <% selected_vm = @current_selections[:vm_uuid] %>
+
+      <input id="user_uuid" maxlength="250" name="user_uuid" type="hidden" value="<%=uuid%>">
+      <div class="form-group">
+       <label for="email">Email</label>
+        <% if disable_email %>
+        <input class="form-control" id="email" maxlength="250" name="email" type="text" value="<%=email%>" disabled>
+        <% else %>
+        <input class="form-control" id="email" maxlength="250" name="email" type="text">
+        <% end %>
+      </div>
+      <div class="form-group">
+        <label for="openid_prefix">Identity URL Prefix</label>
+        <% if disable_url_prefix %>
+        <input class="form-control" id="openid_prefix" maxlength="250" name="openid_prefix" type="text"
+               value="<%=identity_url_prefix%>" disabled=true>
+        <% else %>
+        <input class="form-control" id="openid_prefix" maxlength="250" name="openid_prefix" type="text"
+               value="<%= Rails.configuration.default_openid_prefix %>">
+        <% end %>
+      </div>
+      <div class="form-group">
+        <label for="repo_name">Repository Name</label>
+        <input class="form-control" id="repo_name" maxlength="250" name="repo_name" type="text" value="<%=selected_repo%>">
+      </div>
+      <div class="form-group">
+        <label for="vm_uuid">Virtual Machine</label>
+        <select class="form-control" name="vm_uuid">
+          <option value="" <%= 'selected' unless selected_vm %>>
+           Choose One:
+         </option>
+          <% @vms.each do |vm| %>
+            <option value="<%=vm.uuid%>"
+                   <%= 'selected' if selected_vm == vm.uuid %>>
+             <%= vm.hostname %>
+           </option>
+          <% end %>
+        </select>
+      </div>
+    </div>
+
+    <div class="modal-footer">
+      <button type="submit" id="register" class="btn btn-primary" autofocus>Submit</button>
+      <button class="btn btn-default" onClick="reset_form()" data-dismiss="modal" aria-hidden="true">Cancel</button>
+    </div>
+
+    <% end #form %>
+  </div>
+</div>
index 90afd1132891e3613a49f59d502c87dc1d8fce45..e2f5fdfa64b354a3988e84683c761f90247c9499 100644 (file)
@@ -6,8 +6,18 @@ account.</p>
 <%= button_to "Log in as #{@object.full_name}", sudo_user_url(id: @object.uuid), class: 'btn btn-primary' %>
 </blockquote>
 
+<p>As an admin, you can setup this user. Please input a VM and repository for the user. If you had previously provided any of these items, they are pre-filled for you and you can leave them as is if you would like to reuse them.</p>
+
+<blockquote>
+<%= link_to "Setup #{@object.full_name}", setup_popup_user_url(id: @object.uuid),  {class: 'btn btn-primary', :remote => true, 'data-toggle' =>  "modal", 'data-target' => '#user-setup-modal-window'}  %>
+</blockquote>
+
 <p>As an admin, you can deactivate and reset this user. This will remove all repository/VM permissions for the user. If you "setup" the user again, the user will have to sign the user agreement again.</p>
 
 <blockquote>
 <%= button_to "Deactivate #{@object.full_name}", unsetup_user_url(id: @object.uuid), class: 'btn btn-primary', confirm: "Are you sure you want to deactivate #{@object.full_name}?"%>
 </blockquote>
+
+<% content_for :footer_html do %>
+<div id="user-setup-modal-window" class="modal fade" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true"></div>
+<% end %>
diff --git a/apps/workbench/app/views/users/setup.js.erb b/apps/workbench/app/views/users/setup.js.erb
new file mode 100644 (file)
index 0000000..bce71b4
--- /dev/null
@@ -0,0 +1,2 @@
+$("#user-setup-modal-window").modal("hide");
+document.location.reload();
diff --git a/apps/workbench/app/views/users/setup_popup.js.erb b/apps/workbench/app/views/users/setup_popup.js.erb
new file mode 100644 (file)
index 0000000..5671cc2
--- /dev/null
@@ -0,0 +1,44 @@
+$("#user-setup-modal-window").html("<%= escape_javascript(render partial: 'setup_popup') %>");
+
+// disable the submit button on load
+var $input = $('input:text'),
+$register = $('#register');
+
+var email_disabled = document.forms["setup_form"]["email"].disabled;
+var email_value = document.forms["setup_form"]["email"].value;
+var prefix_value = document.forms["setup_form"]["openid_prefix"].value;
+if ((email_disabled == false) && (email_value == null || email_value == "" ||
+        prefix_value == null || prefix_value == "")) {
+  $register.attr('disabled', true);
+}
+
+// capture events to enable submit button when applicable
+$input.on('keyup paste mouseleave', function() {
+  var trigger = false;
+
+  var email_disabled = document.forms["setup_form"]["email"].disabled;
+  var email_value = document.forms["setup_form"]["email"].value;
+  var prefix_value = document.forms["setup_form"]["openid_prefix"].value;
+
+  var emailRegExp = /^([\w-\.]+@([\w-]+\.)+[\w-]{2,4})?$/;
+  var validEmail = false;
+  if (emailRegExp.test(email_value )) {
+    validEmail = true;
+  }
+
+  if ((email_disabled == false) && (!validEmail || email_value == null ||
+            email_value == "" || prefix_value == null || prefix_value == "")){
+    trigger = true;
+  }
+
+  trigger ? $register.attr('disabled', true) : $register.removeAttr('disabled');
+});
+
+// reset form input fields, for the next time around
+function reset_form() {
+  $('#email').val("");
+  $('#openid_prefix').val("");
+  $('#repo_name').val("");
+  $('select').val('')
+}
index bbed01ea315b064d1cd2ea2db49b1e433fb32967..dfc4f03fd8e0d10939d095396b68c3e74810abea 100644 (file)
@@ -72,3 +72,4 @@ common:
   arvados_theme: default
   show_user_agreement_inline: false
   secret_token: ~
+  default_openid_prefix: https://www.google.com/accounts/o8/id
index 6504df07ff89a117f49994a7cdf6237750d1f885..8c8923889da322d84e4ea387aa41991d3a1ca79a 100644 (file)
@@ -7,6 +7,8 @@ ArvadosWorkbench::Application.routes.draw do
     get 'signatures', on: :collection
   end
   get '/user_agreements/signatures' => 'user_agreements#signatures'
+  get "users/setup_popup" => 'users#setup_popup', :as => :setup_user_popup
+  get "users/setup" => 'users#setup', :as => :setup_user
   resources :nodes
   resources :humans
   resources :traits
@@ -24,6 +26,7 @@ ArvadosWorkbench::Application.routes.draw do
     get 'activity', :on => :collection
     post 'sudo', :on => :member
     post 'unsetup', :on => :member
+    get 'setup_popup', :on => :member
   end
   resources :logs
   resources :factory_jobs
diff --git a/apps/workbench/test/integration/users_test.rb b/apps/workbench/test/integration/users_test.rb
new file mode 100644 (file)
index 0000000..9ee12d8
--- /dev/null
@@ -0,0 +1,193 @@
+require 'integration_helper'
+
+class UsersTest < ActionDispatch::IntegrationTest
+  test "login as active user but not admin" do
+    Capybara.current_driver = Capybara.javascript_driver
+    visit page_with_token('active_trustedclient')
+
+    assert page.has_no_link? 'Users' 'Found Users link for non-admin user'
+  end
+
+  test "login as admin user and verify active user data" do
+    Capybara.current_driver = Capybara.javascript_driver
+    visit page_with_token('admin_trustedclient')
+
+    # go to Users list page
+    click_link 'Users'
+
+    # check active user attributes in the list page
+    page.within(:xpath, '//tr[@data-object-uuid="zzzzz-tpzed-xurymjxw79nv3jz"]') do
+      assert (text.include? 'true false'), 'Expected is_active'
+    end
+
+    click_link 'zzzzz-tpzed-xurymjxw79nv3jz'
+    assert page.has_text? 'Attributes'
+    assert page.has_text? 'Metadata'
+    assert page.has_text? 'Admin'
+
+    # go to the Attributes tab
+    click_link 'Attributes'
+    assert page.has_text? 'modified_by_user_uuid'
+    page.within(:xpath, '//a[@data-name="is_active"]') do
+      assert_equal "true", text, "Expected user's is_active to be true"
+    end
+    page.within(:xpath, '//a[@data-name="is_admin"]') do
+      assert_equal "false", text, "Expected user's is_admin to be false"
+    end
+
+  end
+
+  test "create a new user" do
+    Capybara.current_driver = :webkit
+    visit page_with_token('admin_trustedclient')
+
+    click_link 'Users'
+
+    assert page.has_text? 'zzzzz-tpzed-d9tiejq69daie8f'
+
+    click_link 'Add a new user'
+
+    sleep(0.1)
+    popup = page.driver.browser.window_handles.last
+    page.within_window popup do
+      assert has_text? 'Virtual Machine'
+      fill_in "email", :with => "foo@example.com"
+      fill_in "repo_name", :with => "test_repo"
+      click_button "Submit"
+    end
+
+    sleep(0.1)
+
+    # verify that the new user showed up in the users page
+    assert page.has_text? 'foo@example.com'
+
+    page.within(:xpath, '//tr[@data-object-uuid][1]') do
+      assert (text.include? 'foo@example.com false'), 'Expected email'
+      new_user_uuid = text.split[0]
+
+      # go to the new user's page
+      click_link new_user_uuid
+    end
+
+    assert page.has_text? 'modified_by_user_uuid'
+    page.within(:xpath, '//a[@data-name="is_active"]') do
+      assert_equal "false", text, "Expected new user's is_active to be false"
+    end
+
+    click_link 'Metadata'
+    assert page.has_text? '(Repository: test_repo)'
+    assert !(page.has_text? '(VirtualMachine:)')
+  end
+
+  test "setup the active user" do
+    Capybara.current_driver = :webkit
+    visit page_with_token('admin_trustedclient')
+
+    click_link 'Users'
+
+    assert page.has_link? 'zzzzz-tpzed-xurymjxw79nv3jz'
+
+    # click on active user
+    click_link 'zzzzz-tpzed-xurymjxw79nv3jz'
+
+    # Setup user
+    click_link 'Admin'
+    assert page.has_text? 'As an admin, you can setup'
+
+    click_link 'Setup Active User'
+
+    sleep(0.1)
+    popup = page.driver.browser.window_handles.last
+    page.within_window popup do
+      assert has_text? 'Virtual Machine'
+      fill_in "repo_name", :with => "test_repo"
+      click_button "Submit"
+    end
+
+    sleep(0.1)
+    assert page.has_text? 'modified_by_client_uuid'
+
+    click_link 'Metadata'
+    assert page.has_text? '(Repository: test_repo)'
+    assert !(page.has_text? '(VirtualMachine:)')
+
+    # Click on Setup button again and this time also choose a VM
+    click_link 'Admin'
+    click_link 'Setup Active User'
+
+    sleep(0.1)
+    popup = page.driver.browser.window_handles.last
+    page.within_window popup do
+      fill_in "repo_name", :with => "second_test_repo"
+      select("testvm.shell", :from => 'vm_uuid')
+      click_button "Submit"
+    end
+
+    sleep(0.1)
+    assert page.has_text? 'modified_by_client_uuid'
+
+    click_link 'Metadata'
+    assert page.has_text? '(Repository: second_test_repo)'
+    assert page.has_text? '(VirtualMachine: testvm.shell)'
+  end
+
+  test "unsetup active user" do
+    Capybara.current_driver = :webkit
+
+    visit page_with_token('admin_trustedclient')
+
+    click_link 'Users'
+
+    assert page.has_link? 'zzzzz-tpzed-xurymjxw79nv3jz'
+
+    # click on active user
+    click_link 'zzzzz-tpzed-xurymjxw79nv3jz'
+
+    # Verify that is_active is set
+    click_link 'Attributes'
+    assert page.has_text? 'modified_by_user_uuid'
+    page.within(:xpath, '//a[@data-name="is_active"]') do
+      assert_equal "true", text, "Expected user's is_active to be true"
+    end
+
+    # go to Admin tab
+    click_link 'Admin'
+    assert page.has_text? 'As an admin, you can deactivate and reset this user'
+
+    # unsetup user and verify all the above links are deleted
+    click_link 'Admin'
+    click_button 'Deactivate Active User'
+    sleep(0.1)
+
+    # Should now be back in the Attributes tab for the user
+    assert page.has_text? 'modified_by_user_uuid'
+    page.within(:xpath, '//a[@data-name="is_active"]') do
+      assert_equal "false", text, "Expected user's is_active to be false after unsetup"
+    end
+
+    click_link 'Metadata'
+    assert !(page.has_text? '(Repository: test_repo)')
+    assert !(page.has_text? '(Repository: second_test_repo)')
+    assert !(page.has_text? '(VirtualMachine: testvm.shell)')
+
+    # setup user again and verify links present
+    click_link 'Admin'
+    click_link 'Setup Active User'
+
+    sleep(0.1)
+    popup = page.driver.browser.window_handles.last
+    page.within_window popup do
+      fill_in "repo_name", :with => "second_test_repo"
+      select("testvm.shell", :from => 'vm_uuid')
+      click_button "Submit"
+    end
+
+    sleep(0.1)
+    assert page.has_text? 'modified_by_client_uuid'
+
+    click_link 'Metadata'
+    assert page.has_text? '(Repository: second_test_repo)'
+    assert page.has_text? '(VirtualMachine: testvm.shell)'
+  end
+
+end
index 2f7376f1e968974f7dd1b858560d064daf5f9eec..e185d66d691f1b80127a9be469f2222dbea3fae9 100755 (executable)
@@ -1120,6 +1120,7 @@ sub collate_output
     my $s = IO::Select->new($child_out);
     if ($s->can_read(120)) {
       sysread($child_out, $joboutput, 64 * 1024 * 1024);
+      chomp($joboutput);
     } else {
       Log (undef, "timed out reading from 'arv keep put'");
     }
index fe2d0da5d808f2645b4d327cabeabc26c875c1be..58661a0e9a3c970712eccc054b8d2e9060dc249e 100644 (file)
@@ -124,7 +124,8 @@ class Arvados::V1::UsersController < ApplicationController
     end
 
     if object_found
-      @response = @object.setup_repo_vm_links params[:repo_name], params[:vm_uuid]
+      @response = @object.setup_repo_vm_links params[:repo_name],
+                    params[:vm_uuid], params[:openid_prefix]
     else
       @response = User.setup @object, params[:openid_prefix],
                     params[:repo_name], params[:vm_uuid]
index 497a693bb88398e6343ae924a5309d8057840711..5c03eda519533d839abfca77b07b80f6342bfc2c 100644 (file)
@@ -111,39 +111,17 @@ class User < ArvadosModel
   end
 
   def self.setup(user, openid_prefix, repo_name=nil, vm_uuid=nil)
-    login_perm_props = {identity_url_prefix: openid_prefix}
-
-    # Check oid_login_perm
-    oid_login_perms = Link.where(tail_uuid: user.email,
-                                   head_kind: 'arvados#user',
-                                   link_class: 'permission',
-                                   name: 'can_login')
-
-    if !oid_login_perms.any?
-      # create openid login permission
-      oid_login_perm = Link.create(link_class: 'permission',
-                                   name: 'can_login',
-                                   tail_kind: 'email',
-                                   tail_uuid: user.email,
-                                   head_kind: 'arvados#user',
-                                   head_uuid: user.uuid,
-                                   properties: login_perm_props
-                                  )
-      logger.info { "openid login permission: " + oid_login_perm[:uuid] }
-    else
-      oid_login_perm = oid_login_perms.first
-    end
-
-    return [oid_login_perm] + user.setup_repo_vm_links(repo_name, vm_uuid)
+    return user.setup_repo_vm_links(repo_name, vm_uuid, openid_prefix)
   end
 
   # create links
-  def setup_repo_vm_links(repo_name, vm_uuid)
+  def setup_repo_vm_links(repo_name, vm_uuid, openid_prefix)
+    oid_login_perm = create_oid_login_perm openid_prefix
     repo_perm = create_user_repo_link repo_name
     vm_login_perm = create_vm_login_permission_link vm_uuid, repo_name
     group_perm = create_user_group_link
 
-    return [repo_perm, vm_login_perm, group_perm, self].compact
+    return [oid_login_perm, repo_perm, vm_login_perm, group_perm, self].compact
   end
 
   # delete user signatures, login, repo, and vm perms, and mark as inactive
@@ -175,6 +153,19 @@ class User < ArvadosModel
       Link.delete perm
     end
 
+    # delete "All users' group read permissions for this user
+    group = Group.where(name: 'All users').select do |g|
+      g[:uuid].match /-f+$/
+    end.first
+    group_perms = Link.where(tail_uuid: self.uuid,
+                             head_uuid: group[:uuid],
+                             head_kind: 'arvados#group',
+                             link_class: 'permission',
+                             name: 'can_read')
+    group_perms.each do |perm|
+      Link.delete perm
+    end
+
     # delete any signatures by this user
     signed_uuids = Link.where(link_class: 'signature',
                               tail_kind: 'arvados#user',
@@ -257,6 +248,33 @@ class User < ArvadosModel
     merged
   end
 
+  def create_oid_login_perm (openid_prefix)
+    login_perm_props = {identity_url_prefix: openid_prefix}
+
+    # Check oid_login_perm
+    oid_login_perms = Link.where(tail_uuid: self.email,
+                                   head_kind: 'arvados#user',
+                                   link_class: 'permission',
+                                   name: 'can_login')
+
+    if !oid_login_perms.any?
+      # create openid login permission
+      oid_login_perm = Link.create(link_class: 'permission',
+                                   name: 'can_login',
+                                   tail_kind: 'email',
+                                   tail_uuid: self.email,
+                                   head_kind: 'arvados#user',
+                                   head_uuid: self.uuid,
+                                   properties: login_perm_props
+                                  )
+      logger.info { "openid login permission: " + oid_login_perm[:uuid] }
+    else
+      oid_login_perm = oid_login_perms.first
+    end
+
+    return oid_login_perm
+  end
+
   def create_user_repo_link(repo_name)
     # repo_name is optional
     if not repo_name
@@ -320,7 +338,16 @@ class User < ArvadosModel
                               head_kind: 'arvados#virtualMachine',
                               link_class: 'permission',
                               name: 'can_login')
-      if !login_perms.any?
+
+      perm_exists = false
+      login_perms.each do |perm|
+        if perm.properties[:username] == repo_name
+          perm_exists = true
+          break
+        end
+      end
+
+      if !perm_exists
         login_perm = Link.create(tail_kind: 'arvados#user',
                                  tail_uuid: self.uuid,
                                  head_kind: 'arvados#virtualMachine',
@@ -376,11 +403,13 @@ class User < ArvadosModel
   # all of this user's stuff.
   #
   def add_system_group_permission_link
-    Link.create(link_class: 'permission',
-                name: 'can_manage',
-                tail_kind: 'arvados#group',
-                tail_uuid: system_group_uuid,
-                head_kind: 'arvados#user',
-                head_uuid: self.uuid)
+    act_as_system_user do
+      Link.create(link_class: 'permission',
+                  name: 'can_manage',
+                  tail_kind: 'arvados#group',
+                  tail_uuid: system_group_uuid,
+                  head_kind: 'arvados#user',
+                  head_uuid: self.uuid)
+    end
   end
 end
index 25fcc7ada79ba516073a6c206699b26792d1b6f7..a16ea98910b85067023426fa0580303b460fe809 100644 (file)
@@ -7,7 +7,7 @@ test:
   encoding: utf8
   database: arvados_test
   username: arvados
-  password: ********
+  password: xxxxxxxx
   host: localhost
 
 production:
@@ -15,6 +15,6 @@ production:
   encoding: utf8
   database: arvados_production
   username: arvados
-  password: ********
+  password: xxxxxxxx
   host: localhost
 
index edc64bdf48d4991552772e351e11c5c5b74832bc..a349229b4504151bf38c484bbfa8573dc334dd35 100644 (file)
@@ -6,6 +6,7 @@ running:
   cancelled_by_client_uuid: ~
   started_at: <%= 3.minute.ago.to_s(:db) %>
   finished_at: ~
+  script_version: 1de84a854e2b440dc53bf42f8548afa4c17da332
   running: true
   success: ~
   output: ~
@@ -27,6 +28,7 @@ running_cancelled:
   cancelled_by_client_uuid: zzzzz-ozdt8-obw7foaks3qjyej
   started_at: <%= 3.minute.ago.to_s(:db) %>
   finished_at: ~
+  script_version: 1de84a854e2b440dc53bf42f8548afa4c17da332
   running: true
   success: ~
   output: ~
index 2a7f686f34425b44b363c6eee7cd7f43526b8723..e62eff892585ae7e50d0734dfdfe6601ce3cb45c 100644 (file)
@@ -659,7 +659,7 @@ class Arvados::V1::UsersControllerTest < ActionController::TestCase
     verify_link response_items, 'arvados#virtualMachine', true, 'permission', 'can_login',
         @vm_uuid, created['uuid'], 'arvados#virtualMachine', false, 'VirtualMachine'
 
-    verify_link_existence created['uuid'], created['email'], true, true, true, false
+    verify_link_existence created['uuid'], created['email'], true, true, true, true, false
 
     # now unsetup this user
     post :unsetup, uuid: created['uuid']
@@ -669,7 +669,7 @@ class Arvados::V1::UsersControllerTest < ActionController::TestCase
     assert_not_nil created2['uuid'], 'expected uuid for the newly created user'
     assert_equal created['uuid'], created2['uuid'], 'expected uuid not found'
 
-    verify_link_existence created['uuid'], created['email'], false, false, false, false
+    verify_link_existence created['uuid'], created['email'], false, false, false, false, false
   end
 
   test "unsetup active user" do
@@ -679,9 +679,10 @@ class Arvados::V1::UsersControllerTest < ActionController::TestCase
     active_user = JSON.parse(@response.body)
     assert_not_nil active_user['uuid'], 'expected uuid for the active user'
     assert active_user['is_active'], 'expected is_active for active user'
+    assert active_user['is_invited'], 'expected is_invited for active user'
 
     verify_link_existence active_user['uuid'], active_user['email'],
-          false, false, false, true
+          false, false, false, true, true
 
     authorize_with :admin
 
@@ -693,9 +694,10 @@ class Arvados::V1::UsersControllerTest < ActionController::TestCase
     assert_not_nil response_user['uuid'], 'expected uuid for the upsetup user'
     assert_equal active_user['uuid'], response_user['uuid'], 'expected uuid not found'
     assert !response_user['is_active'], 'expected user to be inactive'
+    assert !response_user['is_invited'], 'expected user to be uninvited'
 
     verify_link_existence response_user['uuid'], response_user['email'],
-          false, false, false, false
+          false, false, false, false, false
   end
 
   def verify_num_links (original_links, expected_additional_links)
@@ -760,7 +762,7 @@ class Arvados::V1::UsersControllerTest < ActionController::TestCase
   end
 
   def verify_link_existence uuid, email, expect_oid_login_perms,
-        expect_repo_perms, expect_vm_perms, expect_signatures
+      expect_repo_perms, expect_vm_perms, expect_group_perms, expect_signatures
     # verify that all links are deleted for the user
     oid_login_perms = Link.where(tail_uuid: email,
                                  head_kind: 'arvados#user',
@@ -792,6 +794,20 @@ class Arvados::V1::UsersControllerTest < ActionController::TestCase
       assert !vm_login_perms.any?, "expected all vm_login_perms deleted"
     end
 
+    group = Group.where(name: 'All users').select do |g|
+      g[:uuid].match /-f+$/
+    end.first
+    group_read_perms = Link.where(tail_uuid: uuid,
+                             head_uuid: group[:uuid],
+                             head_kind: 'arvados#group',
+                             link_class: 'permission',
+                             name: 'can_read')
+    if expect_group_perms
+      assert group_read_perms.any?, "expected all users group read perms"
+    else
+      assert !group_read_perms.any?, "expected all users group perm deleted"
+    end
+
     signed_uuids = Link.where(link_class: 'signature',
                                   tail_kind: 'arvados#user',
                                   tail_uuid: uuid)
index 9f78b1a3650320c29c37cc9d002d0e2cac484c41..16c05a718196f5a3fc3ad9518266be6e44dbb964 100644 (file)
@@ -1,13 +1,19 @@
 require 'test_helper'
 
 class UserTest < ActiveSupport::TestCase
+  include CurrentApiClient
 
   # The fixture services/api/test/fixtures/users.yml serves as the input for this test case
   setup do
+    # Make sure system_user exists before making "pre-test users" list
+    system_user
+
     @all_users = User.find(:all)
 
     @all_users.each do |user|
-      if user.is_admin && user.is_active
+      if user.uuid == system_user_uuid
+        @system_user = user
+      elsif user.is_admin && user.is_active
         @admin_user = user
       elsif user.is_active && !user.is_admin
         @active_user = user
@@ -89,7 +95,7 @@ class UserTest < ActiveSupport::TestCase
     user.save
 
     # verify there is one extra user in the db now
-    assert (User.find(:all).size == @all_users.size+1)
+    assert_equal @all_users.size+1, User.find(:all).size
 
     user = User.find(user.id)   # get the user back
     assert_equal(user.first_name, 'first_name_for_newly_created_user')