Rails:如何从公共

时间:2017-11-28 10:01:26

标签: ruby-on-rails session e-commerce wicked-pdf

我是Rails的新手,正在建立一个电子商务应用程序。我会感激任何帮助。我的电子商务应用程序允许访客(使用购物车的会话 - 购物车会话在创建订单后重置)和登录用户签出(使用设计)。创建订单后,生成订单的人员将被定向到订单显示页面,在那里他们可以查看订单的详细信息并下载pdf(通过wicked_pdf)订单的详细信息。但是,问题是我的订单显示页面网址引用了订单ID,即localhost:3000 / orders / [:id],因此任何没有订单的人都可以轻松输入网址来检索订单详细信息。如果它只是登录可以结帐的用户,那么我可以将页面仅限制为current_user,但问题是当它是访客结账时。

我的解决方案是通过在订单控制器中的show动作中声明仅当订单存在时隐藏其他用户的订单显示页面,然后显示展示页面,否则重定向到根页面。这适用于显示页面的第一次渲染(在创建订单后立即),但是如果我单击显示页面上的pdf,它将不再检测order.id,而是重定向到根页面。因此,虽然解决方案部分用于确保转到/ orders / [:id]的任何人被重定向到root_path,但它也可以将我的pdf请求定向到root_path。

我的订单控制器代码是:

class OrdersController < ApplicationController

include CurrentCart
before_action :set_cart, only: [:new, :create, :show]
before_action :set_order, only: [:show, :edit, :destroy]


def new
    if user_signed_in?
        @order = current_user.orders.new
    else
        @order = Order.new
    end
        @client_token = Braintree::ClientToken.generate
end

def create
    if user_signed_in?
        @order = current_user.orders.new(order_params)
    else
        @order = Order.new(order_params)        
    end
    if @order.save  
        @order.regenerate_auth_token
        charge
        if @result.success? 
        @order[:total_price] = @cart.total_price
        @order.save
        ##Add_carted_activities_from_cart is in cart model - this is what makes the cart go to nil 

            @order.add_carted_activities_from_cart(@cart)   
            Cart.destroy(session[:cart_id])
            session[:cart_id] = nil
            render :show, notice: 'Thank You for Your Order!'
        else
          flash[:error] = 'Check Your Cart'
          redirect_to new_order_path, alert: @result.message
          @order.destroy
        end
    else
      @client_token = Braintree::ClientToken.generate
      render :new 
    end
end

def show
    if params.has_key?(:order) 
        respond_to do |format|
          format.html
          format.pdf do
            render pdf: "order",
            template: "orders/show.pdf.erb"
          end 
        end 
    else 
        redirect_to root_path       
    end 
end

def destroy
    @order.destroy
    redirect_to root_url, notice: 'Your Order has been deleted'
end

private

def set_order
    @order = Order.find(params[:id])
end


def order_params
    params.require(:order).permit(:order_status, :activity_quantity, :activity_price, 
            :fees, :taxes, :billing_address, :customer_name, 
            :total_price)
end

def charge
    @result = Braintree::Transaction.sale(
      amount: @cart.total_price,
      payment_method_nonce: params[:payment_method_nonce])
end

我试过的另一个解决方案(因为我没有把代码放在这里不起作用)是使用会话。我在set_order中设置了session [:order_id] = @ order.id,并定义了after_action:destroy_session:show。 Destroy_session被定义为session [:order_id] = nil。这没有任何效果,任何人仍然可以通过在URL中输入id来查看订单详细信息。

我的订单显示页面代码

