Merge branch 'patch-1' of https://github.com/mr-c/arvados into mr-c-patch-1
[arvados.git] / services / api / lib / current_api_client.rb
1 # Copyright (C) The Arvados Authors. All rights reserved.
2 #
3 # SPDX-License-Identifier: AGPL-3.0
4
5 $system_user = nil
6 $system_group = nil
7 $all_users_group = nil
8 $anonymous_user = nil
9 $anonymous_group = nil
10 $anonymous_group_read_permission = nil
11 $empty_collection = nil
12
13 module CurrentApiClient
14   def current_user
15     Thread.current[:user]
16   end
17
18   def current_api_client
19     Thread.current[:api_client]
20   end
21
22   def current_api_client_authorization
23     Thread.current[:api_client_authorization]
24   end
25
26   def current_api_base
27     Thread.current[:api_url_base]
28   end
29
30   def current_default_owner
31     # owner_uuid for newly created objects
32     ((current_api_client_authorization &&
33       current_api_client_authorization.default_owner_uuid) ||
34      (current_user && current_user.default_owner_uuid) ||
35      (current_user && current_user.uuid) ||
36      nil)
37   end
38
39   # Where is the client connecting from?
40   def current_api_client_ip_address
41     Thread.current[:api_client_ip_address]
42   end
43
44   def system_user_uuid
45     [Rails.configuration.ClusterID,
46      User.uuid_prefix,
47      '000000000000000'].join('-')
48   end
49
50   def system_group_uuid
51     [Rails.configuration.ClusterID,
52      Group.uuid_prefix,
53      '000000000000000'].join('-')
54   end
55
56   def anonymous_group_uuid
57     [Rails.configuration.ClusterID,
58      Group.uuid_prefix,
59      'anonymouspublic'].join('-')
60   end
61
62   def anonymous_user_uuid
63     [Rails.configuration.ClusterID,
64      User.uuid_prefix,
65      'anonymouspublic'].join('-')
66   end
67
68   def system_user
69     $system_user = check_cache $system_user do
70       real_current_user = Thread.current[:user]
71       begin
72         Thread.current[:user] = User.new(is_admin: true,
73                                          is_active: true,
74                                          uuid: system_user_uuid)
75         User.where(uuid: system_user_uuid).
76           first_or_create!(is_active: true,
77                            is_admin: true,
78                            email: 'root',
79                            first_name: 'root',
80                            last_name: '')
81       ensure
82         Thread.current[:user] = real_current_user
83       end
84     end
85   end
86
87   def system_group
88     $system_group = check_cache $system_group do
89       act_as_system_user do
90         ActiveRecord::Base.transaction do
91           Group.where(uuid: system_group_uuid).
92             first_or_create!(name: "System group",
93                              description: "System group",
94                              group_class: "role") do |g|
95             g.save!
96             User.all.collect(&:uuid).each do |user_uuid|
97               Link.create!(link_class: 'permission',
98                            name: 'can_manage',
99                            tail_uuid: system_group_uuid,
100                            head_uuid: user_uuid)
101             end
102           end
103         end
104       end
105     end
106   end
107
108   def all_users_group_uuid
109     [Rails.configuration.ClusterID,
110      Group.uuid_prefix,
111      'fffffffffffffff'].join('-')
112   end
113
114   def all_users_group
115     $all_users_group = check_cache $all_users_group do
116       act_as_system_user do
117         ActiveRecord::Base.transaction do
118           Group.where(uuid: all_users_group_uuid).
119             first_or_create!(name: "All users",
120                              description: "All users",
121                              group_class: "role")
122         end
123       end
124     end
125   end
126
127   def act_as_system_user
128     if block_given?
129       act_as_user system_user do
130         yield
131       end
132     else
133       Thread.current[:user] = system_user
134     end
135   end
136
137   def act_as_user user
138     user_was = Thread.current[:user]
139     Thread.current[:user] = user
140     begin
141       yield
142     ensure
143       Thread.current[:user] = user_was
144     end
145   end
146
147   def anonymous_group
148     $anonymous_group = check_cache $anonymous_group do
149       act_as_system_user do
150         ActiveRecord::Base.transaction do
151           Group.where(uuid: anonymous_group_uuid).
152             first_or_create!(group_class: "role",
153                              name: "Anonymous users",
154                              description: "Anonymous users")
155         end
156       end
157     end
158   end
159
160   def anonymous_group_read_permission
161     $anonymous_group_read_permission =
162         check_cache $anonymous_group_read_permission do
163       act_as_system_user do
164         Link.where(tail_uuid: all_users_group.uuid,
165                    head_uuid: anonymous_group.uuid,
166                    link_class: "permission",
167                    name: "can_read").first_or_create!
168       end
169     end
170   end
171
172   def anonymous_user
173     $anonymous_user = check_cache $anonymous_user do
174       act_as_system_user do
175         User.where(uuid: anonymous_user_uuid).
176           first_or_create!(is_active: false,
177                            is_admin: false,
178                            email: 'anonymous',
179                            first_name: 'Anonymous',
180                            last_name: '') do |u|
181           u.save!
182           Link.where(tail_uuid: anonymous_user_uuid,
183                      head_uuid: anonymous_group.uuid,
184                      link_class: 'permission',
185                      name: 'can_read').
186             first_or_create!
187         end
188       end
189     end
190   end
191
192   def empty_collection_pdh
193     'd41d8cd98f00b204e9800998ecf8427e+0'
194   end
195
196   def empty_collection
197     $empty_collection = check_cache $empty_collection do
198       act_as_system_user do
199         ActiveRecord::Base.transaction do
200           Collection.
201             where(portable_data_hash: empty_collection_pdh).
202             first_or_create(manifest_text: '', owner_uuid: system_user.uuid, name: "empty collection") do |c|
203             c.save!
204             Link.where(tail_uuid: anonymous_group.uuid,
205                        head_uuid: c.uuid,
206                        link_class: 'permission',
207                        name: 'can_read').
208                   first_or_create!
209             c
210           end
211         end
212       end
213     end
214   end
215
216   private
217
218   # If the given value is nil, or the cache has been cleared since it
219   # was set, yield. Otherwise, return the given value.
220   def check_cache value
221     if not Rails.env.test? and
222         ActionController::Base.cache_store.is_a? ActiveSupport::Cache::FileStore and
223         not File.owned? ActionController::Base.cache_store.cache_path
224       # If we don't own the cache dir, we're probably
225       # crunch-dispatch. Whoever we are, using this cache is likely to
226       # either fail or screw up the cache for someone else. So we'll
227       # just assume the $globals are OK to live forever.
228       #
229       # The reason for making the globals expire with the cache in the
230       # first place is to avoid leaking state between test cases: in
231       # production, we don't expect the database seeds to ever go away
232       # even when the cache is cleared, so there's no particular
233       # reason to expire our global variables.
234     else
235       Rails.cache.fetch "CurrentApiClient.$globals" do
236         value = nil
237         true
238       end
239     end
240     return value unless value.nil?
241     yield
242   end
243 end