3114: Merge branch 'master' into 3114-copy-to-project
authorTom Clegg <tom@curoverse.com>
Mon, 18 Aug 2014 22:02:47 +0000 (18:02 -0400)
committerTom Clegg <tom@curoverse.com>
Mon, 18 Aug 2014 22:02:47 +0000 (18:02 -0400)
1  2 
apps/workbench/app/controllers/application_controller.rb
apps/workbench/app/controllers/users_controller.rb
apps/workbench/app/views/collections/show.html.erb

index 160730331dd28ec9495e933787e9e8d2c3dbb697,b62636166c1081c6528f0a0e29cdb7ff2b824ef2..98bc53ae4612d5efd25ef7a6dc96287bb2857bf9
@@@ -14,6 -14,7 +14,7 @@@ class ApplicationController < ActionCon
    around_filter :require_thread_api_token, except: ERROR_ACTIONS
    before_filter :accept_uuid_as_id_param, except: ERROR_ACTIONS
    before_filter :check_user_agreements, except: ERROR_ACTIONS
+   before_filter :check_user_profile, except: ERROR_ACTIONS
    before_filter :check_user_notifications, except: ERROR_ACTIONS
    before_filter :load_filters_and_paging_params, except: ERROR_ACTIONS
    before_filter :find_object_by_uuid, except: [:index, :choose] + ERROR_ACTIONS
      else
        @errors = [e.to_s]
      end
-     # If the user has an active session, and the API server is available,
-     # make user information available on the error page.
+     # Make user information available on the error page, falling back to the
+     # session cache if the API server is unavailable.
      begin
        load_api_token(session[:arvados_api_token])
      rescue ArvadosApiClient::ApiError
-       load_api_token(nil)
+       unless session[:user].nil?
+         begin
+           Thread.current[:user] = User.new(session[:user])
+         rescue ArvadosApiClient::ApiError
+           # This can happen if User's columns are unavailable.  Nothing to do.
+         end
+       end
      end
-     # Preload projects trees for the template.  If that fails, set empty
+     # Preload projects trees for the template.  If that's not doable, set empty
      # trees so error page rendering can proceed.  (It's easier to rescue the
      # exception here than in a template.)
-     begin
-       build_project_trees
-     rescue ArvadosApiClient::ApiError
-       @my_project_tree ||= []
-       @shared_project_tree ||= []
+     unless current_user.nil?
+       begin
+         build_project_trees
+       rescue ArvadosApiClient::ApiError
+         # Fall back to the default-setting code later.
+       end
      end
+     @my_project_tree ||= []
+     @shared_project_tree ||= []
      render_error(err_opts)
    end
  
@@@ -89,6 -99,9 +99,9 @@@
    end
  
    def load_filters_and_paging_params
