Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ end
group :test do
gem 'brakeman', require: false
gem 'bundler-audit', require: false
gem 'byebug'
gem 'ffi-hunspell'
gem 'rails-controller-testing'
gem 'rubocop', require: false
Expand Down
2 changes: 2 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ GEM
bundler-audit (0.7.0.1)
bundler (>= 1.2.0, < 3)
thor (>= 0.18, < 2)
byebug (11.1.3)
carrierwave (0.10.0)
activemodel (>= 3.2.0)
activesupport (>= 3.2.0)
Expand Down Expand Up @@ -372,6 +373,7 @@ DEPENDENCIES
bootstrap4-kaminari-views
brakeman
bundler-audit
byebug
carrierwave-postgresql (< 0.3.0)
chartkick
coffee-rails
Expand Down
56 changes: 56 additions & 0 deletions app/assets/stylesheets/surveys.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// Place all the styles related to the Surveys controller here.
// They will automatically be included in application.css.
// You can use Sass (SCSS) here: https://sass-lang.com/

.star-cb-group {
/* remove inline-block whitespace */
font-size: 0;
/* flip the order so we can use the + and ~ combinators */
unicode-bidi: bidi-override;
direction: rtl;
/* the hidden clearer */
}
.star-cb-group * {
font-size: 1rem;
}
.star-cb-group > input {
display: none;
}
.star-cb-group > input + label {
/* only enough room for the star */
display: inline-block;
overflow: hidden;
text-indent: 9999px;
width: 1em;
white-space: nowrap;
cursor: pointer;
}
.star-cb-group > input + label:before {
display: inline-block;
text-indent: -9999px;
content: "☆";
color: #888;
}
.star-cb-group > input:checked ~ label:before, .star-cb-group > input + label:hover ~ label:before, .star-cb-group > input + label:hover:before {
content: "★";
color: rgb(238, 206, 24);
text-shadow: 0 0 1px #333;
}
.star-cb-group > .star-cb-clear + label {
text-indent: -9999px;
width: .5em;
margin-left: -.5em;
}
.star-cb-group > .star-cb-clear + label:before {
width: .5em;
}
.star-cb-group:hover > input + label:before {
content: "☆";
color: #888;
text-shadow: none;
}
.star-cb-group:hover > input + label:hover ~ label:before, .star-cb-group:hover > input + label:hover:before {
content: "★";
color: rgb(238, 206, 24);
text-shadow: 0 0 1px #333;
}
7 changes: 5 additions & 2 deletions app/controllers/challenges_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,11 @@ def update
@solved_challenge = @flag_found.save_solved_challenge(current_user)
@solved_video_url = @flag_found.video_url
flash.now[:notice] = I18n.t('flag.accepted')
@survey = Survey.new(submitted_flag_id: @submitted_flag.id)
else
flash.now[:alert] = wrong_flag_messages.sample
@solvable = @challenge.can_be_solved_by(current_user.team)
end
@solvable = @challenge.can_be_solved_by(current_user.team)

render :show
end
Expand All @@ -51,7 +52,9 @@ def find_and_log_flag
flag = params[:challenge]&.[](:submitted_flag) # Safe navigation on a hash
return if flag.nil?

SubmittedFlag.create(user: current_user, challenge: @challenge, text: flag) unless current_user.admin?
unless current_user.admin?
@submitted_flag = SubmittedFlag.create(user: current_user, challenge: @challenge, text: flag)
end
@flag_found = @challenge.find_flag(flag)
end

Expand Down
18 changes: 18 additions & 0 deletions app/controllers/surveys_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# frozen_string_literal: true

class SurveysController < ApplicationController
def create
@survey = Survey.new(survey_params)
if(@survey.save)
return redirect_to '/game', notice: I18n.t('surveys.submitted')
else
return redirect_to '/game', notice: @survey.errors.full_messages
end
end

private

def survey_params
params.require(:survey).permit(:difficulty, :realism, :interest, :comment, :submitted_flag_id, :team_id)
end
end
1 change: 1 addition & 0 deletions app/models/submitted_flag.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
class SubmittedFlag < ApplicationRecord
belongs_to :user
belongs_to :challenge
has_one :survey, dependent: :destroy

validates :text, presence: true

Expand Down
6 changes: 6 additions & 0 deletions app/models/survey.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# frozen_string_literal: true

class Survey < ApplicationRecord
belongs_to :submitted_flag, optional: true
belongs_to :team
end
2 changes: 1 addition & 1 deletion app/models/team.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ class Team < ApplicationRecord
# Current_score is so we don't have to have any logic to handle
# which class we are rendering in the game summary view.
attr_accessor :rank, :current_score

has_many :surveys
# This has_many is only applicable to Pentest Challenges
has_many :defense_flags, dependent: :destroy
has_many :feed_items, dependent: :destroy
Expand Down
8 changes: 6 additions & 2 deletions app/views/challenges/show.html.haml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
-# For PentestGames, @challenge here can actually be a flag object since Pentest challenges belong to teams + challenges and are linked by a flag object.
-#
-#
- content_for :admin_menu do
%a.dropdown-item{:href => admin_edit_url(@challenge)}= t('challenges.admin_edit_challenge', challengename: @challenge.name)

Expand Down Expand Up @@ -35,7 +35,11 @@
= f.text_field :submitted_flag, :class => "form-control col-sm-10"
.control-group
= invisible_recaptcha_tags text: 'Submit', :class => "btn btn-primary"

