From 901178e6e7c0cfd5ed7b0626c6b0aea836665053 Mon Sep 17 00:00:00 2001 From: OrngSreyMoch Date: Wed, 4 Dec 2024 15:10:57 +0700 Subject: [PATCH] Close #2047 implement JWT on email confirmation --- .../storefront/anonymous_order_controller.rb | 47 +++++++++++++++++++ app/helpers/spree/base_helper_decorator.rb | 17 +++++++ app/mailers/spree/order_mailer_decorator.rb | 2 + .../purchased_items/_items.html.erb | 1 + config/routes.rb | 1 + 5 files changed, 68 insertions(+) create mode 100644 app/controllers/spree/api/v2/storefront/anonymous_order_controller.rb diff --git a/app/controllers/spree/api/v2/storefront/anonymous_order_controller.rb b/app/controllers/spree/api/v2/storefront/anonymous_order_controller.rb new file mode 100644 index 000000000..68dc18c79 --- /dev/null +++ b/app/controllers/spree/api/v2/storefront/anonymous_order_controller.rb @@ -0,0 +1,47 @@ +module Spree + module Api + module V2 + module Storefront + class AnonymousOrderController < Spree::Api::V2::BaseController + def show_anonymous_order + token = params[:token] + order = order_jwt_token(token) + + if order + render_serialized_payload { serialize_resource(order) } + else + render json: { error: 'Invalid or expired token' }, status: :unauthorized + end + end + + def resource_serializer + Spree::V2::Storefront::OrderSerializer + end + + private + + def order_jwt_token(token) + decoded_token = decode_jwt(token) + + order_number = decoded_token['order_number'] + return nil unless order_number + + order = Spree::Order.find_by(number: order_number) + return nil unless order + + decoded_token = decode_jwt(token, order&.token) + return nil unless decoded_token + + order + end + + def decode_jwt(token, secret = nil) + JWT.decode(token, secret, secret.present?, { algorithm: 'HS256' }).first + rescue JWT::DecodeError + nil + end + end + end + end + end +end diff --git a/app/helpers/spree/base_helper_decorator.rb b/app/helpers/spree/base_helper_decorator.rb index aeef13cca..289252d36 100644 --- a/app/helpers/spree/base_helper_decorator.rb +++ b/app/helpers/spree/base_helper_decorator.rb @@ -19,6 +19,23 @@ def custom_product_storefront_resource_url(resource, options = {}) spree_storefront_resource_url(resource) end end + + def custom_product_line_item_url(line_item, jwt_token, options = {}) + if defined?(locale_param) && locale_param.present? + options.merge!(locale: locale_param) + end + + localize = if options[:locale].present? + "/#{options[:locale]}" + else + '' + end + + order = Spree::Order.find(line_item.order_id) + return if order.number.blank? && jwt_token.blank? + + "#{current_store.formatted_url + localize}/anonymous_orders/#{jwt_token}" + end end end diff --git a/app/mailers/spree/order_mailer_decorator.rb b/app/mailers/spree/order_mailer_decorator.rb index 71ee7e177..f344e5329 100644 --- a/app/mailers/spree/order_mailer_decorator.rb +++ b/app/mailers/spree/order_mailer_decorator.rb @@ -18,6 +18,8 @@ def confirm_email(order, resend: false) subject = (resend ? "[#{Spree.t(:resend).upcase}] " : '') subject += "#{@current_store&.name} Booking Confirmation ##{@order.number}" + payload = { order_number: @order.number, user_id: @order.user.id, store_id: @current_store.id } + @jwt_token = JWT.encode(payload, @order.token, 'HS256') mail(to: @order.email, from: from_address, subject: subject, store_url: @current_store.url) do |format| format.html { render layout: 'spree_cm_commissioner/layouts/order_mailer' } diff --git a/app/views/spree_cm_commissioner/order_mailer/purchased_items/_items.html.erb b/app/views/spree_cm_commissioner/order_mailer/purchased_items/_items.html.erb index 284910549..accba60ec 100644 --- a/app/views/spree_cm_commissioner/order_mailer/purchased_items/_items.html.erb +++ b/app/views/spree_cm_commissioner/order_mailer/purchased_items/_items.html.erb @@ -23,6 +23,7 @@ <%= sanitize(line_item.variant.options_text) %> <% end %> +
<%= link_to 'View Details', custom_product_line_item_url(line_item, @jwt_token) %>
diff --git a/config/routes.rb b/config/routes.rb index ecd380a49..1c05fb28b 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -470,6 +470,7 @@ resources :self_check_in, only: %i[index create] resources :guest_orders, only: %i[index show] post :user_order_transfer, to: 'user_order_transfer#create' + get 'anonymous_order/show_anonymous_order', to: 'anonymous_order#show_anonymous_order' end namespace :operator do