This repository has been archived by the owner on Jun 7, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathctf_scoreboard.rb
165 lines (150 loc) · 4.17 KB
/
ctf_scoreboard.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
require 'bundler'
Bundler.require
require './models/user'
require './models/track'
require './models/flag'
Mongoid.load!('./mongoid.yml', :development)
class CtfScoreboard < Sinatra::Base
register Sinatra::Warden
enable :sessions, :logging
set :session_secret, "secretKey"
use Rack::Flash, sweep: true
get '/login' do
@error = env['x-rack.flash'][:error]
haml :login
end
# Redirec to login or scoreboard
get '/' do
redirect to('/login') if current_user.nil?
redirect to('/tracks')
end
get '/rules' do
haml :rules
end
# Show progress of players
get '/scoreboard' do
@users = User.where(hide: false).all.to_a
@tracks = Track.all.to_a
unless params[:track].nil?
@track = Track.where(name: params[:track]).first
@users = @users.map do |user|
track_flags = user.flags.select{|flag| flag.track.id == @track.id}
user.score = track_flags.map(&:points).inject(:+)
user
end
@users.each {|u| u.score = u.score.to_i}
end
haml :scoreboard
end
# Show player progress and flag submision
get '/tracks' do
authorize!
@user = current_user
@tracks = Track.all.order_by(order: :asc).to_a
haml :tracks
end
get '/track/:id' do
authorize!
@user = current_user
@track = Track.find(params[:id])
begin
haml :"#{@track.view}", layout: :track_layout
rescue
haml :track_no_details, layout: :track_layout
end
end
get '/flag/:id' do
authorize!
@user = current_user
@flag = Flag.find(params[:id])
@track = @flag.track
begin
haml :"#{@flag.view}", layout: :track_layout
rescue
haml :flag_no_hints, layout: :track_layout
end
end
# Submit a flag
post '/flag' do
authorize!
@user = current_user
log_obj = {user: @user.name, flag_id: nil, success: false}
if params['value'].blank?
log_obj[:error] = 'No flag submitted'
else
log_obj[:flag_value] = params['value']
flags = Flag.where(value: params['value'])
if flags.count == 0
log_obj[:error] = 'Incorrect flag value'
elsif flags.count > 1
log_obj[:error] = 'Multiple flags matched'
else
flag = flags.first
log_obj[:flag_name] = "#{flag.track.name}/#{flag.name}"
log_obj[:flag_points] = flag.points
if flag.locked or flag.track.locked
log_obj[:error] = 'The flag or track is locked'
elsif @user.flags.include? flag
log_obj[:error] = 'You have already submitted this flag'
else
@user.flags << flag
@user.update_score
flash[:success] = "Flag «#{flag.track.name} #{flag.name}» submitted! You earned #{flag.points} points"
log_obj[:success] = 1
end
end
end
unless log_obj[:error].nil?
flash[:error] = log_obj[:error]
end
logger.info log_obj.to_json.lines.join(' ')
redirect to('/tracks')
end
post '/register' do
@user = User.new({
email: params[:email]
})
if @user.email.blank?
flash[:error] = 'Email is required'
redirect to('/login')
elsif User.where(email: @user.email).count > 0
flash[:error] = 'Email is already registers'
redirect to('/login')
else
email_parts = params[:email].split('@')
domain = email_parts.last.split('.').last(2).join('.')
@user.affiliation = User::AFFILIATIONS[domain] || ''
haml :register
end
end
post '/register/complete' do
@user = User.new({
name: params[:name],
password: params[:password],
affiliation: params[:affiliation]
})
if params[:password] != params[:confirm]
flash[:error] = 'Password confirmation doesn\'t match password'
elsif @user.valid?
if @user.save
login params
redirect to('/rules')
return
else
flash[:error] = 'User could not be saved to database'
end
else
flash[:error] = @user.errors.full_messages.join '; '
end
haml :register
end
get '/layout.css' do
scss :layout
end
get '/user/:id' do
@user = User.find(params[:id])
@tracks = Track.all.order_by(order: :asc).to_a
haml :user
end
run! if app_file == $0
end