Arvados-DCO-1.1-Signed-off-by: Radhika Chippada <radhika@curoverse.com>
[arvados.git] / services / api / lib / current_api_client.rb
index 4c26010d2a4a3c0e6c38ae7911c2c9eb84eb822f..711c663a233058786ee32b48a842b29cbff456d8 100644 (file)
@@ -1,3 +1,15 @@
+# Copyright (C) The Arvados Authors. All rights reserved.
+#
+# SPDX-License-Identifier: AGPL-3.0
+
+$system_user = nil
+$system_group = nil
+$all_users_group = nil
+$anonymous_user = nil
+$anonymous_group = nil
+$anonymous_group_read_permission = nil
+$empty_collection = nil
+
 module CurrentApiClient
   def current_user
     Thread.current[:user]
@@ -54,48 +66,61 @@ module CurrentApiClient
   end
 
   def system_user
-    if not $system_user
+    $system_user = check_cache $system_user do
       real_current_user = Thread.current[:user]
-      Thread.current[:user] = User.new(is_admin: true,
-                                       is_active: true,
-                                       uuid: system_user_uuid)
-      $system_user = User.where('uuid=?', system_user_uuid).first
-      if !$system_user
-        $system_user = User.new(uuid: system_user_uuid,
-                                is_active: true,
-                                is_admin: true,
-                                email: 'root',
-                                first_name: 'root',
-                                last_name: '')
-        $system_user.save!
-        $system_user.reload
+      begin
+        Thread.current[:user] = User.new(is_admin: true,
+                                         is_active: true,
+                                         uuid: system_user_uuid)
+        User.where(uuid: system_user_uuid).
+          first_or_create!(is_active: true,
+                           is_admin: true,
+                           email: 'root',
+                           first_name: 'root',
+                           last_name: '')
+      ensure
+        Thread.current[:user] = real_current_user
       end
-      Thread.current[:user] = real_current_user
     end
-    $system_user
   end
 
   def system_group
-    if not $system_group
+    $system_group = check_cache $system_group do
       act_as_system_user do
         ActiveRecord::Base.transaction do
-          $system_group = Group.
-            where(uuid: system_group_uuid).first_or_create do |g|
-            g.update_attributes(name: "System group",
-                                description: "System group")
+          Group.where(uuid: system_group_uuid).
+            first_or_create!(name: "System group",
+                             description: "System group") do |g|
+            g.save!
             User.all.collect(&:uuid).each do |user_uuid|
-              Link.create(link_class: 'permission',
-                          name: 'can_manage',
-                          tail_kind: 'arvados#group',
-                          tail_uuid: system_group_uuid,
-                          head_kind: 'arvados#user',
-                          head_uuid: user_uuid)
+              Link.create!(link_class: 'permission',
+                           name: 'can_manage',
+                           tail_uuid: system_group_uuid,
+                           head_uuid: user_uuid)
             end
           end
         end
       end
     end
-    $system_group
+  end
+
+  def all_users_group_uuid
+    [Server::Application.config.uuid_prefix,
+     Group.uuid_prefix,
+     'fffffffffffffff'].join('-')
+  end
+
+  def all_users_group
+    $all_users_group = check_cache $all_users_group do
+      act_as_system_user do
+        ActiveRecord::Base.transaction do
+          Group.where(uuid: all_users_group_uuid).
+            first_or_create!(name: "All users",
+                             description: "All users",
+                             group_class: "role")
+        end
+      end
+    end
   end
 
   def act_as_system_user
@@ -109,59 +134,64 @@ module CurrentApiClient
   end
 
   def act_as_user user
+    #auth_was = Thread.current[:api_client_authorization]
     user_was = Thread.current[:user]
     Thread.current[:user] = user
+    #Thread.current[:api_client_authorization] = ApiClientAuthorization.
+    #  where('user_id=? and scopes is null', user.id).
+    #  order('expires_at desc').
+    #  first
     begin
       yield
     ensure
       Thread.current[:user] = user_was
+      #Thread.current[:api_client_authorization] = auth_was
     end
   end
 
   def anonymous_group
