1class SignaturesController < ApplicationController
 
2  include FormTracking
 
3
 
4  before_action :retrieve_petition, only: [:new, :confirm, :create, :thank_you]
 
5  before_action :retrieve_signature, only: [:verify, :unsubscribe, :signed]
 
6  before_action :build_signature, only: [:new, :confirm, :create]
 
7  before_action :expire_form_requests, only: [:new]
 
8  before_action :expire_signed_tokens, only: [:verify]
 
 9  before_action :verify_token, only: [:verify]
 
10  before_action :verify_signed_token, only: [:signed]
 
11  before_action :verify_unsubscribe_token, only: [:unsubscribe]
 
12  before_action :redirect_to_petition_page_if_rejected, only: [:new, :confirm, :create, :thank_you, :verify, :signed]
 
13  before_action :redirect_to_petition_page_if_closed, only: [:new, :confirm, :create, :thank_you]
 
14  before_action :redirect_to_petition_page_if_closed_for_signing, only: [:verify, :signed]
 
15  before_action :do_not_cache
 
 
17  rescue_from ActiveRecord::RecordNotUnique do |exception|
 
18    @signature = @signature.find_duplicate!
 
 
20    delete_form_request
 
21    send_email_to_petition_signer
 
 
23    redirect_to thank_you_url
 
24  end
 
 
26  rescue_from ActiveRecord::RecordInvalid do |exception|
 
27    respond_to do |format|
 
28      format.html { render :new }
 
29    end
 
30  end
 
  • Complexity 2 » saikuro
32  def new
 
33    respond_to do |format|
 
34      format.html
 
35    end
 
36  end
 
  • Complexity 4 » saikuro
38  def confirm
 
39    respond_to do |format|
 
40      format.html { render(@signature.valid? ? :confirm : :new) }
 
41    end
 
42  end
 
  • Complexity 2 » saikuro
44  def create
 
45    if @signature.save!
 
46      delete_form_request
 
47      send_email_to_petition_signer
 
 
49      redirect_to thank_you_url
 
50    end
 
51  end
 
  • Complexity 3 » saikuro
53  def signed
 
54    unless @signature.seen_signed_confirmation_page?
 
55      @signature.mark_seen_signed_confirmation_page!
 
56    end
 
 
58    respond_to do |format|
 
59      format.html
 
60    end
 
61  end
 
  • Complexity 2 » saikuro
63  def verify
 
64    unless @signature.validated?
 
65      @signature.validate!(request: request)
 
66    end
 
 
68    store_signed_token_in_session
 
69    redirect_to signed_signature_url(@signature)
 
70  end
 
  • Complexity 2 » saikuro
72  def unsubscribe
 
73    @signature.unsubscribe!(token_param)
 
 
75    respond_to do |format|
 
76      format.html
 
77    end
 
78  end
 
  • Complexity 2 » saikuro
80  def thank_you
 
81    respond_to do |format|
 
82      format.html
 
83    end
 
84  end
 
 
86  private
 
  • Complexity 1 » saikuro
88  def petition_id
 
89    @petition_id ||= Integer(params[:petition_id])
 
90  end
 
  • Complexity 1 » saikuro
92  def signature_id
 
93    @signature_id ||= Integer(params[:id])
 
94  end
 
  • Complexity 1 » saikuro
96  def token_param
 
97    @token_param ||= params[:token].to_s.encode('utf-8', invalid: :replace)
 
98  end
 
 99
  • Complexity 2 » saikuro
100  def expire_form_requests
 
101    expired_form_requests.each do |id, token|
 
102      cookies.delete(token)
 
103      form_requests.delete(id)
 
104    end
 
105  end
 
  • Complexity 3 » saikuro
107  def expired_form_requests
 
108    form_requests.each_with_object([]) do |(id, hash), expired|
 
109      expired << [id, hash["form_token"]] if form_request_expired?(hash, form_request_max_age)
 
110    end
 
111  end
 
  • UncommunicativeVariableName - has the variable name 'r' » reek
  • Complexity 2 » saikuro
113  def form_request_timestamps
 
114    timestamps = form_requests.map { |_, r| r["form_requested_at"].in_time_zone }
 
115  end
 
  • Complexity 1 » saikuro
117  def last_form_request_timestamp
 
118    form_request_timestamps.sort[-10]
 
119  end
 
  • Complexity 1 » saikuro
121  def form_request_max_age
 
122    [last_form_request_timestamp, 1.day.ago].compact.max
 
123  end
 
  • UtilityFunction - doesn't depend on instance state (maybe move it to another class?) » reek
  • Complexity 1 » saikuro
125  def form_request_expired?(hash, max_age = 1.day.ago)
 
126    hash["form_requested_at"].in_time_zone < max_age
 
127  end
 
  • Complexity 1 » saikuro
129  def delete_form_request
 
