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