Workshop auth fixes and better error reporting
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user