@@ -37,12 +37,16 @@ def index #:nodoc:
3737 @mode = :cpu if params [ :mode ] . to_s == 'cpu'
3838 @mode = :disk if params [ :mode ] . to_s == 'disk' || @mode != :cpu
3939 cbrain_session [ :quota_mode ] = @mode . to_s
40-
4140 @scope = scope_from_session ( "#{ @mode } _quotas#index" )
4241
42+ # Make sure the target user is set if viewing quotas for another user.
43+ @as_user = see_as_user params [ 'as_user_id' ]
44+ @scope . custom [ 'as_user_id' ] = @as_user . id
45+
4346 @base_scope = base_scope . includes ( [ :user , :data_provider ] ) if @mode == :disk
4447 @base_scope = base_scope . includes ( [ :user , :remote_resource ] ) if @mode == :cpu
45- @view_scope = @scope . apply ( @base_scope )
48+
49+ @view_scope = @scope . apply ( @base_scope )
4650
4751 @scope . pagination ||= Scope ::Pagination . from_hash ( { :per_page => 15 } )
4852 @quotas = @scope . pagination . apply ( @view_scope , api_request? )
@@ -343,6 +347,73 @@ def report_disk_quotas #:nodoc:
343347
344348 end
345349
350+ def report_almost
351+ @mode = params [ :mode ] . to_s == 'cpu' ? :cpu : :disk
352+ cb_exception ( "not supported" ) if @mode == :cpu
353+ report_disk_almost if @mode == :disk
354+ end
355+
356+ def report_disk_almost
357+ almost = 0.95 # share of resource use qualifying for 'almost exceeding'
358+ quota_to_user_ids = { } # quota_obj => [uid, uid...]
359+
360+ # Scan DP-wide quota objects
361+ DiskQuota . where ( :user_id => 0 ) . all . each do |quota |
362+ exceed_size_user_ids = Userfile
363+ . where ( :data_provider_id => quota . data_provider_id )
364+ . group ( :user_id )
365+ . sum ( :size )
366+ . select { |user_id , size | size >= quota . max_bytes * almost }
367+ . keys
368+ exceed_numfiles_user_ids = Userfile
369+ . where ( :data_provider_id => quota . data_provider_id )
370+ . group ( :user_id )
371+ . sum ( :num_files )
372+ . select { |user_id , num_files | num_files >= quota . max_files * almost }
373+ . keys
374+
375+ union_ids = exceed_size_user_ids | exceed_numfiles_user_ids
376+ union_ids -= DiskQuota
377+ . where ( :data_provider_id => quota . data_provider_id , :user_id => union_ids )
378+ . pluck ( :user_id ) # remove user IDs that have their own quota records
379+ quota_to_user_ids [ quota ] = union_ids if union_ids . size > 0
380+ end
381+
382+ # Scan user-specific quota objects
383+ DiskQuota . where ( 'user_id > 0' ) . all . each do |quota |
384+ quota_to_user_ids [ quota ] = [ quota . user_id ] if quota . almost_exceeded?
385+ end
386+
387+ # Inverse relation: user_id => [ quota, quota ]
388+ user_id_to_quotas = { }
389+ quota_to_user_ids . each do |quota , user_ids |
390+ user_ids . each do |user_id |
391+ user_id_to_quotas [ user_id ] ||= [ ]
392+ user_id_to_quotas [ user_id ] << quota
393+ end
394+ end
395+
396+ # Table content: [ [ user_id, quota ], [user_id, quota] ... ]
397+ # Note: the rows are grouped by user_id, but not sorted in any way...
398+ @user_id_and_quota = [ ]
399+ user_id_to_quotas . each do |user_id , quotas |
400+ quotas . each do |quota |
401+ @user_id_and_quota << [ user_id , quota ]
402+ end
403+ end
404+
405+ end
406+
407+ # a clone of browse_as
408+ def see_as_user ( as_user_id ) #:nodoc:
409+ scope = scope_from_session ( "#{ @mode } _quotas#index" )
410+ users = current_user . available_users
411+ as_user = users . where ( :id => as_user_id ) . first
412+ as_user ||= users . where ( :id => scope . custom [ 'as_user_id' ] ) . first
413+ as_user ||= current_user
414+ as_user
415+ end
416+
346417 private
347418
348419 def disk_quota_params #:nodoc:
@@ -366,12 +437,12 @@ def base_scope #:nodoc:
366437 scope = DiskQuota . where ( nil ) if @mode == :disk
367438 scope = CpuQuota . where ( nil ) if @mode == :cpu
368439
369- return scope if current_user . has_role? ( :admin_user )
440+ return scope if current_user . has_role? ( :admin_user ) && @as_user . id == current_user . id
370441
371442 if @mode == :disk
372- dp_ids = DataProvider . all . select { |dp | dp . can_be_accessed_by? ( current_user ) } . map ( &:id )
443+ dp_ids = DataProvider . all . select { |dp | dp . can_be_accessed_by? ( @as_user ) } . map ( &:id )
373444 scope = scope . where (
374- :user_id => [ 0 , current_user . id ] ,
445+ :user_id => [ 0 , @as_user . id ] ,
375446 :data_provider_id => dp_ids ,
376447 )
377448 end
0 commit comments