require 'net/https'
class ApplicationController < BaseController
protect_from_forgery with : :exception , except : [ :do_confirm , :js_error , :admin_update ]
before_filter :application_setup
after_filter :capture_page_info
helper_method :protect , :policies
RECAPTCHA_MINIMUM_SCORE = 0 . 5
def verify_recaptcha? ( token , recaptcha_action )
recaptcha_secret_key = ENV [ 'RECAPTCHA_SECRET_KEY' ]
uri = URI . parse ( " https://www.google.com/recaptcha/api/siteverify?secret= #{ recaptcha_secret_key } &response= #{ token } " )
response = Net :: HTTP . get_response ( uri )
json = JSON . parse ( response . body )
# json['success'] && json['score'] > RECAPTCHA_MINIMUM_SCORE && json['action'] == recaptcha_action
puts json . inspect
json [ 'success' ] && json [ 'score' ] > RECAPTCHA_MINIMUM_SCORE
end
def default_url_options
{ host : " #{ request . protocol } #{ request . host_with_port } " , trailing_slash : true }
end
def capture_page_info
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 = {
open : 1 ,
pre : 2 ,
closed : 3
}
@conferences = Conference . where ( is_featured : true , is_public : true ) . order ( " start_date DESC " ) . sort do | a , b |
status_hierarchy [ ( a . registration_status || :closed ) . to_sym ] < = > status_hierarchy [ ( b . registration_status || :closed ) . to_sym ]
end
# set the top conference
@conference = @conferences . first
# add some style sheets
@stylesheets || = Set . new
# add the translations stylesheet if translating
@stylesheets << params [ :controller ] if params [ :controller ] == 'translations'
@_inline_scripts || = Set . new
@_inline_scripts << File . read ( File . join ( Rails . public_path , ActionController :: Base . helpers . asset_path ( 'main.js' ) ) )
ActionMailer :: Base . default_url_options = {
host : " #{ request . protocol } #{ request . host_with_port } "
}
@alt_lang_urls = { }
I18n . backend . enabled_locales . sort . each do | locale |
locale = locale . to_s
@alt_lang_urls [ locale ] = view_context . url_for_locale ( locale ) # don't show the current locale
end
# give each environment a different icon and theme colour so that we can easily see where we are. See https://css-tricks.com/give-development-domain-different-favicon-production
@favicon = Rails . env . development? || Rails . env . preview? ? " favicon- #{ Rails . env . to_s } .ico " : 'favicon.ico'
@theme_colour = Rails . env . preview? ? '#EF57B4' : ( Rails . env . development? ? '#D89E59' : '#00ADEF' )
end
def home
if @conference . present? && @conference . id . present?
@workshops = Workshop . where ( conference_id : @conference . id )
if @conference . workshop_schedule_published
@event_dlg = true
get_scheule_data ( false )
end
end
end
def policy
@is_policy_page = true
end
def confirmation_sent ( user )
template = 'login_confirmation_sent'
@page_title || = 'page_titles.403.Please_Check_Email'
if ( request . present? && request . referrer . present? && conference = / ^ \/ conferences \/ ( \ w+) \/ register \/ ?$ / . match ( request . referrer . gsub ( / ^https?: \/ \/ .*? \/ / , '/' ) ) )
@this_conference = Conference . find_by! ( slug : conference [ 1 ] )
@banner_image = @this_conference . cover_url
template = 'conferences/email_confirm'
end
do_403 template
end
def locale_not_enabled! ( locale = nil )
locale_not_available! ( locale )
end
def locale_not_available
locale_not_available! ( params [ :locale ] )
end
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'
@main_title_vars = { vars : { language : view_context . language_name ( locale ) } }
@main_title = 'error.locale_not_available.title'
unless @alt_lang_urls . present?
@alt_lang_urls = { }
I18n . backend . enabled_locales . sort . each do | locale |
locale = locale . to_s
@alt_lang_urls [ locale ] = view_context . url_for_locale ( locale ) # don't show the current locale
end
end
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 \t at #{ 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
# show the error page
error_500 exception
end
end
def handle_exception ( exception )
# 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 " )
on_error (
Report . create (
request_id : request . uuid ,
signature : message ,
severity : :error ,
source : :application ,
backtrace : stack ) , exception )
end
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 )
begin
yield
rescue Exception = > exception
handle_exception exception
end
end
def contact
@main_title = @page_title = 'page_titles.contact.Contact_Us'
end
def contact_send
email_list = [ ENV [ 'ADMIN_EMAIL' ] ]
if params [ :reason ] == 'conference' && logged_in?
@conference . conference_administrators . each do | administrator |
email_list << administrator . user . named_email
end
end
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
if ! ( params [ :subject ] =~ / ^ \ s*[a-z]{10} \ s*$ /i )
send_delayed_mail ( :contact ,
current_user || params [ :email ] ,
params [ :subject ] ,
params [ :message ] ,
email_list
)
send_delayed_mail ( :contact_details ,
current_user || params [ :email ] ,
params [ :subject ] ,
params [ :message ] ,
request_info ,
params
)
end
redirect_to contact_sent_path
end
def contact_sent
@main_title = @page_title = 'page_titles.contact.Contact_Us'
@sent = true
render 'contact'
end
def confirm_user
if params [ :email ]
template = 'login_confirmation_sent'
@page_title || = 'page_titles.403.Please_Check_Email'
if ( request . present? && request . referrer . present? && conference = / ^ \/ conferences \/ ( \ w+) \/ register \/ ?$ / . match ( request . referrer . gsub ( / ^https?: \/ \/ .*? \/ / , '/' ) ) )
@this_conference = Conference . find_by! ( slug : conference [ 1 ] )
@banner_image = @this_conference . cover_url
template = 'conferences/email_confirm'
end
end
if request . post?
@banner_image || = 'grafitti.jpg'
@page_title || = 'page_titles.403.Please_Login'
do_403 template
else
do_404
end
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'
@main_title = 'error.404.title'
super ( args )
end
def do_403 ( template = nil )
@banner_image = 'grafitti.jpg'
unless current_user
@page_title = 'page_titles.403.Please_Login'
end
@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'
super ( template )
end
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 )
translator = User . find ( translator_id )
mailer = " #{ object . class . table_name . singularize } _translated "
if object . respond_to? ( :get_translators )
object . get_translators ( data , locale ) . each do | id , user |
if user . id != current_user . id && user . id != translator_id
LinguaFranca . with_locale user . locale do
send_delayed_mail ( :send , mailer , object . id , data , locale , user . id , translator . id )
end
end
end
end
end
def on_translatable_content_change ( object , data )
mailer = " #{ object . class . table_name . singularize } _original_content_changed "
if object . respond_to? ( :get_translators )
object . get_translators ( data ) . each do | id , user |
if user . id != current_user . id
LinguaFranca . with_locale user . locale do
send_delayed_mail ( :send , mailer , object . id , data , user . id , current_user . id )
end
end
end
end
end
def set_success_message ( message , is_ajax = false )
if is_ajax
@success_message = message
else
flash [ :success_message ] = message
end
end
def set_error_message ( message , is_ajax = false )
if is_ajax
@error_message = message
else
flash [ :error_message ] = message
end
end
def set_error ( field , error , is_ajax = false )
if is_ajax
@errors || = { }
@errors [ field ] = error
else
flash [ :errors ] || = { }
flash [ :errors ] [ field ] = error
end
end
def set_flash_messages
@errors = flash [ :errors ] || { }
@warnings = flash [ :warning ] || [ ]
@success_message = flash [ :success_message ]
@error_message = flash [ :error_message ] || [ ]
end
def get_block_data
conference = @this_conference || @conference
@workshop_blocks = conference . workshop_blocks || [ ]
@block_days = [ ]
day = conference . start_date
while day < = conference . end_date
@block_days << day . wday
day += 1 . day
end
end
def get_scheule_data ( do_analyze = true )
conference = @this_conference || @conference
@meals = Hash [ ( conference . meals || { } ) . map { | k , v | [ k . to_i , v ] } ] . sort . to_h
@events = Event . where ( conference_id : conference . id ) . order ( start_time : :asc )
@workshops = Workshop . where ( conference_id : conference . id ) . order ( start_time : :asc )
@locations = { }
get_block_data
schedule = { }
day_1 = conference . start_date . wday
@workshop_blocks . each_with_index do | info , block |
info [ 'days' ] . each do | block_day |
day_diff = block_day . to_i - day_1
day_diff += 7 if day_diff < 0
day = ( conference . start_date + day_diff . days ) . to_date
time = info [ 'time' ] . to_f
schedule [ day ] || = { times : { } , locations : { } }
schedule [ day ] [ :times ] [ time ] || = { }
schedule [ day ] [ :times ] [ time ] [ :type ] = :workshop
schedule [ day ] [ :times ] [ time ] [ :length ] = info [ 'length' ] . to_f
schedule [ day ] [ :times ] [ time ] [ :item ] = { block : block , workshops : { } }
end
end
@workshops . each do | workshop |
if workshop . block . present?
block = @workshop_blocks [ workshop . block [ 'block' ] . to_i ]
day_diff = workshop . block [ 'day' ] . to_i - day_1
day_diff += 7 if day_diff < 0
day = ( conference . start_date + day_diff . days ) . to_date
if block . present? && schedule [ day ] . present? && schedule [ day ] [ :times ] . present? && schedule [ day ] [ :times ] [ block [ 'time' ] . to_f ] . present?
schedule [ day ] [ :times ] [ block [ 'time' ] . to_f ] [ :item ] [ :workshops ] [ workshop . event_location_id ] = { workshop : workshop , status : { errors : [ ] , warnings : [ ] , conflict_score : nil } }
schedule [ day ] [ :locations ] [ workshop . event_location_id ] || = workshop . event_location if workshop . event_location . present?
end
end
end
@meals . each do | time , meal |
day = meal [ 'day' ] . to_date
time = meal [ 'time' ] . to_f
schedule [ day ] || = { }
schedule [ day ] [ :times ] || = { }
schedule [ day ] [ :times ] [ time ] || = { }
schedule [ day ] [ :times ] [ time ] [ :type ] = :meal
schedule [ day ] [ :times ] [ time ] [ :length ] = ( meal [ 'length' ] || 1 . 0 ) . to_f
schedule [ day ] [ :times ] [ time ] [ :item ] = meal
end
@events . each do | event |
if event . present? && event . start_time . present? && event . end_time . present?
day = event . start_time . midnight . to_date
time = event . start_time . hour . to_f + ( event . start_time . min / 60 . 0 )
schedule [ day ] || = { }
schedule [ day ] [ :times ] || = { }
schedule [ day ] [ :times ] [ time ] || = { }
schedule [ day ] [ :times ] [ time ] [ :type ] = :event
schedule [ day ] [ :times ] [ time ] [ :length ] = ( event . end_time - event . start_time ) / 3600 . 0
schedule [ day ] [ :times ] [ time ] [ :item ] = event
end
end
schedule = schedule . sort . to_h
schedule . each do | day , data |
schedule [ day ] [ :times ] = data [ :times ] . sort . to_h
end
schedule . each do | day , data |
last_event = nil
data [ :times ] . each do | time , time_data |
if last_event . present?
schedule [ day ] [ :times ] [ last_event ] [ :next_event ] = time
end
last_event = time
end
schedule [ day ] [ :num_locations ] = ( data [ :locations ] || [ ] ) . size
end
schedule . deep_dup . each do | day , data |
data [ :times ] . each do | time , time_data |
if time_data [ :next_event ] . present? || time_data [ :length ] > conference . schedule_interval
span = conference . schedule_interval
length = time_data [ :next_event ] . present? ? time_data [ :next_event ] - time : time_data [ :length ]
while span < length
schedule [ day ] [ :times ] [ time + span ] || = {
type : ( span > = time_data [ :length ] ? :empty : :nil ) ,
length : conference . schedule_interval
}
span += conference . schedule_interval
end
end
end
end
schedule . each do | day , data |
schedule [ day ] [ :times ] = data [ :times ] . sort . to_h
schedule [ day ] [ :locations ] || = { }
# sort the locations by name
schedule [ day ] [ :locations ] = schedule [ day ] [ :locations ] . sort_by { | event_id , event | event . present? ? event . title . downcase : '' } . to_h
if do_analyze
data [ :times ] . each do | time , time_data |
if time_data [ :type ] == :workshop && time_data [ :item ] . present? && time_data [ :item ] [ :workshops ] . present?
ids = time_data [ :item ] [ :workshops ] . keys
( 0 .. ids . length ) . each do | i |
if time_data [ :item ] [ :workshops ] [ ids [ i ] ] . present?
workshop_i = time_data [ :item ] [ :workshops ] [ ids [ i ] ] [ :workshop ]
conflicts = { }
( i + 1 .. ids . length ) . each do | j |
workshop_j = time_data [ :item ] [ :workshops ] [ ids [ j ] ] . present? ? time_data [ :item ] [ :workshops ] [ ids [ j ] ] [ :workshop ] : nil
if workshop_i . present? && workshop_j . present?
workshop_i . active_facilitators . each do | facilitator_i |
workshop_j . active_facilitators . each do | facilitator_j |
if facilitator_i . id == facilitator_j . id
schedule [ day ] [ :times ] [ time ] [ :status ] || = { }
schedule [ day ] [ :times ] [ time ] [ :item ] [ :workshops ] [ ids [ j ] ] [ :status ] [ :errors ] << {
name : :common_facilitator ,
facilitator : facilitator_i ,
workshop : workshop_i ,
i18nVars : {
facilitator_name : facilitator_i . name ,
workshop_title : workshop_i . title
}
}
end
end
end
end
end
location = workshop_i . event_location || EventLocation . new
needs = JSON . parse ( workshop_i . needs || '[]' ) . map & :to_sym
amenities = JSON . parse ( location . amenities || '[]' ) . map & :to_sym
needs . each do | need |
schedule [ day ] [ :times ] [ time ] [ :item ] [ :workshops ] [ ids [ i ] ] [ :status ] [ :errors ] << {
name : :need_not_available ,
need : need ,
location : location ,
workshop : workshop_i ,
i18nVars : {
need : I18n . t ( " workshop.options.amenity. #{ need } " ) ,
location : location . title ,
workshop_title : workshop_i . title
}
} unless amenities . include? need
end
# collect common interested users
interests = [ ]
( 0 .. ids . length ) . each do | j |
workshop_j = time_data [ :item ] [ :workshops ] [ ids [ j ] ] . present? ? time_data [ :item ] [ :workshops ] [ ids [ j ] ] [ :workshop ] : nil
if workshop_i . present? && workshop_j . present? && workshop_i . id != workshop_j . id
interests = interests | workshop_j . interested . map { | u | u . user_id }
end
end
schedule [ day ] [ :times ] [ time ] [ :item ] [ :workshops ] [ ids [ i ] ] [ :status ] [ :conflict_score ] = ( interests & ( workshop_i . interested . map { | u | u . user_id } ) ) . length
end
end
end
end
end
end
@schedule = { }
schedule . sort . to_h . each do | day , data |
@schedule [ day ] = [ ]
division = 0
locations = nil
@schedule [ day ] [ division ] = { }
@schedule [ day ] [ division ] [ :times ] = { }
data [ :times ] . each do | time , time_data |
if time_data [ :type ] == :workshop && time_data [ :item ] . present? && time_data [ :item ] [ :workshops ] . present?
if ! locations . nil? && ( ( locations . keys - time_data [ :item ] [ :workshops ] . keys ) | ( time_data [ :item ] [ :workshops ] . keys - locations . keys ) ) . length > 0
@schedule [ day ] [ division ] [ :locations ] = locations . deep_dup
@schedule [ day ] [ division ] [ :locations ] [ 0 ] = :add if do_analyze || locations . empty?
locations = data [ :locations ] . select { | id , l | time_data [ :item ] [ :workshops ] [ id ] . present? }
division += 1
@schedule [ day ] [ division ] = { }
@schedule [ day ] [ division ] [ :times ] = { }
else
locations = data [ :locations ] . select { | id , l | time_data [ :item ] [ :workshops ] [ id ] . present? }
end
end
# last_time_data = time_data
@schedule [ day ] [ division ] [ :times ] [ time ] = time_data
end
locations || = data [ :locations ]
@schedule [ day ] [ division ] [ :locations ] = locations
@schedule [ day ] [ division ] [ :locations ] [ 0 ] = :add if do_analyze || locations . empty?
@schedule [ day ] [ division ] [ :num_locations ] = locations . length
end
end
protected
def set_conference
@this_conference = Conference . find_by! ( slug : params [ :slug ] )
end
def set_conference_registration
@registration = logged_in? ? ConferenceRegistration . find_by ( user_id : current_user . id , conference_id : @this_conference . id ) : nil
end
def 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?
@registration || = ConferenceRegistration . new (
conference : @this_conference ,
user_id : current_user . id ,
steps_completed : [ ]
)
last_registration_data = ConferenceRegistration . where ( user_id : current_user . id ) . order ( created_at : :desc ) . limit ( 1 ) . first
if last_registration_data . present?
if last_registration_data [ 'languages' ] . present? && current_user . languages . blank?
current_user . languages = JSON . parse ( last_registration_data [ 'languages' ] )
current_user . save!
end
@registration . city = last_registration_data . city if last_registration_data . city . present?
end
end
# Set empty HTML values to nil, sometimes we will get values such as '<p> </p>' in rich edits, this will help to make sure they are actually empty
def html_value ( value )
return value . present? && ActionView :: Base . full_sanitizer . sanitize ( value ) . strip . present? ? value : nil
end
# send the confirmation email and make sure it get sent as quickly as possible
def send_confirmation ( confirmation )
# puts lookup_context.find_all(params[:action], params[:controller]).inspect
unless verify_recaptcha? ( params [ :recaptcha_token ] , 'sign_in' )
flash . now [ :error ] = 'recaptcha.errors.verification_failed'
return render 'about'
end
send_mail ( :email_confirmation , confirmation . id )
end
def send_delayed_mail ( * args )
if Rails . env . preview? || Rails . env . production?
UserMailer . delay ( queue : Rails . env . to_s ) . send ( * args )
else
UserMailer . send ( * args ) . deliver_now
end
end
def send_mail ( * args )
UserMailer . send ( * args ) . deliver_now
end
def policies
[
:commitment ,
:respect ,
:empowerment ,
:accessible ,
:peaceful ,
:spaces ,
:hearing ,
:intent ,
:open_minds ,
:learning
]
end
end