[ARVADOS] created: 1.1.2-14-g87647b5
Git user
git at public.curoverse.com
Fri Jan 5 10:41:34 EST 2018
at 87647b5d3d72ae0c291fcdf1ee3b4a46b3af91c0 (commit)
commit 87647b5d3d72ae0c291fcdf1ee3b4a46b3af91c0
Author: Tom Clegg <tclegg at veritasgenetics.com>
Date: Fri Jan 5 10:38:04 2018 -0500
12702: Add /arvados/v1/users/{uuid}/update_uuid API.
Arvados-DCO-1.1-Signed-off-by: Tom Clegg <tclegg 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 5e12352..dc7e62f 100644
--- a/services/api/app/controllers/arvados/v1/users_controller.rb
+++ b/services/api/app/controllers/arvados/v1/users_controller.rb
@@ -9,7 +9,7 @@ class Arvados::V1::UsersController < ApplicationController
[:activate, :current, :system, :setup]
skip_before_filter :render_404_if_no_object, only:
[:activate, :current, :system, :setup]
- before_filter :admin_required, only: [:setup, :unsetup]
+ before_filter :admin_required, only: [:setup, :unsetup, :update_uuid]
def current
if current_user
@@ -118,6 +118,13 @@ class Arvados::V1::UsersController < ApplicationController
show
end
+ # Change UUID to a new (unused) uuid and transfer all owned/linked
+ # objects accordingly.
+ def update_uuid
+ @object.update_uuid(new_uuid: params[:new_uuid])
+ show
+ end
+
protected
def self._setup_requires_parameters
@@ -140,6 +147,14 @@ class Arvados::V1::UsersController < ApplicationController
}
end
+ def self._update_uuid_requires_parameters
+ {
+ new_uuid: {
+ type: 'string', required: true,
+ },
+ }
+ end
+
def apply_filters(model_class=nil)
return super if @read_users.any?(&:is_admin)
if params[:uuid] != current_user.andand.uuid
diff --git a/services/api/app/models/user.rb b/services/api/app/models/user.rb
index f3ca759..212047f 100644
--- a/services/api/app/models/user.rb
+++ b/services/api/app/models/user.rb
@@ -254,6 +254,29 @@ class User < ArvadosModel
end
end
+ def update_uuid(new_uuid:)
+ if !current_user.andand.is_admin
+ raise PermissionDeniedError
+ end
+ if self.class != self.class.resource_class_for_uuid(new_uuid)
+ raise "invalid new_uuid #{new_uuid.inspect}"
+ end
+ transaction(requires_new: true) do
+ reload
+ old_uuid = self.uuid
+ self.uuid = new_uuid
+ save!(validate: false)
+ ActiveRecord::Base.descendants.reject(&:abstract_class?).each do |klass|
+ klass.columns.each do |col|
+ if col.name.end_with?('_uuid')
+ column = col.name.to_sym
+ klass.where(column => old_uuid).update_all(column => new_uuid)
+ end
+ end
+ end
+ end
+ end
+
protected
def ensure_ownership_path_leads_to_user
diff --git a/services/api/config/routes.rb b/services/api/config/routes.rb
index 5b6fe80..fcd5c34 100644
--- a/services/api/config/routes.rb
+++ b/services/api/config/routes.rb
@@ -79,6 +79,7 @@ Server::Application.routes.draw do
post 'activate', on: :member
post 'setup', on: :collection
post 'unsetup', on: :member
+ post 'update_uuid', on: :member
end
resources :virtual_machines do
get 'logins', on: :member
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 b75479f..176104e 100644
--- a/services/api/test/functional/arvados/v1/users_controller_test.rb
+++ b/services/api/test/functional/arvados/v1/users_controller_test.rb
@@ -794,6 +794,28 @@ class Arvados::V1::UsersControllerTest < ActionController::TestCase
"user's writable_by should include its owner_uuid")
end
+ test 'update_uuid as admin' do
+ authorize_with :admin
+ orig_uuid = users(:active).uuid
+ post :update_uuid, {
+ id: orig_uuid,
+ new_uuid: 'zbbbb-tpzed-abcde12345abcde',
+ }
+ assert_response :success
+ assert_empty User.where(uuid: orig_uuid)
+ end
+
+ test 'update_uuid as non-admin' do
+ authorize_with :active
+ orig_uuid = users(:active).uuid
+ post :update_uuid, {
+ id: orig_uuid,
+ new_uuid: 'zbbbb-tpzed-abcde12345abcde',
+ }
+ assert_response 403
+ assert_not_empty User.where(uuid: orig_uuid)
+ end
+
NON_ADMIN_USER_DATA = ["uuid", "kind", "is_active", "email", "first_name",
"last_name"].sort
diff --git a/services/api/test/unit/user_test.rb b/services/api/test/unit/user_test.rb
index 3d8fb9d..3c85bd1 100644
--- a/services/api/test/unit/user_test.rb
+++ b/services/api/test/unit/user_test.rb
@@ -721,4 +721,73 @@ class UserTest < ActiveSupport::TestCase
end
end
+ [
+ 'zzzzz-borkd-abcde12345abcde',
+ 'zzzzz-j7d0g-abcde12345abcde',
+ 'zzzzz-tpzed-borkd',
+ ].each do |new_uuid|
+ test "update_uuid to invalid uuid #{new_uuid}" do
+ u = users(:active)
+ orig_uuid = u.uuid
+ act_as_system_user do
+ assert_raises do
+ u.update_uuid(new_uuid: new_uuid)
+ end
+ end
+ # "Successfully aborted orig->new" outcome looks the same as
+ # "successfully updated new->orig".
+ assert_update_success(old_uuid: new_uuid, new_uuid: orig_uuid)
+ end
+ end
+
+ [:active, :spectator, :admin].each do |target|
+ test "update_uuid on #{target} as non-admin user" do
+ act_as_user users(:active) do
+ assert_raises(ArvadosModel::PermissionDeniedError) do
+ users(target).update_uuid(new_uuid: 'zzzzz-tpzed-abcde12345abcde')
+ end
+ end
+ end
+ end
+
+ test "update_uuid to existing uuid" do
+ u = users(:active)
+ orig_uuid = u.uuid
+ new_uuid = users(:admin).uuid
+ act_as_system_user do
+ assert_raises do
+ u.update_uuid(new_uuid: new_uuid)
+ end
+ end
+ u.reload
+ assert_equal u.uuid, orig_uuid
+ assert_not_empty Collection.where(owner_uuid: orig_uuid)
+ assert_not_empty Group.where(owner_uuid: orig_uuid)
+ end
+
+ [
+ 'zbbbb-tpzed-abcde12345abcde',
+ 'zzzzz-tpzed-abcde12345abcde',
+ ].each do |new_uuid|
+ test "update_uuid to unused uuid #{new_uuid}" do
+ u = users(:active)
+ orig_uuid = u.uuid
+ act_as_system_user do
+ u.update_uuid(new_uuid: new_uuid)
+ end
+ assert_update_success(old_uuid: orig_uuid, new_uuid: new_uuid)
+ end
+ end
+
+ def assert_update_success(old_uuid:, new_uuid:)
+ [[User, :uuid],
+ [Link, :head_uuid],
+ [Link, :tail_uuid],
+ [Group, :owner_uuid],
+ [Collection, :owner_uuid],
+ ].each do |klass, attr|
+ assert_empty klass.where(attr => old_uuid)
+ assert_not_empty klass.where(attr => new_uuid)
+ end
+ end
end
-----------------------------------------------------------------------
hooks/post-receive
--
More information about the arvados-commits
mailing list