Merge pull request #1 from curoverse/master
[arvados.git] / services / api / app / models / user.rb
index 9bdd14d94ffbac93c554727734582d80dd107560..a47a4583cd533e272d9b5f850b4281aef75f26c3 100644 (file)
@@ -29,6 +29,7 @@ class User < ArvadosModel
     t.add :is_admin
     t.add :is_invited
     t.add :prefs
+    t.add :writable_by
   end
 
   ALL_PERMISSIONS = {read: true, write: true, manage: true}
@@ -70,6 +71,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 +129,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
@@ -208,11 +234,13 @@ class User < ArvadosModel
   end
 
   def check_auto_admin
-    if User.where("uuid not like '%-000000000000000'").where(:is_admin => true).count == 0 and Rails.configuration.auto_admin_user
-      if self.email == Rails.configuration.auto_admin_user
-        self.is_admin = true
-        self.is_active = true
-      end
+    return if self.uuid.end_with?('anonymouspublic')
+    if (User.where("email = ?",self.email).where(:is_admin => true).count == 0 and
+        Rails.configuration.auto_admin_user and self.email == Rails.configuration.auto_admin_user) or
+       (User.where("uuid not like '%-000000000000000'").where(:is_admin => true).count == 0 and 
+        Rails.configuration.auto_admin_first_user)
+      self.is_admin = true
+      self.is_active = true
     end
   end
 
@@ -371,40 +399,20 @@ class User < ArvadosModel
 
   # add the user to the 'All users' group
   def create_user_group_link
-    # Look up the "All users" group (we expect uuid *-*-fffffffffffffff).
-    group = Group.where(name: 'All users').select do |g|
-      g[:uuid].match /-f+$/
-    end.first
-
-    if not group
-      logger.warn "No 'All users' group with uuid '*-*-fffffffffffffff'."
-      raise "No 'All users' group with uuid '*-*-fffffffffffffff' is found"
-    else
-      logger.info { "\"All users\" group uuid: " + group[:uuid] }
-
-      group_perms = Link.where(tail_uuid: self.uuid,
-                              head_uuid: group[:uuid],
-                              link_class: 'permission',
-                              name: 'can_read')
-
-      if !group_perms.any?
-        group_perm = Link.create(tail_uuid: self.uuid,
-                                 head_uuid: group[:uuid],
-                                 link_class: 'permission',
-                                 name: 'can_read')
-        logger.info { "group permission: " + group_perm[:uuid] }
-      else
-        group_perm = group_perms.first
-      end
-
-      return group_perm
-    end
+    return (Link.where(tail_uuid: self.uuid,
+                       head_uuid: all_users_group[:uuid],
+                       link_class: 'permission',
+                       name: 'can_read').first or
+            Link.create(tail_uuid: self.uuid,
+                        head_uuid: all_users_group[:uuid],
+                        link_class: 'permission',
+                        name: 'can_read'))
   end
 
   # Give the special "System group" permission to manage this user and
   # all of this user's stuff.
-  #
   def add_system_group_permission_link
+    return true if uuid == system_user_uuid
     act_as_system_user do
       Link.create(link_class: 'permission',
                   name: 'can_manage',
@@ -425,6 +433,8 @@ class User < ArvadosModel
   def auto_setup_new_user
     return true if !Rails.configuration.auto_setup_new_users
     return true if !self.email
+    return true if self.uuid == system_user_uuid
+    return true if self.uuid == anonymous_user_uuid
 
     if Rails.configuration.auto_setup_new_users_with_vm_uuid ||
        Rails.configuration.auto_setup_new_users_with_repository