130    cookies.delete(form_token)
 
131    form_requests.delete(form_request_id)
 
132  end
 
  • Complexity 1 » saikuro
134  def signed_tokens
 
135    @signed_tokens = session[:signed_tokens] || {}
 
136  end
 
  • Complexity 1 » saikuro
138  def session_signed_token
 
139    signed_tokens.delete(signature_id.to_s)
 
140  end
 
  • Complexity 1 » saikuro
142  def signed_token_hash
 
143    { signature_id.to_s => @signature.signed_token }
 
144  end
 
  • Complexity 2 » saikuro
146  def expire_signed_tokens
 
147    signed_tokens.delete_if { |id, token| Signature.validated?(id) }
 
148  end
 
  • Complexity 1 » saikuro
150  def store_signed_token_in_session
 
151    session[:signed_tokens] = signed_tokens.merge(signed_token_hash)
 
152  end
 
  • Complexity 2 » saikuro
154  def verify_token
 
155    unless @signature.perishable_token == token_param
 
156      raise ActiveRecord::RecordNotFound, "Unable to find Signature with token: #{token_param.inspect}"
 
157    end
 
158  end
 
  • Complexity 2 » saikuro
160  def verify_signed_token
 
161    unless @signature.signed_token == session_signed_token
 
162      redirect_to signed_token_failure_url
 
163    end
 
164  end
 
  • Complexity 2 » saikuro
166  def verify_unsubscribe_token
 
167    unless @signature.unsubscribe_token == token_param
 
168      raise ActiveRecord::RecordNotFound, "Unable to find Signature with unsubscribe token: #{token_param.inspect}"
 
169    end
 
170  end
 
  • Complexity 1 » saikuro
172  def retrieve_petition
 
173    @petition = Petition.visible.find(petition_id)
 
174  end
 
  • Complexity 2 » saikuro
176  def retrieve_signature
 
177    @signature = Signature.find(signature_id)
 
178    @petition = @signature.petition
 
 
180    unless @petition.visible?
 
181      raise ActiveRecord::RecordNotFound, "Unable to find Signature with id: #{signature_id}"
 
182    end
 
183  end
 
  • DuplicateMethodCall - calls '@petition.signatures' 2 times » reek
  • Complexity 2 » saikuro
185  def build_signature
 
186    if action_name == "new"
 
187      @signature = @petition.signatures.build(signature_params_for_new)
 
188    else
 
189      @signature = @petition.signatures.build(signature_params_for_create)
 
190    end
 
191  end
 
  • Complexity 1 » saikuro
193  def thank_you_url
 
194    thank_you_petition_signatures_url(@petition)
 
195  end
 
  • Complexity 1 » saikuro
197  def signed_token_failure_url
 
198    petition_url(@petition)
 
199  end
 
  • Complexity 2 » saikuro
201  def redirect_to_petition_page_if_rejected
 
202    if @petition.rejected?
 
203      redirect_to petition_url(@petition), notice: "Sorry, you can't sign petitions that have been rejected"
 
204    end
 
205  end
 
  • Complexity 2 » saikuro
207  def redirect_to_petition_page_if_closed
 
208    if @petition.closed?
 
209      redirect_to petition_url(@petition), notice: "Sorry, you can't sign petitions that have been closed"
 
210    end
 
211  end
 
  • Complexity 2 » saikuro
213  def redirect_to_petition_page_if_closed_for_signing
 
214    if @petition.closed_for_signing?
 
215      redirect_to petition_url(@petition), notice: "Sorry, you can't sign petitions that have been closed"
 
216    end
 
217  end
 
  • Complexity 3 » saikuro
219  def send_email_to_petition_signer
 
220    unless @signature.email_threshold_reached?
 
221      if @signature.pending?
 
222        EmailConfirmationForSignerEmailJob.perform_later(@signature)
 
223      else
 
224        EmailDuplicateSignaturesEmailJob.perform_later(@signature)
 
225      end
 
226    end
 
227  end
 
  • Complexity 1 » saikuro
229  def signature_params_for_new
 
230    {
 
231      location_code: "GB",
 
232      form_token: form_token,
 
233      form_requested_at: form_requested_at
 
234    }
 
235  end
 
  • Complexity 1 » saikuro
237  def signature_params
 
238    params.require(:signature).permit(*signature_attributes)
 
239  end
 
  • Complexity 1 » saikuro
241  def signature_params_for_create
 
242    signature_params.merge(
 
243      ip_address: request.remote_ip,
 
244      form_token: form_token,
 
245      form_requested_at: form_requested_at,
 
246      image_loaded_at: image_loaded_at
 
247    )
 
248  end
 
  • Complexity 1 » saikuro
250  def signature_attributes
 
251    %i[name email email_confirmation postcode location_code uk_citizenship notify_by_email]
 
252  end
 
253end