- if @solved_challenge
%hr/
= render partial: "surveys/form"
%hr/

- if @solved_by.length > 0
%table.table.table-bordered.table-striped.table-hover
%thead
Expand Down
28 changes: 28 additions & 0 deletions app/views/surveys/_form.html.haml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
= form_for @survey, html: { class: "well form-inline", style: "margin-bottom:40px;" } do |f|
- if @survey.errors.any?
#error_explanation
%h2= "#{pluralize(@survey.errors.count, "error")} prohibited this survey from being saved:"
%ul
- @survey.errors.full_messages.each do |message|
%li= message

%h3= t('surveys.new.header')
.rating
.field
= f.label :difficulty
= render partial: "surveys/star_rating", locals: { category: :difficulty, f: f }
.field
= f.label :realism
= render partial: "surveys/star_rating", locals: { category: :realism, f: f }
.field
= f.label :interest
= render partial: "surveys/star_rating", locals: { category: :interest, f: f }
.field
= f.label :comment
= f.text_area :comment
.field
= f.hidden_field :submitted_flag_id
.field
= f.hidden_field :team_id
.field
= f.submit t('surveys.new.submit_btn'), class: "btn btn-primary"
5 changes: 5 additions & 0 deletions app/views/surveys/_star_rating.html.haml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.rating
%span.star-cb-group
- [5, 4, 3, 2, 1].each do |rating|
= f.radio_button category, rating, { :name => "survey[#{category}]", :id => "#{category}_#{rating}", :value => rating }
%label{:for => "#{category}_#{rating}"}
2 changes: 1 addition & 1 deletion config/initializers/rails_admin.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
config.actions do
# root actions
dashboard # mandatory
# collection actions
# collection actions
index # mandatory
new do
except ['Challenge', 'FeedItem', 'SolvedChallenge', 'Flag'] # Block users from adding items from their parent classes instead of their own classes
Expand Down
6 changes: 6 additions & 0 deletions config/locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -435,5 +435,11 @@ en:
sign in attempts.
unlock_line_2: 'Click the link below to unlock your account:'
unlock_account_link: Unlock my account
surveys:
submitted: 'Survey Submitted!'
invalid: 'Invalid survey submitted.'
new:
header: 'Review Solved Challenge'
submit_btn: 'Submit Survey'
# Set a default fallback for use if no organization is set on the game.
default_organization: 'us'
2 changes: 2 additions & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@
end
end

resource :surveys, only: %i[create update]

get '/game/summary' => 'games#summary'
get '/game/teams' => 'games#teams'

Expand Down
14 changes: 14 additions & 0 deletions db/migrate/20200710145833_create_surveys.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
class CreateSurveys < ActiveRecord::Migration[6.0]
def change
create_table :surveys do |t|
t.integer :difficulty, default: 0, null: false
t.integer :realism, default: 0, null: false
t.integer :interest, default: 0, null: false
t.text :comment, default: "", null: true
t.integer :submitted_flag_id, null: false
t.references :team, foreign_key: true
t.timestamps
end
add_foreign_key "surveys", "submitted_flags"
end
end
16 changes: 15 additions & 1 deletion db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.

ActiveRecord::Schema.define(version: 2020_06_23_173255) do
ActiveRecord::Schema.define(version: 2020_07_10_145833) do

# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
Expand Down Expand Up @@ -178,6 +178,18 @@
t.index ["flag_id"], name: "index_submitted_flags_on_flag_id"
end

create_table "surveys", force: :cascade do |t|
t.integer "difficulty", default: 0, null: false
t.integer "realism", default: 0, null: false
t.integer "interest", default: 0, null: false
t.text "comment", default: ""
t.integer "submitted_flag_id", null: false
t.bigint "team_id"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.index ["team_id"], name: "index_surveys_on_team_id"
end

create_table "teams", id: :serial, force: :cascade do |t|
t.string "team_name"
t.datetime "created_at"
Expand Down Expand Up @@ -281,5 +293,7 @@
add_foreign_key "challenges", "games"
add_foreign_key "flags", "teams"
add_foreign_key "submitted_flags", "flags"
add_foreign_key "surveys", "submitted_flags"
add_foreign_key "surveys", "teams"
add_foreign_key "teams", "divisions"
end
23 changes: 23 additions & 0 deletions test/controllers/surveys_controller_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
require 'test_helper'

class SurveysControllerTest < ActionController::TestCase

def setup
create(:active_game)
@team1 = create(:team)
@team2 = create(:team)
@standard_challenge = create(:standard_challenge, flag_count: 3)
@pentest_challenge = create(:pentest_challenge_with_flags)
end

test 'create new survey' do
team_user = create(:user_with_team)
sign_in team_user
submitted_flag = create(:submitted_flag, user: team_user, challenge: @standard_challenge)
assert_difference 'Survey.count', +1 do
post :create, params: { survey: { difficulty: 5, realism: 5, interest: 5, comment: "MyText", submitted_flag_id: submitted_flag.id } }
end
assert_redirected_to game_path
assert_match I18n.t('surveys.submitted'), flash[:notice]
end
end
11 changes: 11 additions & 0 deletions test/factories/surveys.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# frozen_string_literal: true

FactoryBot.define do
factory :survey do
difficulty { Faker::Number.between(from:1, to:5) }
realism { Faker::Number.between(from:1, to:5) }
interest { Faker::Number.between(from:1, to:5) }
comment { "MyText" }
submitted_flag_id { 1 }
end
end
Loading