3604: Fix theme support for welcome page
[arvados.git] / apps / workbench / app / controllers / users_controller.rb
1 class UsersController < ApplicationController
2   skip_around_filter :require_thread_api_token, only: :welcome
3   skip_before_filter :check_user_agreements, only: :inactive
4   skip_before_filter :find_object_by_uuid, only: [:welcome, :activity, :storage]
5   before_filter :ensure_current_user_is_admin, only: [:sudo, :unsetup, :setup]
6
7   def welcome
8     if current_user
9       redirect_to (params[:return_to] || '/')
10     end
11   end
12
13   def inactive
14     if current_user.andand.is_invited
15       redirect_to (params[:return_to] || '/')
16     end
17   end
18
19   def activity
20     @breadcrumb_page_name = nil
21     @users = User.limit(params[:limit] || 1000).all
22     @user_activity = {}
23     @activity = {
24       logins: {},
25       jobs: {},
26       pipeline_instances: {}
27     }
28     @total_activity = {}
29     @spans = [['This week', Time.now.beginning_of_week, Time.now],
30               ['Last week',
31                Time.now.beginning_of_week.advance(weeks:-1),
32                Time.now.beginning_of_week],
33               ['This month', Time.now.beginning_of_month, Time.now],
34               ['Last month',
35                1.month.ago.beginning_of_month,
36                Time.now.beginning_of_month]]
37     @spans.each do |span, threshold_start, threshold_end|
38       @activity[:logins][span] = Log.
39         filter([[:event_type, '=', 'login'],
40                 [:object_kind, '=', 'arvados#user'],
41                 [:created_at, '>=', threshold_start],
42                 [:created_at, '<', threshold_end]])
43       @activity[:jobs][span] = Job.
44         filter([[:created_at, '>=', threshold_start],
45                 [:created_at, '<', threshold_end]])
46       @activity[:pipeline_instances][span] = PipelineInstance.
47         filter([[:created_at, '>=', threshold_start],
48                 [:created_at, '<', threshold_end]])
49       @activity.each do |type, act|
50         records = act[span]
51         @users.each do |u|
52           @user_activity[u.uuid] ||= {}
53           @user_activity[u.uuid][span + ' ' + type.to_s] ||= 0
54         end
55         records.each do |record|
56           @user_activity[record.modified_by_user_uuid] ||= {}
57           @user_activity[record.modified_by_user_uuid][span + ' ' + type.to_s] ||= 0
58           @user_activity[record.modified_by_user_uuid][span + ' ' + type.to_s] += 1
59           @total_activity[span + ' ' + type.to_s] ||= 0
60           @total_activity[span + ' ' + type.to_s] += 1
61         end
62       end
63     end
64     @users = @users.sort_by do |a|
65       [-@user_activity[a.uuid].values.inject(:+), a.full_name]
66     end
67     # Prepend a "Total" pseudo-user to the sorted list
68     @user_activity[nil] = @total_activity
69     @users = [OpenStruct.new(uuid: nil)] + @users
70   end
71
72   def storage
73     @breadcrumb_page_name = nil
74     @users = User.limit(params[:limit] || 1000).all
75     @user_storage = {}
76     total_storage = {}
77     @log_date = {}
78     @users.each do |u|
79       @user_storage[u.uuid] ||= {}
80       storage_log = Log.
81         filter([[:object_uuid, '=', u.uuid],
82                 [:event_type, '=', 'user-storage-report']]).
83         order(:created_at => :desc).
84         limit(1)
85       storage_log.each do |log_entry|
86         # We expect this block to only execute once since we specified limit(1)
87         @user_storage[u.uuid] = log_entry['properties']
88         @log_date[u.uuid] = log_entry['event_at']
89       end
90       total_storage.merge!(@user_storage[u.uuid]) { |k,v1,v2| v1 + v2 }
91     end
92     @users = @users.sort_by { |u|
93       [-@user_storage[u.uuid].values.push(0).inject(:+), u.full_name]}
94     # Prepend a "Total" pseudo-user to the sorted list
95     @users = [OpenStruct.new(uuid: nil)] + @users
96     @user_storage[nil] = total_storage
97   end
98
99   def show_pane_list
100     if current_user.andand.is_admin
101       super | %w(Admin)
102     else
103       super
104     end
105   end
106
107   def index_pane_list
108     if current_user.andand.is_admin
109       super | %w(Activity)
110     else
111       super
112     end
113   end
114
115   def sudo
116     resp = arvados_api_client.api(ApiClientAuthorization, '', {
117                                     api_client_authorization: {
118                                       owner_uuid: @object.uuid
119                                     }
120                                   })
121     redirect_to root_url(api_token: resp[:api_token])
122   end
123
124   def home
125     @showallalerts = false
126     @my_ssh_keys = AuthorizedKey.where(authorized_user_uuid: current_user.uuid)
127     @my_tag_links = {}
128
129     @my_jobs = Job.
130       limit(10).
131       order('created_at desc').
132       where(created_by: current_user.uuid)
133
134     @my_collections = Collection.
135       limit(10).
136       order('created_at desc').
137       where(created_by: current_user.uuid)
138     collection_uuids = @my_collections.collect &:uuid
139
140     @persist_state = {}
141     collection_uuids.each do |uuid|
142       @persist_state[uuid] = 'cache'
143     end
144
145     Link.limit(1000).filter([['head_uuid', 'in', collection_uuids],
146                              ['link_class', 'in', ['tag', 'resources']]]).
147       each do |link|
148       case link.link_class
149       when 'tag'
150         (@my_tag_links[link.head_uuid] ||= []) << link
151       when 'resources'
152         if link.name == 'wants'
153           @persist_state[link.head_uuid] = 'persistent'
154         end
155       end
156     end
157
158     @my_pipelines = PipelineInstance.
159       limit(10).
160       order('created_at desc').
161       where(created_by: current_user.uuid)
162
163     respond_to do |f|
164       f.js { render template: 'users/home.js' }
165       f.html { render template: 'users/home' }
166     end
167   end
168
169   def unsetup
170     if current_user.andand.is_admin
171       @object.unsetup
172     end
173     show
174   end
175
176   def setup
177     respond_to do |format|
178       if current_user.andand.is_admin
179         setup_params = {}
180         setup_params[:send_notification_email] = "#{Rails.configuration.send_user_setup_notification_email}"
181         if params['user_uuid'] && params['user_uuid'].size>0
182           setup_params[:uuid] = params['user_uuid']
183         end
184         if params['email'] && params['email'].size>0
185           user = {email: params['email']}
186           setup_params[:user] = user
187         end
188         if params['openid_prefix'] && params['openid_prefix'].size>0
189           setup_params[:openid_prefix] = params['openid_prefix']
190         end
191         if params['repo_name'] && params['repo_name'].size>0
192           setup_params[:repo_name] = params['repo_name']
193         end
194         if params['vm_uuid'] && params['vm_uuid'].size>0
195           setup_params[:vm_uuid] = params['vm_uuid']
196         end
197
198         if User.setup setup_params
199           format.js
200         else
201           self.render_error status: 422
202         end
203       else
204         self.render_error status: 422
205       end
206     end
207   end
208
209   def setup_popup
210     @vms = VirtualMachine.all.results
211
212     @current_selections = find_current_links @object
213
214     respond_to do |format|
215       format.html
216       format.js
217     end
218   end
219
220   def manage_account
221     # repositories current user can read / write
222     repo_links = []
223     Link.filter([['head_uuid', 'is_a', 'arvados#repository'],
224                  ['tail_uuid', '=', current_user.uuid],
225                  ['link_class', '=', 'permission'],
226                  ['name', 'in', ['can_write', 'can_read']],
227                ]).
228           each do |perm_link|
229             repo_links << perm_link[:head_uuid]
230           end
231     @my_repositories = Repository.where(uuid: repo_links)
232
233     # virtual machines the current user can login into
234     @my_vm_logins = {}
235     Link.where(tail_uuid: current_user.uuid,
236                link_class: 'permission',
237                name: 'can_login').
238           each do |perm_link|
239             if perm_link.properties.andand[:username]
240               @my_vm_logins[perm_link.head_uuid] ||= []
241               @my_vm_logins[perm_link.head_uuid] << perm_link.properties[:username]
242             end
243           end
244     @my_virtual_machines = VirtualMachine.where(uuid: @my_vm_logins.keys)
245
246     # current user's ssh keys
247     @my_ssh_keys = AuthorizedKey.where(key_type: 'SSH', owner_uuid: current_user.uuid)
248
249     respond_to do |f|
250       f.html { render template: 'users/manage_account' }
251     end
252   end
253
254   def add_ssh_key_popup
255     respond_to do |format|
256       format.html
257       format.js
258     end
259   end
260
261   def add_ssh_key
262     respond_to do |format|
263       key_params = {'key_type' => 'SSH'}
264       key_params['authorized_user_uuid'] = current_user.uuid
265
266       if params['name'] && params['name'].size>0
267         key_params['name'] = params['name'].strip
268       end
269       if params['public_key'] && params['public_key'].size>0
270         key_params['public_key'] = params['public_key'].strip
271       end
272
273       if !key_params['name'] && params['public_key'].andand.size>0
274         split_key = key_params['public_key'].split
275         key_params['name'] = split_key[-1] if (split_key.size == 3)
276       end
277
278       new_key = AuthorizedKey.create! key_params
279       if new_key
280         format.js
281       else
282         self.render_error status: 422
283       end
284     end
285   end
286
287   protected
288
289   def find_current_links user
290     current_selections = {}
291
292     if !user
293       return current_selections
294     end
295
296     # oid login perm
297     oid_login_perms = Link.where(tail_uuid: user.email,
298                                    head_kind: 'arvados#user',
299                                    link_class: 'permission',
300                                    name: 'can_login')
301
302     if oid_login_perms.any?
303       prefix_properties = oid_login_perms.first.properties
304       current_selections[:identity_url_prefix] = prefix_properties[:identity_url_prefix]
305     end
306
307     # repo perm
308     repo_perms = Link.where(tail_uuid: user.uuid,
309                             head_kind: 'arvados#repository',
310                             link_class: 'permission',
311                             name: 'can_write')
312     if repo_perms.any?
313       repo_uuid = repo_perms.first.head_uuid
314       repos = Repository.where(head_uuid: repo_uuid)
315       if repos.any?
316         repo_name = repos.first.name
317         current_selections[:repo_name] = repo_name
318       end
319     end
320
321     # vm login perm
322     vm_login_perms = Link.where(tail_uuid: user.uuid,
323                               head_kind: 'arvados#virtualMachine',
324                               link_class: 'permission',
325                               name: 'can_login')
326     if vm_login_perms.any?
327       vm_uuid = vm_login_perms.first.head_uuid
328       current_selections[:vm_uuid] = vm_uuid
329     end
330
331     return current_selections
332   end
333
334 end