+     @order = params[:order] || 'created_at desc'
+     @order = [@order] unless @order.is_a? Array
      @limit ||= 200
      if params[:limit]
        @limit = params[:limit].to_i
      respond_to do |f|
        f.json { render json: @objects }
        f.html {
-         if params['tab_pane']
-           comparable = self.respond_to? :compare
-           render(partial: 'show_' + params['tab_pane'].downcase,
-                  locals: { comparable: comparable, objects: @objects })
+         if params[:tab_pane]
+           render_pane params[:tab_pane]
          else
            render
          end
      end
    end
  
+   helper_method :render_pane
+   def render_pane tab_pane, opts={}
+     render_opts = {
+       partial: 'show_' + tab_pane.downcase,
+       locals: {
+         comparable: self.respond_to?(:compare),
+         objects: @objects,
+         tab_pane: tab_pane
+       }.merge(opts[:locals] || {})
+     }
+     if opts[:to_string]
+       render_to_string render_opts
+     else
+       render render_opts
+     end
+   end
    def index
      find_objects_for_index if !@objects
      render_index
        return render_not_found("object not found")
      end
      respond_to do |f|
 -      f.json { render json: @object.attributes.merge(href: url_for(@object)) }
 +      f.json { render json: @object.attributes.merge(href: url_for(action: :show, id: @object)) }
        f.html {
          if params['tab_pane']
-           comparable = self.respond_to? :compare
-           render(partial: 'show_' + params['tab_pane'].downcase,
-                  locals: { comparable: comparable, objects: @objects })
+           render_pane params['tab_pane']
          elsif request.method.in? ['GET', 'HEAD']
            render
          else
      @object ||= model_class.new @new_resource_attrs, params["options"]
      if @object.save
        respond_to do |f|
 -        f.json { render json: @object.attributes.merge(href: url_for(@object)) }
 +        f.json { render json: @object.attributes.merge(href: url_for(action: :show, id: @object)) }
          f.html {
            redirect_to @object
          }
      Thread.current[:arvados_api_token] = new_token
      if new_token.nil?
        Thread.current[:user] = nil
-     elsif (new_token == session[:arvados_api_token]) and
-         session[:user].andand[:is_active]
-       Thread.current[:user] = User.new(session[:user])
      else
        Thread.current[:user] = User.current
      end
          is_admin: user.is_admin,
          prefs: user.prefs
        }
        if !request.format.json? and request.method.in? ['GET', 'HEAD']
          # Repeat this request with api_token in the (new) session
          # cookie instead of the query string.  This prevents API
      end
    end
  
-   # Reroute this request if an API token is unavailable.
+   # Redirect to login/welcome if client provided expired API token (or none at all)
    def require_thread_api_token
      if Thread.current[:arvados_api_token]
        yield
        session.delete :arvados_api_token
        redirect_to_login
      else
-       render 'users/welcome'
+       redirect_to welcome_users_path(return_to: request.fullpath)
      end
    end
  
      end
    end
  
+   helper_method :unsigned_user_agreements
+   def unsigned_user_agreements
+     @signed_ua_uuids ||= UserAgreement.signatures.map &:head_uuid
+     @unsigned_user_agreements ||= UserAgreement.all.map do |ua|
+       if not @signed_ua_uuids.index ua.uuid
+         Collection.find(ua.uuid)
+       end
+     end.compact
+   end
    def check_user_agreements
      if current_user && !current_user.is_active
        if not current_user.is_invited
-         return render 'users/inactive'
+         return redirect_to inactive_users_path(return_to: request.fullpath)
        end
-       signatures = UserAgreement.signatures
-       @signed_ua_uuids = UserAgreement.signatures.map &:head_uuid
-       @required_user_agreements = UserAgreement.all.map do |ua|
-         if not @signed_ua_uuids.index ua.uuid
-           Collection.find(ua.uuid)
-         end
-       end.compact
-       if @required_user_agreements.empty?
+       if unsigned_user_agreements.empty?
          # No agreements to sign. Perhaps we just need to ask?
          current_user.activate
          if !current_user.is_active
          end
        end
        if !current_user.is_active
-         render 'user_agreements/index'
+         redirect_to user_agreements_path(return_to: request.fullpath)
        end
      end
      true
    end
  
+   def check_user_profile
+     if request.method.downcase != 'get' || params[:partial] ||
+        params[:tab_pane] || params[:action_method] ||
+        params[:action] == 'setup_popup'
+       return true
+     end
+     if missing_required_profile?
+       redirect_to profile_user_path(current_user.uuid, return_to: request.fullpath)
+     end
+     true
+   end
+   helper_method :missing_required_profile?
+   def missing_required_profile?
+     missing_required = false
+     profile_config = Rails.configuration.user_profile_form_fields
+     if current_user && profile_config
+       current_user_profile = current_user.prefs[:profile]
+       profile_config.kind_of?(Array) && profile_config.andand.each do |entry|
+         if entry['required']
+           if !current_user_profile ||
+              !current_user_profile[entry['key'].to_sym] ||
+              current_user_profile[entry['key'].to_sym].empty?
+             missing_required = true
+             break
+           end
+         end
+       end
+     end
+     missing_required
+   end
    def select_theme
      return Rails.configuration.arvados_theme
    end
      }
    }
  
