Workshop auth fixes and better error reporting

This commit is contained in:
Godwin
2017-07-19 20:29:25 -07:00
parent c21cc05c99
commit e8ca73a801
20 changed files with 371 additions and 332 deletions
+95 -129
View File
@@ -1,35 +1,53 @@
class ApplicationController < BaseController
protect_from_forgery with: :exception, :except => [:do_confirm, :js_error, :admin_update]
before_filter :capture_page_info
before_filter :application_setup
after_filter :capture_page_info
helper_method :protect, :policies
# @@test_host
# @@test_location
def default_url_options
{ host: "#{request.protocol}#{request.host_with_port}", trailing_slash: true }
end
def capture_page_info
# capture request info in case an error occurs
# if request.method == "GET" && (params[:controller] != 'application' || params[:action] != 'contact')
# session[:last_request]
# request_info = {
# 'params' => params,
# 'request' => {
# 'remote_ip' => request.remote_ip,
# 'uuid' => request.uuid,
# 'original_url' => request.original_url,
# 'env' => Hash.new
# }
# }
# request.env.each do |key, value|
# request_info['request']['env'][key.to_s] = value.to_s
# end
# # session['request_info'] = request_info
# end
capture_response unless @user_type == :potential_bot || @user_type == :bot
end
def capture_response(response_code = nil)
Request.create(
request_id: request.uuid,
session_id: session.id,
application: :bikebike,
response: (response_code || response.code || 0).to_i,
data: {
user: logged_in? ? current_user.id : nil,
params: @original_params || params,
remote_ip: request.remote_ip,
request_method: request.method,
url: request.original_url,
user_agent: request.user_agent,
language: request.env['HTTP_ACCEPT_LANGUAGE'],
cookies: request.env['HTTP_COOKIE'],
requested_with: request.env['HTTP_X_REQUESTED_WITH']
})
@error_reports.each { |report| report_on(report) } if @error_reports
end
def report_on(report)
return if Rails.env.development? || Rails.env.test?
send_mail(:error_report, report.signature)
end
def application_setup
if request.user_agent =~ /Googlebot/
@user_type = :bot
elsif request.url =~ /^.*\.php(\?.*)?$/
@user_type = :potential_bot
else
@user_type = :normal
end
# get the current conferences and set them globally
status_hierarchy = {
@@ -82,51 +100,6 @@ class ApplicationController < BaseController
@is_policy_page = true
end
def js_error
# send and email if this is production
report = "A JavaScript error has occurred on <code>#{params[:location]}</code>"
if params[:location] == params[:url]
report += " on line <code>#{params[:lineNumber]}</code>"
else
report += " in <code>#{params[:url]}:#{params[:lineNumber]}</code>"
end
begin
# log the error
logger.info "A JavaScript error has occurred on #{params[:location]}:#{params[:lineNumber]}: #{params[:message]}"
if Rails.env.preview? || Rails.env.production?
# don't worry about bots
unless request.user_agent =~ /Googlebot/
request_info = {
'remote_ip' => request.remote_ip,
'uuid' => request.uuid,
'original_url' => request.original_url,
'env' => Hash.new
}
request.env.each do |key, value|
request_info['env'][key.to_s] = value.to_s
end
send_mail(:error_report,
"A JavaScript error has occurred",
report,
params[:message],
nil,
request_info,
params,
current_user,
Time.now.strftime("%d/%m/%Y %H:%M")
)
end
end
rescue Exception => exception2
logger.info exception2.to_s
logger.info exception2.backtrace.join("\n")
end
render json: {}
end
def confirmation_sent(user)
template = 'login_confirmation_sent'
@page_title ||= 'page_titles.403.Please_Check_Email'
@@ -150,6 +123,7 @@ class ApplicationController < BaseController
def locale_not_available!(locale = nil)
set_default_locale
@original_params = params.clone
params[:_original_action] = params[:action]
params[:action] = 'error-locale-not-available'
@page_title = 'page_titles.404.Locale_Not_Available'
@@ -167,6 +141,28 @@ class ApplicationController < BaseController
render 'application/locale_not_available', status: 404
end
def on_error(report, exception = nil)
@error_reports ||= []
@error_reports << report
logger.info report.backtrace
raise exception if exception.present? && Rails.env.development?
end
def js_error
stack = params[:stack] || "#{params[:message]}\n\tat #{params[:url] || params[:location]}:#{params[:line]}:#{params[:col]}"
requests = Request.where(session_id: session.id).order("created_at DESC")
on_error(
Report.create(
request_id: requests.first.request_id,
signature: params[:message],
severity: :error,
source: :javascript,
backtrace: stack))
render json: {}
end
unless Rails.env.test?
rescue_from StandardError do |exception|
handle_exception exception
@@ -177,37 +173,31 @@ class ApplicationController < BaseController
end
def handle_exception(exception)
# log the error
logger.info exception.to_s
logger.info exception.backtrace.join("\n")
# remove memory location from anonymous classes so tat we have a common signature
classMatcher = /#<(.*?):0x[0-9a-f]+>/
message = exception.message
message.gsub!(classMatcher, '\1') while message =~ classMatcher
stack = ([message] + exception.backtrace).join("\n ")
# send and email if this is production
if Rails.env.preview? || Rails.env.production?
suppress(Exception) do
request_info = {
'remote_ip' => request.remote_ip,
'uuid' => request.uuid,
'original_url' => request.original_url,
'env' => Hash.new
}
request.env.each do |key, value|
request_info['env'][key.to_s] = value.to_s
end
send_mail(:error_report,
"An error has occurred in #{Rails.env}",
nil,
exception.to_s,
exception.backtrace.join("\n"),
request_info,
params,
current_user,
Time.now.strftime("%d/%m/%Y %H:%M")
)
end
end
on_error(
Report.create(
request_id: request.uuid,
signature: message,
severity: :error,
source: :application,
backtrace: stack), exception)
end
# raise the error if we are in development so that we can debug it
raise exception if Rails.env.development?
def i18n_exception(str, exception, locale, key)
message = "#{exception.class.name}: #{exception.to_s}"
stack = "#{message}\n #{caller.join("\n ")}"
on_error(
Report.create(
request_id: request.uuid,
signature: message,
severity: :error,
source: :i18n,
backtrace: stack))
end
def protect(&block)
@@ -291,6 +281,7 @@ class ApplicationController < BaseController
end
def error_404(args = {})
@original_params = params.clone
params[:_original_action] = params[:action]
params[:action] = 'error-404'
@page_title = 'page_titles.404.Page_Not_Found'
@@ -308,6 +299,7 @@ class ApplicationController < BaseController
@template = template
@page_title ||= 'page_titles.403.Access_Denied'
@main_title ||= @page_title
@original_params = params.clone
params[:_original_action] = params[:action]
params[:action] = 'error-403'
@@ -317,11 +309,13 @@ class ApplicationController < BaseController
def error_500(exception = nil)
@page_title = 'page_titles.500.An_Error_Occurred'
@main_title = 'error.500.title'
@original_params = params.clone
params[:_original_action] = params[:action]
params[:action] = 'error-500'
@exception = exception
super(exception)
capture_response(500)
end
def on_translation_change(object, data, locale, translator_id)
@@ -353,39 +347,6 @@ class ApplicationController < BaseController
end
end
def i18n_exception(str, exception, locale, key)
# log it
logger.info "Missing translation found for: #{key}"
# send an email if this is production
if Rails.env.preview? || Rails.env.production?
begin
request_info = {
'remote_ip' => request.remote_ip,
'uuid' => request.uuid,
'original_url' => request.original_url,
'env' => Hash.new
}
request.env.each do |key, value|
request_info['env'][key.to_s] = value.to_s
end
send_mail(:error_report,
"A missing translation found in #{Rails.env}",
"<p>A translation for <code>#{key}</code> in <code>#{locale.to_s}</code> was found. The text that was rendered to the user was:</p><blockquote>#{str || 'nil'}</blockquote>",
exception.to_s,
nil,
request_info,
params,
current_user.id,
Time.now.strftime("%d/%m/%Y %H:%M")
)
rescue Exception => exception2
logger.info exception2.to_s
logger.info exception2.backtrace.join("\n")
end
end
end
def set_success_message(message, is_ajax = false)
if is_ajax
@success_message = message
@@ -613,10 +574,15 @@ class ApplicationController < BaseController
end
def set_conference_registration!
@registration = set_conference_registration
set_conference_registration
raise ActiveRecord::PremissionDenied unless @registration.present?
end
def ensure_registration_is_complete!
set_conference_registration!
raise ActiveRecord::PremissionDenied unless @registration.registered?
end
def set_or_create_conference_registration
set_conference_registration
return @registration if @registration.present?
@@ -82,6 +82,11 @@ class ConferencesController < ApplicationController
# get the current step
@step = current_registration_step(@this_conference, current_user)
if @update_status.nil? && flash[:status_message].present?
@update_status = flash[:status_message][:status]
@update_message = flash[:status_message][:message]
end
if @step == :payment_form && (params[:token].present? || @test_token.present?)
result = paypal_payment_confirm(@this_conference, current_user, params)
data_to_instance_variables(result)
+38 -36
View File
@@ -26,7 +26,8 @@ class WorkshopsController < ApplicationController
def create_workshop
set_conference
set_conference_registration!
ensure_registration_is_complete!
@workshop = Workshop.new
@languages = [I18n.locale.to_sym]
@needs = []
@@ -47,7 +48,7 @@ class WorkshopsController < ApplicationController
def edit_workshop
set_conference
set_conference_registration!
ensure_registration_is_complete!
@workshop = Workshop.find_by_id_and_conference_id(params[:workshop_id], @this_conference.id)
return do_404 unless @workshop.present?
@@ -82,7 +83,7 @@ class WorkshopsController < ApplicationController
def delete_workshop
set_conference
set_conference_registration!
ensure_registration_is_complete!
@workshop = Workshop.find_by_id_and_conference_id(params[:workshop_id], @this_conference.id)
return do_404 unless @workshop.present?
@@ -95,9 +96,9 @@ class WorkshopsController < ApplicationController
@workshop.destroy
end
return redirect_to register_step_path(@this_conference.slug, 'workshops')
return redirect_to workshops_path(@this_conference.slug)
end
return redirect_to view_workshop_url(@this_conference.slug, @workshop.id)
return redirect_to view_workshop_path(@this_conference.slug, @workshop.id)
end
@register_template = :workshops
@@ -106,13 +107,13 @@ class WorkshopsController < ApplicationController
def save_workshop
set_conference
set_conference_registration!
ensure_registration_is_complete!
if params[:button].to_sym != :save
if params[:workshop_id].present?
return redirect_to view_workshop_url(@this_conference.slug, params[:workshop_id])
return redirect_to view_workshop_path(@this_conference.slug, params[:workshop_id])
end
return redirect_to register_step_path(@this_conference.slug, 'workshops')
return redirect_to workshops_path(@this_conference.slug)
end
if params[:workshop_id].present?
@@ -120,8 +121,8 @@ class WorkshopsController < ApplicationController
return do_404 unless workshop.present?
can_edit = workshop.can_edit?(current_user)
else
workshop = Workshop.new(:conference_id => @this_conference.id)
workshop.workshop_facilitators = [WorkshopFacilitator.new(:user_id => current_user.id, :role => :creator)]
workshop = Workshop.new(conference_id: @this_conference.id)
workshop.workshop_facilitators = [WorkshopFacilitator.new(user_id: current_user.id, role: :creator)]
can_edit = true
end
@@ -157,27 +158,27 @@ class WorkshopsController < ApplicationController
workshop.save
# Rouge nil facilitators have been know to be created, just destroy them here now
WorkshopFacilitator.where(:user_id => nil).destroy_all
WorkshopFacilitator.where(user_id: nil).destroy_all
else
return do_403
end
redirect_to view_workshop_url(@this_conference.slug, workshop.id)
redirect_to view_workshop_path(@this_conference.slug, workshop.id)
end
def toggle_workshop_interest
set_conference
set_conference_registration!
ensure_registration_is_complete!
workshop = Workshop.find_by_id_and_conference_id(params[:workshop_id], @this_conference.id)
return do_404 unless workshop
# save the current state
interested = workshop.interested? current_user
# remove all associated fields
WorkshopInterest.delete_all(:workshop_id => workshop.id, :user_id => current_user.id)
WorkshopInterest.delete_all(workshop_id: workshop.id, user_id: current_user.id)
# creat the new interest row if we weren't interested before
WorkshopInterest.create(:workshop_id => workshop.id, :user_id => current_user.id) unless interested
WorkshopInterest.create(workshop_id: workshop.id, user_id: current_user.id) unless interested
if request.xhr?
render json: [
@@ -192,13 +193,13 @@ class WorkshopsController < ApplicationController
]
else
# go back to the workshop
redirect_to view_workshop_url(@this_conference.slug, workshop.id)
redirect_to view_workshop_path(@this_conference.slug, workshop.id)
end
end
def facilitate_workshop
set_conference
set_conference_registration!
ensure_registration_is_complete!
@workshop = Workshop.find_by_id_and_conference_id(params[:workshop_id], @this_conference.id)
return do_404 unless @workshop
return do_403 if @workshop.facilitator?(current_user) || !current_user
@@ -209,7 +210,7 @@ class WorkshopsController < ApplicationController
def facilitate_request
set_conference
set_conference_registration!
ensure_registration_is_complete!
workshop = Workshop.find_by_id_and_conference_id(params[:workshop_id], @this_conference.id)
return do_404 unless workshop
return do_403 if workshop.facilitator?(current_user) || !current_user
@@ -219,12 +220,12 @@ class WorkshopsController < ApplicationController
send_mail(:workshop_facilitator_request, workshop.id, current_user.id, params[:message])
redirect_to sent_facilitate_workshop_url(@this_conference.slug, workshop.id)
redirect_to sent_facilitate_workshop_path(@this_conference.slug, workshop.id)
end
def sent_facilitate_request
set_conference
set_conference_registration!
ensure_registration_is_complete!
@workshop = Workshop.find_by_id_and_conference_id(params[:workshop_id], @this_conference.id)
return do_404 unless @workshop
return do_403 unless @workshop.requested_collaborator?(current_user)
@@ -236,7 +237,7 @@ class WorkshopsController < ApplicationController
def approve_facilitate_request
return do_403 unless logged_in?
set_conference
set_conference_registration!
ensure_registration_is_complete!
workshop = Workshop.find_by_id_and_conference_id(params[:workshop_id], @this_conference.id)
return do_404 unless workshop.present?
@@ -253,24 +254,24 @@ class WorkshopsController < ApplicationController
LinguaFranca.with_locale(user.locale) do
send_mail(:workshop_facilitator_request_approved, workshop.id, user.id)
end
return redirect_to view_workshop_url(@this_conference.slug, workshop.id)
return redirect_to view_workshop_path(@this_conference.slug, workshop.id)
end
when :deny
if workshop.active_facilitator?(current_user) && workshop.requested_collaborator?(User.find(user_id))
WorkshopFacilitator.delete_all(
:workshop_id => workshop.id,
:user_id => user_id)
workshop_id: workshop.id,
user_id: user_id)
LinguaFranca.with_locale user.locale do
send_mail(:workshop_facilitator_request_denied, workshop.id, user.id)
end
return redirect_to view_workshop_url(@this_conference.slug, workshop.id)
return redirect_to view_workshop_path(@this_conference.slug, workshop.id)
end
when :remove
if workshop.can_remove?(current_user, user)
WorkshopFacilitator.delete_all(
:workshop_id => workshop.id,
:user_id => user_id)
return redirect_to view_workshop_url(@this_conference.slug, workshop.id)
workshop_id: workshop.id,
user_id: user_id)
return redirect_to view_workshop_path(@this_conference.slug, workshop.id)
end
when :switch_ownership
if workshop.creator?(current_user)
@@ -282,7 +283,7 @@ class WorkshopsController < ApplicationController
workshop.id, user_id)
f.role = :creator
f.save
return redirect_to view_workshop_url(@this_conference.slug, workshop.id)
return redirect_to view_workshop_path(@this_conference.slug, workshop.id)
end
end
@@ -291,7 +292,7 @@ class WorkshopsController < ApplicationController
def add_workshop_facilitator
set_conference
set_conference_registration!
ensure_registration_is_complete!
user = User.find_user(params[:email])
@@ -313,12 +314,12 @@ class WorkshopsController < ApplicationController
end
end
return redirect_to view_workshop_url(@this_conference.slug, params[:workshop_id])
return redirect_to view_workshop_path(@this_conference.slug, params[:workshop_id])
end
def add_comment
set_conference
set_conference_registration!
ensure_registration_is_complete!
workshop = Workshop.find_by_id_and_conference_id(params[:workshop_id], @this_conference.id)
return do_404 unless workshop && current_user
@@ -335,7 +336,7 @@ class WorkshopsController < ApplicationController
elsif params[:button] = 'add_comment'
new_comment = workshop.add_comment(current_user, params[:comment])
workshop.active_facilitators.each do | u |
workshop.active_facilitators.each do |u|
unless u.id == current_user.id
LinguaFranca.with_locale u.locale do
send_mail(:workshop_comment, workshop.id, new_comment.id, u.id)
@@ -346,20 +347,21 @@ class WorkshopsController < ApplicationController
return do_404
end
return redirect_to view_workshop_url(@this_conference.slug, workshop.id, anchor: "comment-#{new_comment.id}")
return redirect_to view_workshop_path(@this_conference.slug, workshop.id, anchor: "comment-#{new_comment.id}")
end
rescue_from ActiveRecord::PremissionDenied do |exception|
if !@this_conference.can_register?
do_404
elsif logged_in?
redirect_to 'conferences/register'
flash[:status_message] = { message: :registration_required, status: :warning }
redirect_to register_path(@this_conference.slug)
else
@register_template = :confirm_email
@page_title = "articles.conference_registration.headings.#{@this_conference.registration_status == :open ? '': 'Pre_'}Registration_Details"
@main_title = "articles.conference_registration.headings.#{@this_conference.registration_status == :open ? '': 'Pre_'}Register"
@main_title_vars = { vars: { title: @this_conference.title } }
render 'conferences/register'
render register_path(@this_conference.slug)
end
end