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