diff --git a/lib/blacklight.rb b/lib/blacklight.rb index 3d94e52c61..6a4bb0d159 100644 --- a/lib/blacklight.rb +++ b/lib/blacklight.rb @@ -19,6 +19,7 @@ module Blacklight autoload :Controller, 'blacklight/controller' autoload :Base, 'blacklight/base' autoload :Catalog, 'blacklight/catalog' + autoload :EncryptedUser, 'blacklight/encrypted_user' autoload :Bookmarks, 'blacklight/bookmarks' autoload :DocumentPresenter, 'blacklight/document_presenter' diff --git a/lib/blacklight/bookmarks.rb b/lib/blacklight/bookmarks.rb index 4343fde868..33fe4a4cba 100644 --- a/lib/blacklight/bookmarks.rb +++ b/lib/blacklight/bookmarks.rb @@ -1,6 +1,6 @@ # -*- encoding : utf-8 -*- # note that while this is mostly restful routing, the #update and #destroy actions -# take the Solr document ID as the :id, NOT the id of the actual Bookmark action. +# take the Solr document ID as the :id, NOT the id of the actual Bookmark action. module Blacklight::Bookmarks extend ActiveSupport::Concern @@ -9,15 +9,11 @@ module Blacklight::Bookmarks # Give Bookmarks access to the CatalogController configuration include Blacklight::Configurable include Blacklight::SolrHelper + include Blacklight::EncryptedUser copy_blacklight_config_from(CatalogController) - rescue_from Blacklight::Exceptions::ExpiredSessionToken do - head :unauthorized - end - before_filter :verify_user - helper_method :encrypt_user_id self.document_actions = document_actions.reject { |k,v| k == :sms } end @@ -31,7 +27,7 @@ def action_documents def action_success_redirect_path bookmarks_path end - + # Blacklight uses #search_action_url to figure out the right URL for # the global search box def search_action_url *args @@ -41,7 +37,7 @@ def search_action_url *args def index @bookmarks = token_or_current_or_guest_user.bookmarks bookmark_ids = @bookmarks.collect { |b| b.document_id.to_s } - + @response, @document_list = get_solr_response_for_document_ids(bookmark_ids) respond_to do |format| @@ -62,14 +58,14 @@ def update create end - # For adding a single bookmark, suggest use PUT/#update to + # For adding a single bookmark, suggest use PUT/#update to # /bookmarks/$docuemnt_id instead. # But this method, accessed via POST to /bookmarks, can be used for # creating multiple bookmarks at once, by posting with keys - # such as bookmarks[n][document_id], bookmarks[n][title]. + # such as bookmarks[n][document_id], bookmarks[n][title]. # It can also be used for creating a single bookmark by including keys # bookmark[title] and bookmark[document_id], but in that case #update - # is simpler. + # is simpler. def create if params[:bookmarks] @bookmarks = params[:bookmarks] @@ -80,7 +76,7 @@ def create current_or_guest_user.save! unless current_or_guest_user.persisted? success = @bookmarks.all? do |bookmark| - current_or_guest_user.bookmarks.where(bookmark).exists? || current_or_guest_user.bookmarks.create(bookmark) + current_or_guest_user.bookmarks.where(bookmark).exists? || current_or_guest_user.bookmarks.create(bookmark) end if request.xhr? @@ -95,9 +91,9 @@ def create redirect_to :back end end - + # Beware, :id is the Solr document_id, not the actual Bookmark id. - # idempotent, as DELETE is supposed to be. + # idempotent, as DELETE is supposed to be. def destroy bookmark = current_or_guest_user.bookmarks.where(document_id: params[:id], document_type: blacklight_config.solr_document_model).first @@ -108,23 +104,23 @@ def destroy flash[:notice] = I18n.t('blacklight.bookmarks.remove.success') else flash[:error] = I18n.t('blacklight.bookmarks.remove.failure') - end + end redirect_to :back else # ajaxy request needs no redirect and should not have flash set success ? render(json: { bookmarks: { count: current_or_guest_user.bookmarks.count }}) : render(:text => "", :status => "500") - end + end end - def clear + def clear if current_or_guest_user.bookmarks.clear - flash[:notice] = I18n.t('blacklight.bookmarks.clear.success') + flash[:notice] = I18n.t('blacklight.bookmarks.clear.success') else - flash[:error] = I18n.t('blacklight.bookmarks.clear.failure') + flash[:error] = I18n.t('blacklight.bookmarks.clear.failure') end redirect_to :action => "index" end - + protected def verify_user unless current_or_guest_user or (action == "index" and token_or_current_or_guest_user) @@ -135,47 +131,4 @@ def verify_user def start_new_search_session? action_name == "index" end - - # Used for #export action, with encrypted user_id. - def decrypt_user_id(encrypted_user_id) - user_id, timestamp = message_encryptor.decrypt_and_verify(encrypted_user_id) - - if timestamp < 1.hour.ago - raise Blacklight::Exceptions::ExpiredSessionToken.new - end - - user_id - end - - # Used for #export action with encrypted user_id, available - # as a helper method for views. - def encrypt_user_id(user_id) - message_encryptor.encrypt_and_sign([user_id, Time.now]) - end - - ## - # This method provides Rails 3 compatibility to our message encryptor. - # When we drop support for Rails 3, we can just use the AS::KeyGenerator - # directly instead of this helper. - def bookmarks_export_secret_token salt - OpenSSL::PKCS5.pbkdf2_hmac_sha1(Blacklight.secret_key, salt, 1000, 64) - end - - def message_encryptor - derived_secret = bookmarks_export_secret_token("bookmarks session key") - ActiveSupport::MessageEncryptor.new(derived_secret) - end - - def token_or_current_or_guest_user - token_user || current_or_guest_user - end - - def token_user - @token_user ||= if params[:encrypted_user_id] - user_id = decrypt_user_id params[:encrypted_user_id] - User.find(user_id) - else - nil - end - end end diff --git a/lib/blacklight/encrypted_user.rb b/lib/blacklight/encrypted_user.rb new file mode 100644 index 0000000000..dcd8400c72 --- /dev/null +++ b/lib/blacklight/encrypted_user.rb @@ -0,0 +1,59 @@ +module Blacklight::EncryptedUser + extend ActiveSupport::Concern + + included do + helper_method :encrypt_user_id + + rescue_from Blacklight::Exceptions::ExpiredSessionToken do + head :unauthorized + end + + end + + protected + + def token_or_current_or_guest_user + token_user || current_or_guest_user + end + + def token_user + @token_user ||= if params[:encrypted_user_id] + user_id = decrypt_user_id params[:encrypted_user_id] + User.find(user_id) + else + nil + end + end + + # Used for #export action, with encrypted user_id. + def decrypt_user_id(encrypted_user_id) + user_id, timestamp = message_encryptor.decrypt_and_verify(encrypted_user_id) + + if timestamp < 1.hour.ago + raise Blacklight::Exceptions::ExpiredSessionToken.new + end + + user_id + end + + # Used for #export action with encrypted user_id, available + # as a helper method for views. + def encrypt_user_id(user_id) + message_encryptor.encrypt_and_sign([user_id, Time.now]) + end + + ## + # This method provides Rails 3 compatibility to our message encryptor. + # When we drop support for Rails 3, we can just use the AS::KeyGenerator + # directly instead of this helper. + def bookmarks_export_secret_token salt + OpenSSL::PKCS5.pbkdf2_hmac_sha1(Blacklight.secret_key, salt, 1000, 64) + end + + def message_encryptor + derived_secret = bookmarks_export_secret_token("bookmarks session key") + ActiveSupport::MessageEncryptor.new(derived_secret) + end + + +end