3687: Merge branch 'master' into 3687-grant-permission-on-repo-TC
[arvados.git] / services / api / app / models / user.rb
index 0053ce0dc3ba16c4e2a8f4ba07a0af3be3b17885..6e7facd5d550ee45bd948a255e28e5b18ddec6cb 100644 (file)
@@ -70,6 +70,30 @@ class User < ArvadosModel
         next if (group_permissions[target.owner_uuid] and
                  group_permissions[target.owner_uuid][action])
       end
+      sufficient_perms = case action
+                         when :manage
+                           ['can_manage']
+                         when :write
+                           ['can_manage', 'can_write']
+                         when :read
+                           ['can_manage', 'can_write', 'can_read']
+                         else
+                           # (Skip this kind of permission opportunity
+                           # if action is an unknown permission type)
+                         end
+      if sufficient_perms
+        # Check permission links with head_uuid pointing directly at
+        # the target object. If target is a Group, this is redundant
+        # and will fail except [a] if permission caching is broken or
+        # [b] during a race condition, where a permission link has
+        # *just* been added.
+        if Link.where(link_class: 'permission',
+                      name: sufficient_perms,
+                      tail_uuid: groups_i_can(action) + [self.uuid],
+                      head_uuid: target_uuid).any?
+          next
+        end
+      end
       return false
     end
     true
@@ -104,12 +128,13 @@ class User < ArvadosModel
         Group.where('owner_uuid in (?)', lookup_uuids).each do |group|
           newgroups << [group.owner_uuid, group.uuid, 'can_manage']
         end
-        # add any permission links from the current lookup_uuids to a
-        # User or Group.
-        Link.where('tail_uuid in (?) and link_class = ? and (head_uuid like ? or head_uuid like ?)',
-                   lookup_uuids,
+        # add any permission links from the current lookup_uuids to a Group.
+        Link.where('link_class = ? and tail_uuid in (?) and ' \
+                   '(head_uuid like ? or (name = ? and head_uuid like ?))',
                    'permission',
+                   lookup_uuids,
                    Group.uuid_like_pattern,
+                   'can_manage',
                    User.uuid_like_pattern).each do |link|
           newgroups << [link.tail_uuid, link.head_uuid, link.name]
         end
@@ -431,44 +456,34 @@ class User < ArvadosModel
       username = self.email.partition('@')[0] if self.email
       return true if !username
 
-      username = username.gsub!(/[-._]/, '') || username
       blacklisted_usernames = Rails.configuration.auto_setup_name_blacklist
       if blacklisted_usernames.include?(username)
-        return true;
-      elsif !(/^[a-zA-Z][a-zA-Z0-9]{0,31}$/.match(username))
+        return true
+      elsif !(/^[a-zA-Z][-._a-zA-Z0-9]{0,30}[a-zA-Z0-9]$/.match(username))
         return true
       else
-        username = derive_unique_username username
-      end  
+        return true if !(username = derive_unique_username username)
+      end
     end
+
     # setup user
-    if !Rails.configuration.auto_setup_new_users_with_vm_uuid &&
-       !Rails.configuration.auto_setup_new_users_with_repository
-      oid_login_perm = create_oid_login_perm Rails.configuration.default_openid_prefix
-      group_perm = create_user_group_link
-    else
-      setup_repo_vm_links(username,
-                          Rails.configuration.auto_setup_new_users_with_vm_uuid,
-                          Rails.configuration.default_openid_prefix)
-    end
+    setup_repo_vm_links(username,
+                        Rails.configuration.auto_setup_new_users_with_vm_uuid,
+                        Rails.configuration.default_openid_prefix)
   end
 
   # Find a username that starts with the given string and does not collide
   # with any existing repository name or VM login name
   def derive_unique_username username
-    vm_uuid = Rails.configuration.auto_setup_new_users_with_vm_uuid
     while true
       if Repository.where(name: username).empty?
-        login_collisions = Link.where(head_uuid: vm_uuid,
-                                      link_class: 'permission',
+        login_collisions = Link.where(link_class: 'permission',
                                       name: 'can_login').select do |perm|
           perm.properties['username'] == username
         end
-        if login_collisions.empty?
-          return username
-        end
+        return username if login_collisions.empty?
       end
-      username = username + SecureRandom.random_number(100).to_s
+      username = username + SecureRandom.random_number(10).to_s
     end
   end