[ARVADOS] created: 1.3.0-841-g6eec8fe2f

Git user git at public.curoverse.com
Tue May 7 22:04:33 UTC 2019


        at  6eec8fe2f0adb2bd0f53a51a37ca8ebbeaced44d (commit)


commit 6eec8fe2f0adb2bd0f53a51a37ca8ebbeaced44d
Author: Peter Amstutz <pamstutz at veritasgenetics.com>
Date:   Tue May 7 18:00:57 2019 -0400

    15061: Implement admin variant of user merge by uuid
    
    Arvados-DCO-1.1-Signed-off-by: Peter Amstutz <pamstutz at veritasgenetics.com>

diff --git a/services/api/app/controllers/arvados/v1/users_controller.rb b/services/api/app/controllers/arvados/v1/users_controller.rb
index de18144c5..4a345f363 100644
--- a/services/api/app/controllers/arvados/v1/users_controller.rb
+++ b/services/api/app/controllers/arvados/v1/users_controller.rb
@@ -126,40 +126,65 @@ class Arvados::V1::UsersController < ApplicationController
   end
 
   def merge
-    if !Thread.current[:api_client].andand.is_trusted
-      return send_error("supplied API token is not from a trusted client", status: 403)
-    elsif Thread.current[:api_client_authorization].scopes != ['all']
-      return send_error("cannot merge with a scoped token", status: 403)
-    end
+    if (params[:old_user_uuid] || params[:new_user_uuid])
+      if !current_user.andand.is_admin
+        return send_error("Must be admin to use old_user_uuid/new_user_uuid", status: 403)
+      end
+      if !params[:old_user_uuid] || !params[:new_user_uuid]
+        return send_error("Must supply both old_user_uuid and new_user_uuid", status: 422)
+      end
+      new_user = User.find_by_uuid(params[:new_user_uuid])
+      if !new_user
+        return send_error("User in new_user_uuid not found", status: 422)
+      end
+      @object = User.find_by_uuid(params[:old_user_uuid])
+      if !@object
+        return send_error("User in old_user_uuid not found", status: 422)
+      end
+    else
+      if !Thread.current[:api_client].andand.is_trusted
+        return send_error("supplied API token is not from a trusted client", status: 403)
+      elsif Thread.current[:api_client_authorization].scopes != ['all']
+        return send_error("cannot merge with a scoped token", status: 403)
+      end
 
-    new_auth = ApiClientAuthorization.validate(token: params[:new_user_token])
-    if !new_auth
-      return send_error("invalid new_user_token", status: 401)
-    end
+      new_auth = ApiClientAuthorization.validate(token: params[:new_user_token])
+      if !new_auth
+        return send_error("invalid new_user_token", status: 401)
+      end
 
-    if new_auth.user.uuid[0..4] == Rails.configuration.ClusterID
-      if !new_auth.api_client.andand.is_trusted
-        return send_error("supplied new_user_token is not from a trusted client", status: 403)
-      elsif new_auth.scopes != ['all']
-        return send_error("supplied new_user_token has restricted scope", status: 403)
+      if new_auth.user.uuid[0..4] == Rails.configuration.ClusterID
+        if !new_auth.api_client.andand.is_trusted
+          return send_error("supplied new_user_token is not from a trusted client", status: 403)
+        elsif new_auth.scopes != ['all']
+          return send_error("supplied new_user_token has restricted scope", status: 403)
+        end
       end
+      new_user = new_auth.user
+      @object = current_user
     end
-    new_user = new_auth.user
 
-    if current_user.uuid == new_user.uuid
+    if @object.uuid == new_user.uuid
       return send_error("cannot merge user to self", status: 422)
     end
 
+    if !params[:new_owner_uuid]
+      return send_error("missing new_owner_uuid", status: 422)
+    end
+
     if !new_user.can?(write: params[:new_owner_uuid])
       return send_error("cannot move objects into supplied new_owner_uuid: new user does not have write permission", status: 403)
     end
 
     redirect = params[:redirect_to_new_user]
+    if @object.uuid[0..4] != Rails.configuration.ClusterID && redirect
+      return send_error("cannot merge remote user to other with redirect_to_new_user=true", status: 422)
+    end
+
     if !redirect
       return send_error("merge with redirect_to_new_user=false is not yet supported", status: 422)
     end
 