<div class = "container">
    <div class = "cart">
        <div class = "row">
            <h3>Confirm & Pay</h3>
                <div class="col-md-12">
                      <ul class="progressbar">
                            <li>Your Order</li>
                            <li>Confirm & Pay</li>
                            <li class="active">Thank You</li>
                      </ul>
                </div>
        </div>
    </div>

    <br>

    <div class = "col-md-12">
    <hr>
        <center>
            <div class = "panel panel-default" id = "thankyou">
                <div class = "panel panel-body">
                <i class="fa fa-check-circle-o fa-2x fa-pull-left" aria-hidden="true" style="-webkit-text-stroke: 2px white;"></i>
                    <div class = "thankyou_text">
                        <h5>Thank you, we've received your booking.</h5>
                        <p> 
                            <h6> We will send a confirmation of your booking to <%= @order.customer_email%></h6>
                        </p>
                    </div>
                </div>
            </div>
            <%= link_to_blank order_path(@order.id, :format => 'pdf') do %> 
            <i class="fa fa-file-pdf-o fa-2x" aria-hidden="true" style="color: #00a8ba;">View Details</i>
            <% end %>
        </center>

        <div class = "summary"> 
        <hr>
            <h5 style = "text-transform: uppercase;">
                Order Number: <%= @order.auth_token.slice(0..4) + @order.id.to_s %> 
            </h5>

            <h5> Summary of your order
            </h5>

            <h6><% @order.carted_activities.each do |carted_activity| %> 

                <p> <%=carted_activity.supplier_activity_option.supplier_activity.activity.name %>
                    x 
                    <%= carted_activity.activity_quantity %>
                    <span class = "right_side"> <%= number_to_currency carted_activity.total_price %> </span>
                </p>
                <% end %> 

                <p>Our Service Fee
                    <span class = "right_side"> Free </span>
                </p>

                <p>Taxes
                    <span class = "right_side">##</span>
                </p>

                <span class = "order_total">
                    <p>Order Total
                        <span class = "right_side"><%=number_to_currency @order.total_price %></span>
                    </p>
                </span>
            </h6>
        </div>
    </div>

路线文件

Rails.application.routes.draw do

  get 'place_images/index'

  get 'activity_images/index'

   root to: 'pages#index'

  devise_for :admin_users, ActiveAdmin::Devise.config
  ActiveAdmin.routes(self)

  devise_for :users, controllers: {registrations: 'users/registrations', omniauth_callbacks: "users/omniauth_callbacks"} 
  resources :users

  get 'activities/types' => 'activities#tagged'
  get '/about' => 'pages#about'
  get '/search' => 'searches#search'
  put 'carted_activities/qty' => 'carted_activities#updateQuantity'
  get 'carts/show' => 'carts#show'


  resources :countries 

  resources :regions 

  resources :carted_activities

  resources :carts

  resources :orders

  resources :supplier_activities do
    resources :reviews 
  end

  resources :suppliers

  resources  :activity_images, only:  [:index]
  resources  :place_images, only:  [:index]

  resources :activities, only: [:create, :index, :destroy, :show] do
    resources :wishlists
  end 


end

我还应该做些什么来确保pdf请求检测到当前订单而不是重定向到root_path?理想情况下,我需要将订单显示网址阻止给生成订单的人以外的所有人,但生成订单的人可以查看和发送pdf给任何人。任何有关如何实现这一目标的反馈和指导都将非常感激。

2 个答案:

答案 0 :(得分:0)

当用户加载订单显示页面时,检查订单是否由当前用户放置。

class OrdersController < ApplicationController

before_action :check_current_user, only: [:show]

def check_current_user
 redirect_to root_url unless @order.user == current_user
end

答案 1 :(得分:0)

感谢大家的帮助。我现在用我的订单控制器中的创建和显示操作中的会话哈希解决了这个问题,如下所示:

def create
        if user_signed_in?
            @order = current_user.orders.new(order_params)
        else
            @order = Order.new(order_params)        
        end
        if @order.save  
            @order.regenerate_auth_token
            charge
            if @result.success? 
            @order[:total_price] = @cart.total_price
            @order.save
            session[:order] = true
            ##Add_carted_activities_from_cart is in cart model - this is what makes the cart go to nil 
                @order.add_carted_activities_from_cart(@cart)   
                Cart.destroy(session[:cart_id])
                session[:cart_id] = nil
                render :show, notice: 'Thank You for Your Order!'
            else
              flash[:error] = 'Check Your Cart'
              redirect_to new_order_path, alert: @result.message
              @order.destroy
            end
        else
          @client_token = Braintree::ClientToken.generate
          render :new 
        end
    end

    def show
        if !session[:order].blank?
            respond_to do |format|
              format.html
              format.pdf do
                render pdf: "seeksophie_order",
                template: "orders/show.pdf.erb"
              end 
            end 
            session.delete(:order)
        else 
            redirect_to root_path       
        end 
    end