lib/scrivito/link_parser.rb in scrivito_sdk-1.6.0.rc1 vs lib/scrivito/link_parser.rb in scrivito_sdk-1.6.0.rc2

- old
+ new

@@ -1,55 +1,82 @@ require 'addressable/uri' module Scrivito class LinkParser + EDITING_CONTEXT_PARAMS = [ + '_scrivito_display_mode'.freeze, + '_scrivito_workspace_id'.freeze, + ].freeze + + EDITING_CONTEXT_AND_ENCRYPTED_PARAMS = ( + EDITING_CONTEXT_PARAMS + [ + 'encrypted_params'.freeze + ] + ).freeze + + ENCRYPTED_PARAMS = 'encrypted_params'.freeze + SCRIVITO_BINARY_REDIRECT = 'scrivito/binary_redirect'.freeze + SCRIVITO_CMS_DISPATCH = 'scrivito/cms_dispatch'.freeze + SCRIVITO_UI_PATH = 'scrivito/ui'.freeze + def initialize(host, port) @host = host @port = port end def parse(url) uri = Addressable::URI.parse(url) - if application_uri?(uri) && (params = sdk_route(uri.to_s)) && - params[:controller] == 'scrivito/ui' - uri.path = params[:application_path] - end + return Link.new(url: url) unless application_uri?(uri) - link_params = {} + uri.path = remove_ui_path(uri) - if obj = find_obj(uri) - link_params[:obj] = obj + route_params = recognize_path(uri.to_s) + + if obj = find_obj_via_id_or_permalink(route_params) + Link.new( + obj: obj, + query: remove_params(uri.query_values, EDITING_CONTEXT_PARAMS), + fragment: uri.fragment, + ) + elsif obj = find_obj_via_binary(route_params, uri) + Link.new( + obj: obj, + query: remove_params(uri.query_values, EDITING_CONTEXT_AND_ENCRYPTED_PARAMS), + fragment: uri.fragment, + ) else - if application_uri?(uri) - uri.path = '/' unless uri.path.present? - uri.port = nil - uri.host = nil - uri.scheme = nil - end + uri.path = '/' if uri.path.blank? + uri.port = nil + uri.host = nil + uri.scheme = nil - link_params[:url] = uri.to_s + Link.new(url: uri.to_s) end - - link_params[:query] = remove_editing_context_params(uri.query_values) - link_params[:fragment] = uri.fragment - - Link.new(link_params) rescue Addressable::URI::InvalidURIError Link.new(url: url) end private + def remove_ui_path(uri) + if (params = recognize_precedence_path(uri.to_s)) && params[:controller] == SCRIVITO_UI_PATH + params[:application_path] + else + uri.path + end + end + def application_uri?(uri) absolute_uri?(uri) && internal_uri?(uri) || relative_uri?(uri) && uri.path.present? end def absolute_uri?(uri) - # Ruby's URI parser assumes URLs without a scheme as relativ, while a browser assumes a + # Ruby's URI parser assumes URLs without a scheme as relative, while a browser assumes a # schemeless "//scrivito.com" as absolute. Since the URLs are for the browser, we cannot use # Ruby's URI here. + # See issue https://github.com/sporkmonger/addressable/issues/147 for details. uri.to_s =~ /\A([a-z][a-z\d\-+\.]*:|\/\/).*/i end def relative_uri?(uri) !absolute_uri?(uri) @@ -61,48 +88,48 @@ else uri.host == @host end end - def find_obj(uri) - return nil unless application_uri?(uri) + def find_obj_via_id_or_permalink(route_params) + return unless route_params[:controller] == SCRIVITO_CMS_DISPATCH - route_params = obj_route_params(uri) - if id = route_params[:id] Obj.find(id) elsif permalink = route_params[:permalink] Obj.find_by_permalink(permalink) end rescue Scrivito::ResourceNotFound end - def obj_route_params(uri) - dispatch_route_for(sdk_route(uri)) || dispatch_route_for(route(uri)) || {} + def find_obj_via_binary(route_params, uri) + return unless route_params[:controller] == SCRIVITO_BINARY_REDIRECT + + encrypted_params = uri.query_values[ENCRYPTED_PARAMS] + binary = BinaryParamVerifier.verify_without_expire(encrypted_params) + Obj.find(binary.obj_id) + rescue Scrivito::ResourceNotFound, Scrivito::BinaryParamVerifier::InvalidSignature end - def dispatch_route_for(route_params) - if route_params && route_params[:controller] == 'scrivito/cms_dispatch' - route_params - end + def recognize_path(url) + recognize_precedence_path(url) || recognize_app_path(url) || {} end - def sdk_route(uri) - Scrivito::SdkEngine.routes.recognize_path(uri.to_s, method: :get) + def recognize_precedence_path(url) + Scrivito::SdkEngine.routes.recognize_path(url, method: :get) rescue ActionController::RoutingError end - def route(uri) - Rails.application.routes.recognize_path(uri.to_s, method: :get) + def recognize_app_path(url) + Rails.application.routes.recognize_path(url, method: :get) rescue ActionController::RoutingError end - def remove_editing_context_params(query_values) + def remove_params(query_values, params_to_remove) if query_values - query_values.delete('_scrivito_display_mode') - query_values.delete('_scrivito_workspace_id') - uri = Addressable::URI.new(query_values: query_values) - uri.query + filtered_query_values = query_values.except!(*params_to_remove) + uri = Addressable::URI.new(query_values: filtered_query_values) + uri.query.presence end end end end