-    @object = current_user
     act_as_system_user do
       @object.merge(new_owner_uuid: params[:new_owner_uuid], redirect_to_user_uuid: redirect && new_user.uuid)
     end
@@ -174,11 +199,17 @@ class Arvados::V1::UsersController < ApplicationController
         type: 'string', required: true,
       },
       new_user_token: {
-        type: 'string', required: true,
+        type: 'string', required: false,
       },
       redirect_to_new_user: {
         type: 'boolean', required: false,
       },
+      old_user_uuid: {
+        type: 'string', required: false,
+      },
+      new_user_uuid: {
+        type: 'string', required: false,
+      }
     }
   end
 
diff --git a/services/api/app/controllers/user_sessions_controller.rb b/services/api/app/controllers/user_sessions_controller.rb
index 1e4befb05..ef0f88686 100644
--- a/services/api/app/controllers/user_sessions_controller.rb
+++ b/services/api/app/controllers/user_sessions_controller.rb
@@ -85,10 +85,6 @@ class UserSessionsController < ApplicationController
       # Send them to their home cluster's login
       rh = Rails.configuration.RemoteClusters[user.uuid[0..4]]
       remote, return_to_url = params[:return_to].split(',', 2)
-      if remote !~ /^[0-9a-z]{5}$/ && remote != ""
-        return send_error 'Invalid remote cluster id', status: 400
-      end
-      remote = nil if remote == ''
       @remotehomeurl = "#{rh.Scheme || "https"}://#{rh.Host}/login?remote=#{Rails.configuration.ClusterID}&return_to=#{return_to_url}"
       render
       return
diff --git a/services/api/test/functional/arvados/v1/users_controller_test.rb b/services/api/test/functional/arvados/v1/users_controller_test.rb
index 0501da167..60696b98a 100644
--- a/services/api/test/functional/arvados/v1/users_controller_test.rb
+++ b/services/api/test/functional/arvados/v1/users_controller_test.rb
@@ -927,7 +927,7 @@ class Arvados::V1::UsersControllerTest < ActionController::TestCase
            redirect_to_new_user: true,
          })
     assert_response(:success)
-    assert_equal(users(:project_viewer).redirect_to_user_uuid, users(:active).uuid)
+    assert_equal(users(:active).uuid, User.unscoped.find_by_uuid(users(:project_viewer).uuid).redirect_to_user_uuid)
 
     auth = ApiClientAuthorization.validate(token: api_client_authorizations(:project_viewer).api_token)
     assert_not_nil(auth)
@@ -935,6 +935,82 @@ class Arvados::V1::UsersControllerTest < ActionController::TestCase
     assert_equal(users(:active).uuid, auth.user.uuid)
   end
 
