Merge branch '22226-empty-output-panic'
[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 module CurrentApiClient
6   def current_user
7     Thread.current[:user]
8   end
9
10   def current_api_client_authorization
11     Thread.current[:api_client_authorization]
12   end
13
14   def current_api_base
15     Thread.current[:api_url_base]
16   end
17
18   # Where is the client connecting from?
19   def current_api_client_ip_address
20     Thread.current[:api_client_ip_address]
21   end
22
23   def system_user_uuid
24     [Rails.configuration.ClusterID,
25      User.uuid_prefix,
26      '000000000000000'].join('-')
27   end
28
29   def system_group_uuid
30     [Rails.configuration.ClusterID,
31      Group.uuid_prefix,
32      '000000000000000'].join('-')
33   end
34
35   def anonymous_group_uuid
36     [Rails.configuration.ClusterID,
37      Group.uuid_prefix,
38      'anonymouspublic'].join('-')
39   end
40
41   def anonymous_user_uuid
42     [Rails.configuration.ClusterID,
43      User.uuid_prefix,
44      'anonymouspublic'].join('-')
45   end
46
47   def public_project_uuid
48     [Rails.configuration.ClusterID,
49      Group.uuid_prefix,
50      'publicfavorites'].join('-')
51   end
52
53   def system_user
54     real_current_user = Thread.current[:user]
55     begin
56       Thread.current[:user] = User.new(is_admin: true,
57                                        is_active: true,
58                                        uuid: system_user_uuid)
59       $system_user = check_cache($system_user) do
60         User.where(uuid: system_user_uuid).
61           first_or_create!(is_active: true,
62                            is_admin: true,
63                            email: 'root',
64                            first_name: 'root',
65                            last_name: '')
66       end
67     ensure
68       Thread.current[:user] = real_current_user
69     end
70   end
71
72   def system_group
73     $system_group = check_cache($system_group) do
74       act_as_system_user do
75         ActiveRecord::Base.transaction do
76           Group.where(uuid: system_group_uuid).
77             first_or_create!(name: "System group",
78                              description: "System group",
79                              group_class: "role") do |g|
80             g.save!
81             User.all.collect(&:uuid).each do |user_uuid|
82               Link.create!(link_class: 'permission',
83                            name: 'can_manage',
84                            tail_uuid: system_group_uuid,
85                            head_uuid: user_uuid)
86             end
87           end
88         end
89       end
90     end
91   end
92
93   def all_users_group_uuid
94     [Rails.configuration.ClusterID,
95      Group.uuid_prefix,
96      'fffffffffffffff'].join('-')
97   end
98
99   def all_users_group
100     $all_users_group = check_cache($all_users_group) do
101       act_as_system_user do
102         ActiveRecord::Base.transaction do
103           Group.where(uuid: all_users_group_uuid).
104             first_or_create!(name: "All users",
105                              description: "All users",
106                              group_class: "role")
107         end
108       end
109     end
110   end
111
112   def act_as_system_user
113     if block_given?
114       act_as_user system_user do
115         yield
116       end
117     else
118       Thread.current[:user] = system_user
119     end
120   end
121
122   def act_as_user user
123     user_was = Thread.current[:user]
124     Thread.current[:user] = user
125     begin
126       yield
127     ensure
128       Thread.current[:user] = user_was
129       if user_was
130         user_was.forget_cached_group_perms
131       end
132     end
133   end
134
135   def anonymous_group
136     $anonymous_group = check_cache($anonymous_group) do
137       act_as_system_user do
138         ActiveRecord::Base.transaction do
139           Group.where(uuid: anonymous_group_uuid).
140             first_or_create!(group_class: "role",
141                              name: "Anonymous users",
142                              description: "Anonymous users")
143         end
144       end
145     end
146   end
147
148   def anonymous_group_read_permission
149     $anonymous_group_read_permission = check_cache($anonymous_group_read_permission) do
150       act_as_system_user do
151         Link.where(tail_uuid: all_users_group.uuid,
152                    head_uuid: anonymous_group.uuid,
153                    link_class: "permission",
154                    name: "can_read").first_or_create!
155       end
156     end
157   end
158
159   def anonymous_user
160     $anonymous_user = check_cache($anonymous_user) do
161       act_as_system_user do
162         User.where(uuid: anonymous_user_uuid).
163           first_or_create!(is_active: false,
164                            is_admin: false,
165                            email: 'anonymous',
166                            first_name: 'Anonymous',
167                            last_name: '') do |u|
168           u.save!
169           Link.where(tail_uuid: anonymous_user_uuid,
170                      head_uuid: anonymous_group.uuid,
171                      link_class: 'permission',
172                      name: 'can_read').
173             first_or_create!
174         end
175       end
176     end
177   end
178
179   def public_project_group
180     $public_project_group = check_cache($public_project_group) do
181       act_as_system_user do
182         ActiveRecord::Base.transaction do
183           Group.where(uuid: public_project_uuid).
184             first_or_create!(group_class: "project",
185                              name: "Public favorites",
186                              description: "Public favorites")
187         end
188       end
189     end
190   end
191
192   def public_project_read_permission
193     $public_project_group_read_permission = check_cache($public_project_group_read_permission) do
194       act_as_system_user do
195         Link.where(tail_uuid: anonymous_group.uuid,
196                    head_uuid: public_project_group.uuid,
197                    link_class: "permission",
198                    name: "can_read").first_or_create!
199       end
200     end
201   end
202
203   def empty_collection_pdh
204     'd41d8cd98f00b204e9800998ecf8427e+0'
205   end
206
207   def empty_collection
208     $empty_collection = check_cache($empty_collection) do
209       act_as_system_user do
210         ActiveRecord::Base.transaction do
211           Collection.
212             where(portable_data_hash: empty_collection_pdh).
213             first_or_create(manifest_text: '', owner_uuid: system_user.uuid, name: "empty collection") do |c|
214             c.save!
215             Link.where(tail_uuid: anonymous_group.uuid,
216                        head_uuid: c.uuid,
217                        link_class: 'permission',
218                        name: 'can_read').
219                   first_or_create!
220             c
221           end
222         end
223       end
224     end
225   end
226
227   # Purge the module globals if necessary. If the cached value is
228   # non-nil and the globals weren't purged, return the cached
229   # value. Otherwise, call the block.
230   #
231   # Purge is only done in test mode.
232   def check_cache(cached)
233     if Rails.env != 'test'
234       return (cached || yield)
235     end
236     t = Rails.cache.fetch "CurrentApiClient.$system_globals_reset" do
237       Time.now.to_f
238     end
239     if t != $system_globals_reset
240       reset_system_globals(t)
241       yield
242     else
243       cached || yield
244     end
245   end
246
247   def reset_system_globals(t)
248     $system_globals_reset = t
249     $system_user = nil
250     $system_group = nil
251     $all_users_group = nil
252     $anonymous_group = nil
253     $anonymous_group_read_permission = nil
254     $anonymous_user = nil
255     $public_project_group = nil
256     $public_project_group_read_permission = nil
257     $empty_collection = nil
258   end
259   module_function :reset_system_globals
260 end
261
262 CurrentApiClient.reset_system_globals(0)