18693: Return existing instead of creating redundant can_login link.
authorTom Clegg <tom@curii.com>
Mon, 19 Dec 2022 01:19:47 +0000 (20:19 -0500)
committerTom Clegg <tom@curii.com>
Mon, 19 Dec 2022 01:19:47 +0000 (20:19 -0500)
Arvados-DCO-1.1-Signed-off-by: Tom Clegg <tom@curii.com>

services/api/app/controllers/arvados/v1/links_controller.rb
services/api/test/integration/permissions_test.rb

index 19b6d439a473b2da5897000c443ceadbb941b69e..c9ebe034608505b1c7115fbab2de262bfd727b28 100644 (file)
@@ -37,6 +37,19 @@ class Arvados::V1::LinksController < ApplicationController
           return show
         end
       end
+    elsif resource_attrs[:link_class] == 'permission' &&
+          resource_attrs[:name] == 'can_login' &&
+          resource_attrs[:properties].respond_to?(:has_key?) &&
+          resource_attrs[:properties].has_key?(:username)
+      existing = Link.where(link_class: 'permission',
+                            tail_uuid: resource_attrs[:tail_uuid],
+                            head_uuid: resource_attrs[:head_uuid]).
+                   where('properties @> ?', SafeJSON.dump({'username' => resource_attrs[:properties][:username]})).
+                   first
+      if existing
+        @object = existing
+        return show
+      end
     end
 
     super
index fab51d4003232b3a02fc227daf271d026557819b..d2dce44f018a0ce2e63232889d9d7cc4fe412aae 100644 (file)
@@ -746,4 +746,53 @@ class PermissionsTest < ActionDispatch::IntegrationTest
       assert_equal expect, link1.name
     end
   end
+
+  test "creating duplicate login permission returns existing link" do
+    link1 = act_as_system_user do
+      Link.create!({
+                     link_class: "permission",
+                     tail_uuid: users(:active).uuid,
+                     head_uuid: virtual_machines(:testvm2).uuid,
+                     name: "can_login",
+                     properties: {"username": "foo1"}
+                   })
+    end
+    link2 = act_as_system_user do
+      Link.create!({
+                     link_class: "permission",
+                     tail_uuid: users(:active).uuid,
+                     head_uuid: virtual_machines(:testvm2).uuid,
+                     name: "can_login",
+                     properties: {"username": "foo2"}
+                   })
+    end
+    link3 = act_as_system_user do
+      Link.create!({
+                     link_class: "permission",
+                     tail_uuid: users(:active).uuid,
+                     head_uuid: virtual_machines(:testvm2).uuid,
+                     name: "can_read",
+                   })
+    end
+    post "/arvados/v1/links",
+         params: {
+           link: {
+             link_class: "permission",
+             tail_uuid: users(:active).uuid,
+             head_uuid: virtual_machines(:testvm2).uuid,
+             name: "can_login",
+             properties: {"username": "foo2"},
+           },
+         },
+         headers: auth(:admin)
+    assert_response :success
+    assert_equal link2.uuid, json_response["uuid"]
+    assert_equal link2.created_at.to_date, json_response["created_at"].to_date
+    assert_equal "can_login", json_response["name"]
+    assert_equal "foo2", json_response["properties"]["username"]
+    link1.reload
+    assert_equal "foo1", link1.properties["username"]
+    link2.reload
+    assert_equal "foo2", link2.properties["username"]
+  end
 end