+
+  test "merge 'project_viewer' account into 'active' account using uuids" do
+    authorize_with(:admin)
+    post(:merge, params: {
+           old_user_uuid: users(:project_viewer).uuid,
+           new_user_uuid: users(:active).uuid,
+           new_owner_uuid: users(:active).uuid,
+           redirect_to_new_user: true,
+         })
+    assert_response(:success)
+    assert_equal(users(:active).uuid, User.unscoped.find_by_uuid(users(:project_viewer).uuid).redirect_to_user_uuid)
+
+    auth = ApiClientAuthorization.validate(token: api_client_authorizations(:project_viewer).api_token)
+    assert_not_nil(auth)
+    assert_not_nil(auth.user)
+    assert_equal(users(:active).uuid, auth.user.uuid)
+  end
+
+  test "merge 'project_viewer' account into 'active' account using uuids denied for non-admin" do
+    authorize_with(:active)
+    post(:merge, params: {
+           old_user_uuid: users(:project_viewer).uuid,
+           new_user_uuid: users(:active).uuid,
+           new_owner_uuid: users(:active).uuid,
+           redirect_to_new_user: true,
+         })
+    assert_response(403)
+    assert_nil(users(:project_viewer).redirect_to_user_uuid)
+  end
+
+  test "merge 'project_viewer' account into 'active' account using uuids denied missing old_user_uuid" do
+    authorize_with(:admin)
+    post(:merge, params: {
+           new_user_uuid: users(:active).uuid,
+           new_owner_uuid: users(:active).uuid,
+           redirect_to_new_user: true,
+         })
+    assert_response(422)
+    assert_nil(users(:project_viewer).redirect_to_user_uuid)
+  end
+
+  test "merge 'project_viewer' account into 'active' account using uuids denied missing new_user_uuid" do
+    authorize_with(:admin)
+    post(:merge, params: {
+           old_user_uuid: users(:project_viewer).uuid,
+           new_owner_uuid: users(:active).uuid,
+           redirect_to_new_user: true,
+         })
+    assert_response(422)
+    assert_nil(users(:project_viewer).redirect_to_user_uuid)
+  end
+
+  test "merge 'project_viewer' account into 'active' account using uuids denied bogus old_user_uuid" do
+    authorize_with(:admin)
+    post(:merge, params: {
+           old_user_uuid: "zzzzz-tpzed-bogusbogusbogus",
+           new_user_uuid: users(:active).uuid,
+           new_owner_uuid: users(:active).uuid,
+           redirect_to_new_user: true,
+         })
+    assert_response(422)
+    assert_nil(users(:project_viewer).redirect_to_user_uuid)
+  end
+
+  test "merge 'project_viewer' account into 'active' account using uuids denied bogus new_user_uuid" do
+    authorize_with(:admin)
+    post(:merge, params: {
+           old_user_uuid: users(:project_viewer).uuid,
+           new_user_uuid: "zzzzz-tpzed-bogusbogusbogus",
+           new_owner_uuid: users(:active).uuid,
+           redirect_to_new_user: true,
+         })
+    assert_response(422)
+    assert_nil(users(:project_viewer).redirect_to_user_uuid)
+  end
+
   NON_ADMIN_USER_DATA = ["uuid", "kind", "is_active", "email", "first_name",
                          "last_name", "username"].sort
 

commit 662f94469d5640982be334b39c4ba2153b5bb1a6
Author: Peter Amstutz <pamstutz at veritasgenetics.com>
Date:   Tue May 7 16:31:21 2019 -0400

    15061: API support for linking local account to remote user
    
    Adds page to login process to redirect user to log in to home cluster.
    
    Arvados-DCO-1.1-Signed-off-by: Peter Amstutz <pamstutz at veritasgenetics.com>

diff --git a/services/api/Gemfile b/services/api/Gemfile
index 6d4295694..804d2a479 100644
--- a/services/api/Gemfile
+++ b/services/api/Gemfile
@@ -71,6 +71,8 @@ gem 'rails-observers'
 gem 'rails-perftest'
 gem 'rails-controller-testing'
 
+gem 'sass-rails'
+
 # Install any plugin gems
 Dir.glob(File.join(File.dirname(__FILE__), 'lib', '**', "Gemfile")) do |f|
     eval(IO.read(f), binding)
diff --git a/services/api/Gemfile.lock b/services/api/Gemfile.lock
index 13f7564be..078b2b7f4 100644
--- a/services/api/Gemfile.lock
+++ b/services/api/Gemfile.lock
@@ -110,6 +110,7 @@ GEM
     faye-websocket (0.10.7)
       eventmachine (>= 0.12.0)
       websocket-driver (>= 0.5.1)
+    ffi (1.9.25)
     globalid (0.4.2)
       activesupport (>= 4.2.0)
     googleauth (0.8.0)
@@ -220,6 +221,9 @@ GEM
       rake (>= 0.8.7)
       thor (>= 0.18.1, < 2.0)
     rake (12.3.2)
+    rb-fsevent (0.10.3)
+    rb-inotify (0.9.10)
+      ffi (>= 0.5.0, < 2)
     ref (2.0.0)
     request_store (1.4.1)
       rack (>= 1.4)
@@ -231,6 +235,17 @@ GEM
     rvm-capistrano (1.5.6)
       capistrano (~> 2.15.4)
     safe_yaml (1.0.5)
