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: [:update_profile] + 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
+ before_filter :find_object_by_uuid, except: [:create, :index, :choose] + ERROR_ACTIONS
theme :select_theme
begin
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
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
end
end
end
+ # After this, params[:filters] can be trusted to be an array of arrays:
+ params[:filters] = filters
@filters += filters
end
end
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 do
+ extra_attrs = { href: url_for(action: :show, id: @object) }
+ @object.textile_attributes.each do |textile_attr|
+ extra_attrs.merge!({ "#{textile_attr}Textile" => view_context.render_markup(@object.attributes[textile_attr]) })
+ end
+ render json: @object.attributes.merge(extra_attrs)
+ end
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
def choose
params[:limit] ||= 40
- find_objects_for_index if !@objects
respond_to do |f|
if params[:partial]
f.json {
+ find_objects_for_index if !@objects
render json: {
content: render_to_string(partial: "choose_rows.html",
formats: [:html]),
}
end
f.js {
+ find_objects_for_index if !@objects
render partial: 'choose', locals: {multiple: params[:multiple]}
}
end
@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
}
false # We may redirect to login, or not, based on the current action.
else
session[:arvados_api_token] = params[:api_token]
+ # If we later have trouble contacting the API server, we still want
+ # to be able to render basic user information in the UI--see
+ # render_exception above. We store that in the session here. This is
+ # not intended to be used as a general-purpose cache. See #2891.
+ session[:user] = {
+ uuid: user.uuid,
+ email: user.email,
+ first_name: user.first_name,
+ last_name: user.last_name,
+ is_active: user.is_active,
+ 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
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
- profile_config = Rails.configuration.user_profile_form_fields
-
if request.method.downcase != 'get' || params[:partial] ||
params[:tab_pane] || params[:action_method] ||
params[:action] == 'setup_popup'
return true
end
- if current_user && profile_config
- missing_required_profile = false
+ if missing_required_profile?
+ redirect_to profile_user_path(current_user.uuid, return_to: request.fullpath)
+ end
+ true
+ end
- user_prefs = current_user.prefs
- current_user_profile = user_prefs[:profile] if user_prefs
+ 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_profile = true
+ missing_required = true
break
end
end
end
-
- if missing_required_profile
- render 'users/profile'
- end
end
- true
+
+ missing_required
end
def select_theme
}
}
- #@@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)
@my_project_tree =
sorted_paths.call buildtree.call(children_of, 'me')
@shared_project_tree =
- sorted_paths.call({'Shared with me' =>
+ sorted_paths.call({'Projects shared with me' =>
buildtree.call(children_of, false)})
end