-    if not $anonymous_group
+    $anonymous_group = check_cache $anonymous_group do
       act_as_system_user do
         ActiveRecord::Base.transaction do
-          $anonymous_group = Group.
-          where(uuid: anonymous_group_uuid).first_or_create do |g|
-            g.update_attributes(name: "Anonymous group",
-                                description: "Anonymous group")
-          end
+          Group.where(uuid: anonymous_group_uuid).
+            first_or_create!(group_class: "role",
+                             name: "Anonymous users",
+                             description: "Anonymous users")
         end
       end
     end
-    $anonymous_group
   end
 
-  def anonymous_user
-    if not $anonymous_user
+  def anonymous_group_read_permission
+    $anonymous_group_read_permission =
+        check_cache $anonymous_group_read_permission do
       act_as_system_user do
-        $anonymous_user = User.where('uuid=?', anonymous_user_uuid).first
-        if !$anonymous_user
-          $anonymous_user = User.new(uuid: anonymous_user_uuid,
-                                     is_active: false,
-                                     is_admin: false,
-                                     email: 'anonymouspublic',
-                                     first_name: 'anonymouspublic',
-                                     last_name: 'anonymouspublic')
-          $anonymous_user.save!
-          $anonymous_user.reload
-        end
-
-        group_perms = Link.where(tail_uuid: anonymous_user_uuid,
-                                 head_uuid: anonymous_group_uuid,
-                                 link_class: 'permission',
-                                 name: 'can_read')
+        Link.where(tail_uuid: all_users_group.uuid,
+                   head_uuid: anonymous_group.uuid,
+                   link_class: "permission",
+                   name: "can_read").first_or_create!
+      end
+    end
+  end
 
-        if !group_perms.any?
-          group_perm = Link.create!(tail_uuid: anonymous_user_uuid,
-                                    head_uuid: anonymous_group_uuid,
-                                    link_class: 'permission',
-                                    name: 'can_read')
+  def anonymous_user
+    $anonymous_user = check_cache $anonymous_user do
+      act_as_system_user do
+        User.where(uuid: anonymous_user_uuid).
+          first_or_create!(is_active: false,
+                           is_admin: false,
+                           email: 'anonymous',
+                           first_name: 'Anonymous',
+                           last_name: '') do |u|
+          u.save!
+          Link.where(tail_uuid: anonymous_user_uuid,
+                     head_uuid: anonymous_group.uuid,
+                     link_class: 'permission',
+                     name: 'can_read').
+            first_or_create!
         end
       end
     end
-    $anonymous_user
   end
 
   def empty_collection_uuid
@@ -169,15 +199,42 @@ module CurrentApiClient
   end
 
   def empty_collection
-    if not $empty_collection
+    $empty_collection = check_cache $empty_collection do
       act_as_system_user do
         ActiveRecord::Base.transaction do
-          $empty_collection = Collection.
+          Collection.
             where(portable_data_hash: empty_collection_uuid).
             first_or_create!(manifest_text: '', owner_uuid: anonymous_group.uuid)
         end
       end
     end
-    $empty_collection
+  end
+
+  private
+
+  # If the given value is nil, or the cache has been cleared since it
+  # was set, yield. Otherwise, return the given value.
+  def check_cache value
+    if not Rails.env.test? and
+        ActionController::Base.cache_store.is_a? ActiveSupport::Cache::FileStore and
+        not File.owned? ActionController::Base.cache_store.cache_path
+      # If we don't own the cache dir, we're probably
+      # crunch-dispatch. Whoever we are, using this cache is likely to
+      # either fail or screw up the cache for someone else. So we'll
+      # just assume the $globals are OK to live forever.
+      #
+      # The reason for making the globals expire with the cache in the
+      # first place is to avoid leaking state between test cases: in
+      # production, we don't expect the database seeds to ever go away
+      # even when the cache is cleared, so there's no particular
+      # reason to expire our global variables.
+    else
+      Rails.cache.fetch "CurrentApiClient.$globals" do
+        value = nil
+        true
+      end
+    end
+    return value unless value.nil?
+    yield
   end
 end