+    sass (3.5.5)
+      sass-listen (~> 4.0.0)
+    sass-listen (4.0.0)
+      rb-fsevent (~> 0.9, >= 0.9.4)
+      rb-inotify (~> 0.9, >= 0.9.7)
+    sass-rails (5.0.7)
+      railties (>= 4.0.0, < 6)
+      sass (~> 3.1)
+      sprockets (>= 2.8, < 4.0)
+      sprockets-rails (>= 2.0, < 4.0)
+      tilt (>= 1.1, < 3)
     signet (0.11.0)
       addressable (~> 2.3)
       faraday (~> 0.9)
@@ -257,6 +272,7 @@ GEM
       ref
     thor (0.20.3)
     thread_safe (0.3.6)
+    tilt (2.0.8)
     tzinfo (1.2.5)
       thread_safe (~> 0.1)
     uglifier (2.7.2)
@@ -299,6 +315,7 @@ DEPENDENCIES
   ruby-prof (~> 0.15.0)
   rvm-capistrano
   safe_yaml
+  sass-rails
   simplecov (~> 0.7.1)
   simplecov-rcov
   sshkey
diff --git a/services/api/app/assets/images/logo.png b/services/api/app/assets/images/logo.png
index 4db96efab..c511f0ec5 100644
Binary files a/services/api/app/assets/images/logo.png and b/services/api/app/assets/images/logo.png differ
diff --git a/services/api/app/assets/stylesheets/application.css b/services/api/app/assets/stylesheets/application.css
index 742a575a9..721ff801c 100644
--- a/services/api/app/assets/stylesheets/application.css
+++ b/services/api/app/assets/stylesheets/application.css
@@ -7,7 +7,7 @@ SPDX-License-Identifier: AGPL-3.0 */
  * and any sub-directories. You're free to add application-wide styles to this file and they'll appear at
  * the top of the compiled file, but it's generally better to create a new file per style scope.
  *= require_self
- *= require_tree . 
+ *= require_tree .
 */
 
 .contain-align-left {
@@ -63,8 +63,7 @@ div#header span.beta > span {
     font-size: 0.8em;
 }
 img.curoverse-logo {
-    width: 221px;
-    height: 44px;
+    height: 66px;
 }
 #intropage {
     font-family: Verdana,Arial,sans-serif;
@@ -180,4 +179,3 @@ div#header a.sudo-logout {
     color: #000;
     font-weight: bold;
 }
-
diff --git a/services/api/app/controllers/arvados/v1/users_controller.rb b/services/api/app/controllers/arvados/v1/users_controller.rb
index 18b6b46d2..de18144c5 100644
--- a/services/api/app/controllers/arvados/v1/users_controller.rb
+++ b/services/api/app/controllers/arvados/v1/users_controller.rb
@@ -136,10 +136,13 @@ class Arvados::V1::UsersController < ApplicationController
     if !new_auth
       return send_error("invalid new_user_token", status: 401)
     end
-    if !new_auth.api_client.andand.is_trusted
-      return send_error("supplied new_user_token is not from a trusted client", status: 403)
-    elsif new_auth.scopes != ['all']
-      return send_error("supplied new_user_token has restricted scope", status: 403)
+
+    if new_auth.user.uuid[0..4] == Rails.configuration.ClusterID
+      if !new_auth.api_client.andand.is_trusted
+        return send_error("supplied new_user_token is not from a trusted client", status: 403)
+      elsif new_auth.scopes != ['all']
+        return send_error("supplied new_user_token has restricted scope", status: 403)
+      end
     end
     new_user = new_auth.user
 
diff --git a/services/api/app/controllers/user_sessions_controller.rb b/services/api/app/controllers/user_sessions_controller.rb
index 6e18cdd46..1e4befb05 100644
--- a/services/api/app/controllers/user_sessions_controller.rb
+++ b/services/api/app/controllers/user_sessions_controller.rb
@@ -80,6 +80,20 @@ class UserSessionsController < ApplicationController
     # For the benefit of functional and integration tests:
     @user = user
 
