Secure public contestant forms by asking the code first
This commit is contained in:
@@ -7,7 +7,7 @@ class ContestantsController < ApplicationController
|
||||
before_action :set_contest, only: %i[ index edit new create update destroy import upload_csv convert_csv finalize_import export generate_qrcodes generate_qrcodes_pdf generate_qrcodes_archive ]
|
||||
before_action :set_contestant, only: %i[ destroy edit update]
|
||||
before_action :set_completions, only: %i[edit update ]
|
||||
skip_before_action :require_authentication, only: %i[ get_public_completion post_public_completion public_completion_updated ]
|
||||
skip_before_action :require_authentication, only: %i[ get_public_completion get_public_completion_code post_public_completion_code post_public_completion public_completion_updated ]
|
||||
|
||||
def index
|
||||
authorize @contest
|
||||
@@ -162,23 +162,74 @@ class ContestantsController < ApplicationController
|
||||
|
||||
def get_public_completion
|
||||
skip_authorization
|
||||
@public = true
|
||||
|
||||
@contestant = Contestant.find(params[:contestant_id])
|
||||
if !@contestant || !@contestant.contest.code.present? || !@contestant.contest.organizer_form
|
||||
not_found and return
|
||||
end
|
||||
I18n.locale = @contestant.contest.lang
|
||||
@completion = Completion.new
|
||||
@title = @contestant.contest.name
|
||||
|
||||
render "completions/validate_organizer_code"
|
||||
end
|
||||
|
||||
def post_public_completion_code
|
||||
skip_authorization
|
||||
@public = true
|
||||
|
||||
@contestant = Contestant.find(params[:contestant_id])
|
||||
if !@contestant || !@contestant.contest.code.present? || !@contestant.contest.organizer_form
|
||||
not_found and return
|
||||
end
|
||||
I18n.locale = @contestant.contest.lang
|
||||
@title = @contestant.contest.name
|
||||
|
||||
@completion = Completion.new(completion_params)
|
||||
@completion.contest = @contestant.contest
|
||||
@completion.contestant = @contestant
|
||||
if !@completion.code.present?
|
||||
to_modify = true
|
||||
@completion.code = "incorrect-xZy"
|
||||
end
|
||||
@completion.save
|
||||
if @completion.code != @contestant.contest.code
|
||||
if to_modify
|
||||
@completion.code = nil
|
||||
end
|
||||
render "completions/validate_organizer_code", status: :unprocessable_entity
|
||||
else
|
||||
redirect_to "/public/p/#{@contestant.id}/code?code=#{@completion.code}"
|
||||
end
|
||||
end
|
||||
|
||||
def get_public_completion_code
|
||||
skip_authorization
|
||||
@public = true
|
||||
|
||||
@contestant = Contestant.find(params[:contestant_id])
|
||||
if !@contestant || !@contestant.contest.code.present? || !@contestant.contest.organizer_form
|
||||
not_found and return
|
||||
end
|
||||
I18n.locale = @contestant.contest.lang
|
||||
|
||||
if !params.key?(:code) || params[:code] != @contestant.contest.code
|
||||
redirect_to "/public/p/#{@contestant.id}" and return
|
||||
end
|
||||
|
||||
@contest = @contestant.contest
|
||||
I18n.locale = @contest.lang
|
||||
@puzzles = @contest.puzzles.where(hidden: false).or(@contest.puzzles.where(hidden: nil)).order(:id)
|
||||
@completion = Completion.new
|
||||
@completion.completed = true
|
||||
@public = true
|
||||
@completion.code = @contest.code
|
||||
|
||||
render "completions/_form", locals: { completion: @completion, submit_text: t("helpers.buttons.create"), method: :post, url: "/public/p/#{params[:contestant_id]}" }
|
||||
end
|
||||
|
||||
def post_public_completion
|
||||
skip_authorization
|
||||
@public = true
|
||||
|
||||
@contestant = Contestant.find(params[:contestant_id])
|
||||
if !@contestant || !@contestant.contest.code.present?
|
||||
@@ -188,21 +239,17 @@ class ContestantsController < ApplicationController
|
||||
I18n.locale = @contest.lang
|
||||
|
||||
@completion = Completion.new(completion_params)
|
||||
if @completion.code != @contest.code
|
||||
redirect_to "/public/p/#{@contestant.id}" and return
|
||||
end
|
||||
|
||||
@completion.contest = @contest
|
||||
@completion.contestant = @contestant
|
||||
if !@completion.code.present?
|
||||
to_modify = true
|
||||
@completion.code = "incorrect-xZy"
|
||||
end
|
||||
if @completion.save
|
||||
extend_completions!(@completion.contestant)
|
||||
redirect_to "/public/p/#{params[:contestant_id]}/updated"
|
||||
else
|
||||
@puzzles = @contest.puzzles
|
||||
@public = true
|
||||
if to_modify
|
||||
@completion.code = nil
|
||||
end
|
||||
render "completions/_form", locals: { completion: @completion, submit_text: t("helpers.buttons.create"), method: :post, url: "/public/p/#{params[:contestant_id]}" }, status: :unprocessable_entity
|
||||
end
|
||||
end
|
||||
|
||||
@@ -126,9 +126,7 @@
|
||||
.row.mb-3
|
||||
.col
|
||||
.form-floating
|
||||
= form.text_field :code, autocomplete: "off", class: "form-control"
|
||||
= form.label :code
|
||||
= t("completions.form.code")
|
||||
= form.hidden_field :code, autocomplete: "off", class: "form-control"
|
||||
.row
|
||||
.col
|
||||
= form.submit submit_text, class: "btn btn-primary"
|
||||
20
app/views/completions/validate_organizer_code.html.slim
Normal file
20
app/views/completions/validate_organizer_code.html.slim
Normal file
@@ -0,0 +1,20 @@
|
||||
- if @public && @contestant.contest.puzzles.length == @contestant.completions.length
|
||||
h4
|
||||
= t("completions.form.validate_name", name: @contestant.name)
|
||||
.mt-3.alert.alert-warning
|
||||
= t("completions.form.all_finished", name: @contestant.name)
|
||||
- else
|
||||
.row.mt-2
|
||||
.col
|
||||
h4
|
||||
= t("completions.form.validate_name", name: @contestant.name)
|
||||
= form_with model: @completion, url: "/public/p/#{@contestant.id}/code", method: "post" do |form|
|
||||
.row.mt-3
|
||||
.col
|
||||
.form-floating
|
||||
= form.text_field :code, autocomplete: "off", class: "form-control"
|
||||
= form.label :code
|
||||
= t("completions.form.code")
|
||||
.row.mt-3
|
||||
.col
|
||||
= form.submit t("helpers.buttons.validate"), class: "btn btn-primary"
|
||||
@@ -349,6 +349,7 @@ en:
|
||||
stopwatch_reset: Reset
|
||||
stopwatch_start: Start
|
||||
update: Save modifications
|
||||
validate: Validate
|
||||
field: Field
|
||||
none: No field selected
|
||||
rank: Rank
|
||||
|
||||
@@ -320,6 +320,7 @@ fr:
|
||||
stopwatch_reset: Ré-initialiser
|
||||
stopwatch_start: Démarrer
|
||||
update: Enregistrer les modifications
|
||||
validate: Valider
|
||||
field: Champ
|
||||
none: Aucun champ sélectionné
|
||||
rank: Rang
|
||||
|
||||
@@ -63,6 +63,8 @@ Rails.application.routes.draw do
|
||||
get "public/:id/offline/:token/completed", to: "contests#offline_completed"
|
||||
get "public/p/:contestant_id", to: "contestants#get_public_completion"
|
||||
post "public/p/:contestant_id", to: "contestants#post_public_completion"
|
||||
get "public/p/:contestant_id/code", to: "contestants#get_public_completion_code"
|
||||
post "public/p/:contestant_id/code", to: "contestants#post_public_completion_code"
|
||||
get "public/p/:contestant_id/updated", to: "contestants#public_completion_updated"
|
||||
|
||||
direct :public_scoreboard do |contest|
|
||||
|
||||
Reference in New Issue
Block a user