-   #@@notification_tests.push lambda { |controller, current_user|
-   #  Job.limit(1).where(created_by: current_user.uuid).each do
-   #    return nil
-   #  end
-   #  return lambda { |view|
-   #    view.render partial: 'notifications/jobs_notification'
-   #  }
-   #}
    @@notification_tests.push lambda { |controller, current_user|
      Collection.limit(1).where(created_by: current_user.uuid).each do
        return nil
      @notification_count = 0
      @notifications = []
  
-     if current_user
+     if current_user.andand.is_active
        @showallalerts = false
        @@notification_tests.each do |t|
          a = t.call(self, current_user)
index d817b32711fe5d7695a642343a442cd4c394c73e,eb07fc3757c3eef7568098f5460060246e2ca4d3..189f295f8fe097c2a2a17e8a5f41342ed254eef0
@@@ -1,22 -1,26 +1,34 @@@
  class UsersController < ApplicationController
-   skip_before_filter :find_object_by_uuid, :only => [:welcome, :activity, :storage]
+   skip_around_filter :require_thread_api_token, only: :welcome
+   skip_before_filter :check_user_agreements, only: [:welcome, :inactive]
+   skip_before_filter :check_user_profile, only: [:welcome, :inactive, :profile]
+   skip_before_filter :find_object_by_uuid, only: [:welcome, :activity, :storage]
    before_filter :ensure_current_user_is_admin, only: [:sudo, :unsetup, :setup]
  
 +  def show
 +    if params[:uuid] == current_user.uuid
 +      redirect_to project_path(params[:uuid])
 +    else
 +      super
 +    end
 +  end
 +
    def welcome
      if current_user
-       params[:action] = 'home'
-       home
+       redirect_to (params[:return_to] || '/')
      end
    end
  
+   def inactive
+     if current_user.andand.is_invited
+       redirect_to (params[:return_to] || '/')
+     end
+   end
+   def profile
+     params[:offer_return_to] ||= params[:return_to]
+   end
    def activity
      @breadcrumb_page_name = nil
      @users = User.limit(params[:limit] || 1000).all
index 4585a43664b0dd2fa4acbbd2067b070e215cee6c,83dcb4511bfbc36aaae6910492c48e777bcd9cf0..0d52b088c47a91f59bc1f46092d4a73e3fc51a34
@@@ -1,22 -1,3 +1,22 @@@
 +<% content_for :tab_line_buttons do %>
 +  <%= link_to(
 +      choose_projects_path(
 +       title: 'Copy to project...',
 +       my_root_selectable: true,
 +       action_name: 'Copy',
 +       action_href: actions_path,
 +       action_method: 'post',
 +       action_data: {
 +         copy_selections_into_project: true,
 +         selection: @name_link.andand.uuid || @object.uuid,
 +         selection_param: 'uuid',
 +         success: 'redirect-to-created-object'
 +       }.to_json),
 +      { class: "btn btn-sm btn-primary arv-move-to-project", remote: true, method: 'get' }) do %>
 +    <i class="fa fa-fw fa-copy"></i> Copy to project...
 +  <% end %>
 +<% end %>
 +
  <div class="row row-fill-height">
    <div class="col-md-6">
      <div class="panel panel-info">
    </div>
  </div>
  
- <%= render file: 'application/show.html.erb' %>
+ <% content_for :tab_line_buttons do %>
+   <span style="padding-left: 1em">Collection storage status:</span>
+   <%= render partial: 'toggle_persist', locals: { uuid: @object.uuid, current_state: (@is_persistent ? 'persistent' : 'cache') } %>
+ <% end %>
+ <%= render file: 'application/show.html.erb', locals: local_assigns %>