+    if user.uuid[0..4] != Rails.configuration.ClusterID
+      # Actually a remote user
+      # Send them to their home cluster's login
+      rh = Rails.configuration.RemoteClusters[user.uuid[0..4]]
+      remote, return_to_url = params[:return_to].split(',', 2)
+      if remote !~ /^[0-9a-z]{5}$/ && remote != ""
+        return send_error 'Invalid remote cluster id', status: 400
+      end
+      remote = nil if remote == ''
+      @remotehomeurl = "#{rh.Scheme || "https"}://#{rh.Host}/login?remote=#{Rails.configuration.ClusterID}&return_to=#{return_to_url}"
+      render
+      return
+    end
+
     # prevent ArvadosModel#before_create and _update from throwing
     # "unauthorized":
     Thread.current[:user] = user
diff --git a/services/api/app/views/layouts/application.html.erb b/services/api/app/views/layouts/application.html.erb
index 302859543..a99b6f165 100644
--- a/services/api/app/views/layouts/application.html.erb
+++ b/services/api/app/views/layouts/application.html.erb
@@ -5,14 +5,15 @@ SPDX-License-Identifier: AGPL-3.0 %>
 <!DOCTYPE html>
 <html>
 <head>
-  <title>Server</title>
+  <title>Arvados API Server (<%= Rails.configuration.ClusterID %>)</title>
   <%= stylesheet_link_tag    "application" %>
   <%= javascript_include_tag "application" %>
   <%= csrf_meta_tags %>
 </head>
 <body>
 <div id="header">
-  <div class="apptitle">ARVADOS <span class="beta"><span>BETA</span></span></div>
+  <div class="apptitle">ARVADOS</div>
+  <div>(<%= Rails.configuration.ClusterID %>)</div>
   <div style="float:right">
     <% if current_user %>
     <%= current_user.full_name %>
@@ -23,7 +24,7 @@ SPDX-License-Identifier: AGPL-3.0 %>
      • 
     <a class="logout" href="/logout">Log out</a>
     <% else %>
-    <a class="logout" href="/auth/joshid">Log in</a>
+      <!--<a class="logout" href="/auth/joshid">Log in</a>-->
     <% end %>
 
     <% if current_user and session[:real_uid] and session[:switch_back_to] and User.find(session[:real_uid].to_i).verify_userswitch_cookie(session[:switch_back_to]) %>
diff --git a/services/api/app/views/static/login_failure.html.erb b/services/api/app/views/static/login_failure.html.erb
index 0f3141e0e..b3c6e70d9 100644
--- a/services/api/app/views/static/login_failure.html.erb
+++ b/services/api/app/views/static/login_failure.html.erb
@@ -17,9 +17,9 @@ $(function(){
 
     <p>Sorry, something went wrong logging you in. Please try again.</p>
 
-    <p style="float:right;margin-top:1em">
-      <a href="/auth/joshid">Log in here.</a>
-    </p>
+    <!--<p style="float:right;margin-top:1em">
+      <a href="/login">Log in here.</a>
+    </p>-->
 
     <div style="clear:both;height:8em"></div>
   </div>

commit 1b44bcdcfdbfa5d272cf5409cf58df57e6eed3f9
Author: Peter Amstutz <pamstutz at veritasgenetics.com>
Date:   Mon May 6 15:35:42 2019 -0400

    15061: Correctly filter out "*" from RemoteClusters
    
    Arvados-DCO-1.1-Signed-off-by: Peter Amstutz <pamstutz at veritasgenetics.com>

diff --git a/services/api/app/controllers/arvados/v1/schema_controller.rb b/services/api/app/controllers/arvados/v1/schema_controller.rb
index 13e47f76c..eb3ff2388 100644
--- a/services/api/app/controllers/arvados/v1/schema_controller.rb
+++ b/services/api/app/controllers/arvados/v1/schema_controller.rb
@@ -26,7 +26,7 @@ class Arvados::V1::SchemaController < ApplicationController
     Rails.cache.fetch 'arvados_v1_rest_discovery' do
       Rails.application.eager_load!
       remoteHosts = {}
-      Rails.configuration.RemoteClusters.each {|k,v| if k != "*" then remoteHosts[k] = v["Host"] end }
+      Rails.configuration.RemoteClusters.each {|k,v| if k != :"*" then remoteHosts[k] = v["Host"] end }
       discovery = {
         kind: "discovery#restDescription",
         discoveryVersion: "v1",

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


hooks/post-receive
-- 




More information about the arvados-commits mailing list