Description:
switch to strong parameter for mass update (have not finished the problem controller yet)
Commit status:
[Not Reviewed]
References:
Comments:
0 Commit comments 0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
Add another comment

r617:f062e467ef5c - - 10 files changed: 42 inserted, 63 deleted

@@ -1,111 +1,117
1 1 class AnnouncementsController < ApplicationController
2 2
3 3 before_filter :admin_authorization
4 4
5 5 in_place_edit_for :announcement, :published
6 6
7 7 # GET /announcements
8 8 # GET /announcements.xml
9 9 def index
10 10 @announcements = Announcement.find(:all,
11 11 :order => "created_at DESC")
12 12
13 13 respond_to do |format|
14 14 format.html # index.html.erb
15 15 format.xml { render :xml => @announcements }
16 16 end
17 17 end
18 18
19 19 # GET /announcements/1
20 20 # GET /announcements/1.xml
21 21 def show
22 22 @announcement = Announcement.find(params[:id])
23 23
24 24 respond_to do |format|
25 25 format.html # show.html.erb
26 26 format.xml { render :xml => @announcement }
27 27 end
28 28 end
29 29
30 30 # GET /announcements/new
31 31 # GET /announcements/new.xml
32 32 def new
33 33 @announcement = Announcement.new
34 34
35 35 respond_to do |format|
36 36 format.html # new.html.erb
37 37 format.xml { render :xml => @announcement }
38 38 end
39 39 end
40 40
41 41 # GET /announcements/1/edit
42 42 def edit
43 43 @announcement = Announcement.find(params[:id])
44 44 end
45 45
46 46 # POST /announcements
47 47 # POST /announcements.xml
48 48 def create
49 49 @announcement = Announcement.new(params[:announcement])
50 50
51 51 respond_to do |format|
52 52 if @announcement.save
53 53 flash[:notice] = 'Announcement was successfully created.'
54 54 format.html { redirect_to(@announcement) }
55 55 format.xml { render :xml => @announcement, :status => :created, :location => @announcement }
56 56 else
57 57 format.html { render :action => "new" }
58 58 format.xml { render :xml => @announcement.errors, :status => :unprocessable_entity }
59 59 end
60 60 end
61 61 end
62 62
63 63 # PUT /announcements/1
64 64 # PUT /announcements/1.xml
65 65 def update
66 66 @announcement = Announcement.find(params[:id])
67 67
68 68 respond_to do |format|
69 - if @announcement.update_attributes(params[:announcement])
69 + if @announcement.update_attributes(announcement_params)
70 70 flash[:notice] = 'Announcement was successfully updated.'
71 71 format.html { redirect_to(@announcement) }
72 72 format.js {}
73 73 format.xml { head :ok }
74 74 else
75 75 format.html { render :action => "edit" }
76 76 format.js {}
77 77 format.xml { render :xml => @announcement.errors, :status => :unprocessable_entity }
78 78 end
79 79 end
80 80 end
81 81
82 82 def toggle
83 83 @announcement = Announcement.find(params[:id])
84 84 @announcement.update_attributes( published: !@announcement.published? )
85 85 respond_to do |format|
86 86 format.js { render partial: 'toggle_button',
87 87 locals: {button_id: "#announcement_toggle_#{@announcement.id}",button_on: @announcement.published? } }
88 88 end
89 89 end
90 90
91 91 def toggle_front
92 92 @announcement = Announcement.find(params[:id])
93 93 @announcement.update_attributes( frontpage: !@announcement.frontpage? )
94 94 respond_to do |format|
95 95 format.js { render partial: 'toggle_button',
96 96 locals: {button_id: "#announcement_toggle_front_#{@announcement.id}",button_on: @announcement.frontpage? } }
97 97 end
98 98 end
99 99
100 100 # DELETE /announcements/1
101 101 # DELETE /announcements/1.xml
102 102 def destroy
103 103 @announcement = Announcement.find(params[:id])
104 104 @announcement.destroy
105 105
106 106 respond_to do |format|
107 107 format.html { redirect_to(announcements_url) }
108 108 format.xml { head :ok }
109 109 end
110 110 end
111 +
112 + private
113 +
114 + def announcement_params
115 + params.require(:announcement).permit(:author, :body, :published, :frontpage, :contest_only,:title, :note)
111 116 end
117 + end
@@ -1,30 +1,35
1 1 class ConfigurationsController < ApplicationController
2 2
3 3 before_filter :authenticate
4 4 before_filter { |controller| controller.authorization_by_roles(['admin'])}
5 5
6 6
7 7 def index
8 8 @configurations = GraderConfiguration.find(:all,
9 9 :order => '`key`')
10 10 @group = GraderConfiguration.pluck("grader_configurations.key").map{ |x| x[0...(x.index('.'))] }.uniq.sort
11 11 end
12 12
13 13 def reload
14 14 GraderConfiguration.reload
15 15 redirect_to :action => 'index'
16 16 end
17 17
18 18 def update
19 19 @config = GraderConfiguration.find(params[:id])
20 20 User.clear_last_login if @config.key == GraderConfiguration::MULTIPLE_IP_LOGIN_KEY and @config.value == 'true' and params[:grader_configuration][:value] == 'false'
21 21 respond_to do |format|
22 - if @config.update_attributes(params[:grader_configuration])
22 + if @config.update_attributes(configuration_params)
23 23 format.json { head :ok }
24 24 else
25 25 format.json { respond_with_bip(@config) }
26 26 end
27 27 end
28 28 end
29 29
30 + private
31 + def configuration_params
32 + params.require(:grader_configuration).permit(:key,:value_type,:value,:description)
30 33 end
34 +
35 + end
@@ -1,92 +1,98
1 1 class ContestsController < ApplicationController
2 2
3 3 before_filter :admin_authorization
4 4
5 5 in_place_edit_for :contest, :title
6 6 in_place_edit_for :contest, :enabled
7 7
8 8 # GET /contests
9 9 # GET /contests.xml
10 10 def index
11 11 @contests = Contest.all
12 12
13 13 respond_to do |format|
14 14 format.html # index.html.erb
15 15 format.xml { render :xml => @contests }
16 16 end
17 17 end
18 18
19 19 # GET /contests/1
20 20 # GET /contests/1.xml
21 21 def show
22 22 @contest = Contest.find(params[:id])
23 23
24 24 respond_to do |format|
25 25 format.html # show.html.erb
26 26 format.xml { render :xml => @contest }
27 27 end
28 28 end
29 29
30 30 # GET /contests/new
31 31 # GET /contests/new.xml
32 32 def new
33 33 @contest = Contest.new
34 34
35 35 respond_to do |format|
36 36 format.html # new.html.erb
37 37 format.xml { render :xml => @contest }
38 38 end
39 39 end
40 40
41 41 # GET /contests/1/edit
42 42 def edit
43 43 @contest = Contest.find(params[:id])
44 44 end
45 45
46 46 # POST /contests
47 47 # POST /contests.xml
48 48 def create
49 49 @contest = Contest.new(params[:contest])
50 50
51 51 respond_to do |format|
52 52 if @contest.save
53 53 flash[:notice] = 'Contest was successfully created.'
54 54 format.html { redirect_to(@contest) }
55 55 format.xml { render :xml => @contest, :status => :created, :location => @contest }
56 56 else
57 57 format.html { render :action => "new" }
58 58 format.xml { render :xml => @contest.errors, :status => :unprocessable_entity }
59 59 end
60 60 end
61 61 end
62 62
63 63 # PUT /contests/1
64 64 # PUT /contests/1.xml
65 65 def update
66 66 @contest = Contest.find(params[:id])
67 67
68 68 respond_to do |format|
69 - if @contest.update_attributes(params[:contest])
69 + if @contest.update_attributes(contests_params)
70 70 flash[:notice] = 'Contest was successfully updated.'
71 71 format.html { redirect_to(@contest) }
72 72 format.xml { head :ok }
73 73 else
74 74 format.html { render :action => "edit" }
75 75 format.xml { render :xml => @contest.errors, :status => :unprocessable_entity }
76 76 end
77 77 end
78 78 end
79 79
80 80 # DELETE /contests/1
81 81 # DELETE /contests/1.xml
82 82 def destroy
83 83 @contest = Contest.find(params[:id])
84 84 @contest.destroy
85 85
86 86 respond_to do |format|
87 87 format.html { redirect_to(contests_url) }
88 88 format.xml { head :ok }
89 89 end
90 90 end
91 91
92 + private
93 +
94 + def contests_params
95 + params.require(:contest).permit(:title,:enabled,:name)
92 96 end
97 +
98 + end
@@ -1,62 +1,67
1 1 class SiteController < ApplicationController
2 2
3 3 before_filter :site_admin_authorization, :except => 'login'
4 4
5 5 def login
6 6 # Site administrator login
7 7 @countries = Country.find(:all, :include => :sites)
8 8 @country_select = @countries.collect { |c| [c.name, c.id] }
9 9
10 10 @country_select_with_all = [['Any',0]]
11 11 @countries.each do |country|
12 12 @country_select_with_all << [country.name, country.id]
13 13 end
14 14
15 15 @site_select = []
16 16 @countries.each do |country|
17 17 country.sites.each do |site|
18 18 @site_select << ["#{site.name}, #{country.name}", site.id]
19 19 end
20 20 end
21 21
22 22 @default_site = Site.first if !GraderConfiguration['contest.multisites']
23 23
24 24 render :action => 'login', :layout => 'empty'
25 25 end
26 26
27 27 def index
28 28 if @site.started
29 29 render :action => 'started', :layout => 'empty'
30 30 else
31 31 render :action => 'prompt', :layout => 'empty'
32 32 end
33 33 end
34 34
35 35 def start
36 36 @site.started = true
37 37 @site.start_time = Time.new.gmtime
38 38 @site.save
39 39 redirect_to :action => 'index'
40 40 end
41 41
42 42 def logout
43 43 reset_session
44 44 redirect_to :controller => 'main', :action => 'login'
45 45 end
46 46
47 47 protected
48 48 def site_admin_authorization
49 49 if session[:site_id]==nil
50 50 redirect_to :controller => 'site', :action => 'login' and return
51 51 end
52 52 begin
53 53 @site = Site.find(session[:site_id], :include => :country)
54 54 rescue ActiveRecord::RecordNotFound
55 55 @site = nil
56 56 end
57 57 if @site==nil
58 58 redirect_to :controller => 'site', :action => 'login' and return
59 59 end
60 60 end
61 61
62 + private
63 + def site_params
64 + params.require(:site).permit()
62 65 end
66 +
67 + end
@@ -1,91 +1,97
1 1 class SitesController < ApplicationController
2 2
3 3 before_filter :admin_authorization
4 4
5 5 # GET /sites
6 6 # GET /sites.xml
7 7 def index
8 8 @sites = Site.find(:all, :order => 'country_id')
9 9
10 10 respond_to do |format|
11 11 format.html # index.html.erb
12 12 format.xml { render :xml => @sites }
13 13 end
14 14 end
15 15
16 16 # GET /sites/1
17 17 # GET /sites/1.xml
18 18 def show
19 19 @site = Site.find(params[:id])
20 20
21 21 respond_to do |format|
22 22 format.html # show.html.erb
23 23 format.xml { render :xml => @site }
24 24 end
25 25 end
26 26
27 27 # GET /sites/new
28 28 # GET /sites/new.xml
29 29 def new
30 30 @site = Site.new
31 31
32 32 respond_to do |format|
33 33 format.html # new.html.erb
34 34 format.xml { render :xml => @site }
35 35 end
36 36 end
37 37
38 38 # GET /sites/1/edit
39 39 def edit
40 40 @site = Site.find(params[:id])
41 41 end
42 42
43 43 # POST /sites
44 44 # POST /sites.xml
45 45 def create
46 46 @site = Site.new(params[:site])
47 47 @site.clear_start_time_if_not_started
48 48
49 49 respond_to do |format|
50 50 if @site.save
51 51 flash[:notice] = 'Site was successfully created.'
52 52 format.html { redirect_to(@site) }
53 53 format.xml { render :xml => @site, :status => :created, :location => @site }
54 54 else
55 55 format.html { render :action => "new" }
56 56 format.xml { render :xml => @site.errors, :status => :unprocessable_entity }
57 57 end
58 58 end
59 59 end
60 60
61 61 # PUT /sites/1
62 62 # PUT /sites/1.xml
63 63 def update
64 64 @site = Site.find(params[:id])
65 65 @site.clear_start_time_if_not_started
66 66
67 67 respond_to do |format|
68 - if @site.update_attributes(params[:site])
68 + if @site.update_attributes(site_params)
69 69 flash[:notice] = 'Site was successfully updated.'
70 70 format.html { redirect_to(@site) }
71 71 format.xml { head :ok }
72 72 else
73 73 format.html { render :action => "edit" }
74 74 format.xml { render :xml => @site.errors, :status => :unprocessable_entity }
75 75 end
76 76 end
77 77 end
78 78
79 79 # DELETE /sites/1
80 80 # DELETE /sites/1.xml
81 81 def destroy
82 82 @site = Site.find(params[:id])
83 83 @site.destroy
84 84
85 85 respond_to do |format|
86 86 format.html { redirect_to(sites_url) }
87 87 format.xml { head :ok }
88 88 end
89 89 end
90 90
91 + private
92 +
93 + def site_params
94 + params.require(:site).permit(:name,:started,:start_time,:country_id,:password)
91 95 end
96 +
97 + end
@@ -1,137 +1,83
1 1 class SubmissionsController < ApplicationController
2 2 before_filter :authenticate
3 3 before_filter :submission_authorization, only: [:show, :direct_edit_submission]
4 4
5 5 # GET /submissions
6 6 # GET /submissions.json
7 7 # Show problem selection and user's submission of that problem
8 8 def index
9 9 @user = @current_user
10 10 @problems = @user.available_problems
11 11
12 12 if params[:problem_id]==nil
13 13 @problem = nil
14 14 @submissions = nil
15 15 else
16 16 @problem = Problem.find_by_id(params[:problem_id])
17 17 if (@problem == nil) or (not @problem.available)
18 18 redirect_to main_list_path
19 19 flash[:notice] = 'Error: submissions for that problem are not viewable.'
20 20 return
21 21 end
22 22 @submissions = Submission.find_all_by_user_problem(@user.id, @problem.id)
23 23 end
24 24 end
25 25
26 26 # GET /submissions/1
27 27 # GET /submissions/1.json
28 28 def show
29 29 @submission = Submission.find(params[:id])
30 30
31 31 #log the viewing
32 32 user = User.find(session[:user_id])
33 33 SubmissionViewLog.create(user_id: session[:user_id],submission_id: @submission.id) unless user.admin?
34 34 end
35 35
36 36 #on-site new submission on specific problem
37 37 def direct_edit_problem
38 38 @problem = Problem.find(params[:problem_id])
39 39 @source = ''
40 40 render 'edit'
41 41 end
42 42
43 43 # GET /submissions/1/edit
44 44 def edit
45 45 @submission = Submission.find(params[:id])
46 46 @source = @submission.source.to_s
47 47 @problem = @submission.problem
48 48 @lang_id = @submission.language.id
49 49 end
50 50
51 51
52 52 def get_latest_submission_status
53 53 @problem = Problem.find(params[:pid])
54 54 @submission = Submission.find_last_by_user_and_problem(params[:uid],params[:pid])
55 55 puts User.find(params[:uid]).login
56 56 puts Problem.find(params[:pid]).name
57 57 puts 'nil' unless @submission
58 58 respond_to do |format|
59 59 format.js
60 60 end
61 61 end
62 62
63 - # # GET /submissions/new
64 - # # GET /submissions/new.json
65 - # def new
66 - # @submission = Submission.new
67 - #
68 - # respond_to do |format|
69 - # format.html # new.html.erb
70 - # format.json { render json: @submission }
71 - # end
72 - # end
73 - #
74 - #
75 - # # POST /submissions
76 - # # POST /submissions.json
77 - # def create
78 - # @submission = Submission.new(params[:submission])
79 - #
80 - # respond_to do |format|
81 - # if @submission.save
82 - # format.html { redirect_to @submission, notice: 'Submission was successfully created.' }
83 - # format.json { render json: @submission, status: :created, location: @submission }
84 - # else
85 - # format.html { render action: "new" }
86 - # format.json { render json: @submission.errors, status: :unprocessable_entity }
87 - # end
88 - # end
89 - # end
90 - #
91 - # # PUT /submissions/1
92 - # # PUT /submissions/1.json
93 - # def update
94 - # @submission = Submission.find(params[:id])
95 - #
96 - # respond_to do |format|
97 - # if @submission.update_attributes(params[:submission])
98 - # format.html { redirect_to @submission, notice: 'Submission was successfully updated.' }
99 - # format.json { head :no_content }
100 - # else
101 - # format.html { render action: "edit" }
102 - # format.json { render json: @submission.errors, status: :unprocessable_entity }
103 - # end
104 - # end
105 - # end
106 - #
107 - # # DELETE /submissions/1
108 - # # DELETE /submissions/1.json
109 - # def destroy
110 - # @submission = Submission.find(params[:id])
111 - # @submission.destroy
112 - #
113 - # respond_to do |format|
114 - # format.html { redirect_to submissions_url }
115 - # format.json { head :no_content }
116 - # end
117 - # end
118 63
119 64 protected
120 65 def submission_authorization
121 66 #admin always has privileged
122 67 if @current_user.admin?
123 68 return true
124 69 end
125 70
126 71 sub = Submission.find(params[:id])
127 72 if sub.problem.available?
128 73 puts "sub = #{sub.user.id}, current = #{@current_user.id}"
129 74 return true if GraderConfiguration["right.user_view_submission"] or sub.user == @current_user
130 75 end
131 76
132 77 #default to NO
133 78 unauthorized_redirect
134 79 return false
135 80 end
136 81
82 +
137 83 end
@@ -1,313 +1,313
1 1 require 'csv'
2 2
3 3 class UserAdminController < ApplicationController
4 4
5 5 include MailHelperMethods
6 6
7 7 before_filter :admin_authorization
8 8
9 9 # GETs should be safe (see http://www.w3.org/2001/tag/doc/whenToUseGet.html)
10 10 verify :method => :post, :only => [
11 11 :create, :create_from_list,
12 12 :update,
13 13 :manage_contest,
14 14 :bulk_mail
15 15 ],
16 16 :redirect_to => { :action => :list }
17 17
18 18 def index
19 19 @user_count = User.count
20 20 if params[:page] == 'all'
21 21 @users = User.all
22 22 @paginated = false
23 23 else
24 24 @users = User.paginate :page => params[:page]
25 25 @paginated = true
26 26 end
27 27 @hidden_columns = ['hashed_password', 'salt', 'created_at', 'updated_at']
28 28 @contests = Contest.enabled
29 29 end
30 30
31 31 def active
32 32 sessions = ActiveRecord::SessionStore::Session.find(:all, :conditions => ["updated_at >= ?", 60.minutes.ago])
33 33 @users = []
34 34 sessions.each do |session|
35 35 if session.data[:user_id]
36 36 @users << User.find(session.data[:user_id])
37 37 end
38 38 end
39 39 end
40 40
41 41 def show
42 42 @user = User.find(params[:id])
43 43 end
44 44
45 45 def new
46 46 @user = User.new
47 47 end
48 48
49 49 def create
50 50 @user = User.new(params[:user])
51 51 @user.activated = true
52 52 if @user.save
53 53 flash[:notice] = 'User was successfully created.'
54 54 redirect_to :action => 'index'
55 55 else
56 56 render :action => 'new'
57 57 end
58 58 end
59 59
60 60 def clear_last_ip
61 61 @user = User.find(params[:id])
62 62 @user.last_ip = nil
63 63 @user.save
64 64 redirect_to action: 'index', page: params[:page]
65 65 end
66 66
67 67 def create_from_list
68 68 lines = params[:user_list]
69 69
70 70 note = []
71 71
72 72 lines.split("\n").each do |line|
73 73 items = line.chomp.split(',')
74 74 if items.length>=2
75 75 login = items[0]
76 76 full_name = items[1]
77 77
78 78 added_random_password = false
79 79 if items.length>=3
80 80 password = items[2].chomp(" ")
81 81 user_alias = (items.length>=4) ? items[3] : login
82 82 else
83 83 password = random_password
84 84 user_alias = (items.length>=4) ? items[3] : login
85 85 added_random_password = true
86 86 end
87 87
88 88 user = User.find_by_login(login)
89 89 if (user)
90 90 user.full_name = full_name
91 91 user.password = password
92 92 else
93 93 user = User.new({:login => login,
94 94 :full_name => full_name,
95 95 :password => password,
96 96 :password_confirmation => password,
97 97 :alias => user_alias})
98 98 end
99 99 user.activated = true
100 100 user.save
101 101
102 102 if added_random_password
103 103 note << "'#{login}' (+)"
104 104 else
105 105 note << login
106 106 end
107 107 end
108 108 end
109 109 flash[:notice] = 'User(s) ' + note.join(', ') +
110 110 ' were successfully created. ' +
111 111 '( (+) - created with random passwords.)'
112 112 redirect_to :action => 'index'
113 113 end
114 114
115 115 def edit
116 116 @user = User.find(params[:id])
117 117 end
118 118
119 119 def update
120 120 @user = User.find(params[:id])
121 - if @user.update_attributes(params[:user])
121 + if @user.update_attributes(user_params)
122 122 flash[:notice] = 'User was successfully updated.'
123 123 redirect_to :action => 'show', :id => @user
124 124 else
125 125 render :action => 'edit'
126 126 end
127 127 end
128 128
129 129 def destroy
130 130 User.find(params[:id]).destroy
131 131 redirect_to :action => 'index'
132 132 end
133 133
134 134 def user_stat
135 135 if params[:commit] == 'download csv'
136 136 @problems = Problem.all
137 137 else
138 138 @problems = Problem.find_available_problems
139 139 end
140 140 @users = User.includes(:contests, :contest_stat).where(enabled: true) #find(:all, :include => [:contests, :contest_stat]).where(enabled: true)
141 141 @scorearray = Array.new
142 142 @users.each do |u|
143 143 ustat = Array.new
144 144 ustat[0] = u
145 145 @problems.each do |p|
146 146 sub = Submission.find_last_by_user_and_problem(u.id,p.id)
147 147 if (sub!=nil) and (sub.points!=nil) and p and p.full_score
148 148 ustat << [(sub.points.to_f*100/p.full_score).round, (sub.points>=p.full_score)]
149 149 else
150 150 ustat << [0,false]
151 151 end
152 152 end
153 153 @scorearray << ustat
154 154 end
155 155 if params[:commit] == 'download csv' then
156 156 csv = gen_csv_from_scorearray(@scorearray,@problems)
157 157 send_data csv, filename: 'last_score.csv'
158 158 else
159 159 render template: 'user_admin/user_stat'
160 160 end
161 161 end
162 162
163 163 def user_stat_max
164 164 if params[:commit] == 'download csv'
165 165 @problems = Problem.all
166 166 else
167 167 @problems = Problem.find_available_problems
168 168 end
169 169 @users = User.find(:all, :include => [:contests, :contest_stat])
170 170 @scorearray = Array.new
171 171 #set up range from param
172 172 since_id = params.fetch(:since_id, 0).to_i
173 173 until_id = params.fetch(:until_id, 0).to_i
174 174 @users.each do |u|
175 175 ustat = Array.new
176 176 ustat[0] = u
177 177 @problems.each do |p|
178 178 max_points = 0
179 179 Submission.find_in_range_by_user_and_problem(u.id,p.id,since_id,until_id).each do |sub|
180 180 max_points = sub.points if sub and sub.points and (sub.points > max_points)
181 181 end
182 182 ustat << [(max_points.to_f*100/p.full_score).round, (max_points>=p.full_score)]
183 183 end
184 184 @scorearray << ustat
185 185 end
186 186
187 187 if params[:commit] == 'download csv' then
188 188 csv = gen_csv_from_scorearray(@scorearray,@problems)
189 189 send_data csv, filename: 'max_score.csv'
190 190 else
191 191 render template: 'user_admin/user_stat'
192 192 end
193 193 end
194 194
195 195 def import
196 196 if params[:file]==''
197 197 flash[:notice] = 'Error importing no file'
198 198 redirect_to :action => 'index' and return
199 199 end
200 200 import_from_file(params[:file])
201 201 end
202 202
203 203 def random_all_passwords
204 204 users = User.find(:all)
205 205 @prefix = params[:prefix] || ''
206 206 @non_admin_users = User.find_non_admin_with_prefix(@prefix)
207 207 @changed = false
208 208 if request.request_method == 'POST'
209 209 @non_admin_users.each do |user|
210 210 password = random_password
211 211 user.password = password
212 212 user.password_confirmation = password
213 213 user.save
214 214 end
215 215 @changed = true
216 216 end
217 217 end
218 218
219 219 # contest management
220 220
221 221 def contests
222 222 @contest, @users = find_contest_and_user_from_contest_id(params[:id])
223 223 @contests = Contest.enabled
224 224 end
225 225
226 226 def assign_from_list
227 227 contest_id = params[:users_contest_id]
228 228 org_contest, users = find_contest_and_user_from_contest_id(contest_id)
229 229 contest = Contest.find(params[:new_contest][:id])
230 230 if !contest
231 231 flash[:notice] = 'Error: no contest'
232 232 redirect_to :action => 'contests', :id =>contest_id
233 233 end
234 234
235 235 note = []
236 236 users.each do |u|
237 237 u.contests = [contest]
238 238 note << u.login
239 239 end
240 240 flash[:notice] = 'User(s) ' + note.join(', ') +
241 241 " were successfully reassigned to #{contest.title}."
242 242 redirect_to :action => 'contests', :id =>contest.id
243 243 end
244 244
245 245 def add_to_contest
246 246 user = User.find(params[:id])
247 247 contest = Contest.find(params[:contest_id])
248 248 if user and contest
249 249 user.contests << contest
250 250 end
251 251 redirect_to :action => 'index'
252 252 end
253 253
254 254 def remove_from_contest
255 255 user = User.find(params[:id])
256 256 contest = Contest.find(params[:contest_id])
257 257 if user and contest
258 258 user.contests.delete(contest)
259 259 end
260 260 redirect_to :action => 'index'
261 261 end
262 262
263 263 def contest_management
264 264 end
265 265
266 266 def manage_contest
267 267 contest = Contest.find(params[:contest][:id])
268 268 if !contest
269 269 flash[:notice] = 'You did not choose the contest.'
270 270 redirect_to :action => 'contest_management' and return
271 271 end
272 272
273 273 operation = params[:operation]
274 274
275 275 if not ['add','remove','assign'].include? operation
276 276 flash[:notice] = 'You did not choose the operation to perform.'
277 277 redirect_to :action => 'contest_management' and return
278 278 end
279 279
280 280 lines = params[:login_list]
281 281 if !lines or lines.blank?
282 282 flash[:notice] = 'You entered an empty list.'
283 283 redirect_to :action => 'contest_management' and return
284 284 end
285 285
286 286 note = []
287 287 users = []
288 288 lines.split("\n").each do |line|
289 289 user = User.find_by_login(line.chomp)
290 290 if user
291 291 if operation=='add'
292 292 if ! user.contests.include? contest
293 293 user.contests << contest
294 294 end
295 295 elsif operation=='remove'
296 296 user.contests.delete(contest)
297 297 else
298 298 user.contests = [contest]
299 299 end
300 300
301 301 if params[:reset_timer]
302 302 user.contest_stat.forced_logout = true
303 303 user.contest_stat.reset_timer_and_save
304 304 end
305 305
306 306 if params[:notification_emails]
307 307 send_contest_update_notification_email(user, contest)
308 308 end
309 309
310 310 note << user.login
311 311 users << user
312 312 end
313 313 end
@@ -346,193 +346,198
346 346 flash[:notice] = 'Unknown user'
347 347 redirect_to :action => 'admin' and return
348 348 elsif user.login == 'root'
349 349 flash[:notice] = 'You cannot revoke admisnistrator permission from root.'
350 350 redirect_to :action => 'admin' and return
351 351 end
352 352
353 353 admin_role = Role.find_by_name('admin')
354 354 user.roles.delete(admin_role)
355 355 flash[:notice] = 'User permission revoked'
356 356 redirect_to :action => 'admin'
357 357 end
358 358
359 359 # mass mailing
360 360
361 361 def mass_mailing
362 362 end
363 363
364 364 def bulk_mail
365 365 lines = params[:login_list]
366 366 if !lines or lines.blank?
367 367 flash[:notice] = 'You entered an empty list.'
368 368 redirect_to :action => 'mass_mailing' and return
369 369 end
370 370
371 371 mail_subject = params[:subject]
372 372 if !mail_subject or mail_subject.blank?
373 373 flash[:notice] = 'You entered an empty mail subject.'
374 374 redirect_to :action => 'mass_mailing' and return
375 375 end
376 376
377 377 mail_body = params[:email_body]
378 378 if !mail_body or mail_body.blank?
379 379 flash[:notice] = 'You entered an empty mail body.'
380 380 redirect_to :action => 'mass_mailing' and return
381 381 end
382 382
383 383 note = []
384 384 users = []
385 385 lines.split("\n").each do |line|
386 386 user = User.find_by_login(line.chomp)
387 387 if user
388 388 send_mail(user.email, mail_subject, mail_body)
389 389 note << user.login
390 390 end
391 391 end
392 392
393 393 flash[:notice] = 'User(s) ' + note.join(', ') +
394 394 ' were successfully modified. '
395 395 redirect_to :action => 'mass_mailing'
396 396 end
397 397
398 398 protected
399 399
400 400 def random_password(length=5)
401 401 chars = 'abcdefghijkmnopqrstuvwxyz23456789'
402 402 newpass = ""
403 403 length.times { newpass << chars[rand(chars.size-1)] }
404 404 return newpass
405 405 end
406 406
407 407 def import_from_file(f)
408 408 data_hash = YAML.load(f)
409 409 @import_log = ""
410 410
411 411 country_data = data_hash[:countries]
412 412 site_data = data_hash[:sites]
413 413 user_data = data_hash[:users]
414 414
415 415 # import country
416 416 countries = {}
417 417 country_data.each_pair do |id,country|
418 418 c = Country.find_by_name(country[:name])
419 419 if c!=nil
420 420 countries[id] = c
421 421 @import_log << "Found #{country[:name]}\n"
422 422 else
423 423 countries[id] = Country.new(:name => country[:name])
424 424 countries[id].save
425 425 @import_log << "Created #{country[:name]}\n"
426 426 end
427 427 end
428 428
429 429 # import sites
430 430 sites = {}
431 431 site_data.each_pair do |id,site|
432 432 s = Site.find_by_name(site[:name])
433 433 if s!=nil
434 434 @import_log << "Found #{site[:name]}\n"
435 435 else
436 436 s = Site.new(:name => site[:name])
437 437 @import_log << "Created #{site[:name]}\n"
438 438 end
439 439 s.password = site[:password]
440 440 s.country = countries[site[:country_id]]
441 441 s.save
442 442 sites[id] = s
443 443 end
444 444
445 445 # import users
446 446 user_data.each_pair do |id,user|
447 447 u = User.find_by_login(user[:login])
448 448 if u!=nil
449 449 @import_log << "Found #{user[:login]}\n"
450 450 else
451 451 u = User.new(:login => user[:login])
452 452 @import_log << "Created #{user[:login]}\n"
453 453 end
454 454 u.full_name = user[:name]
455 455 u.password = user[:password]
456 456 u.country = countries[user[:country_id]]
457 457 u.site = sites[user[:site_id]]
458 458 u.activated = true
459 459 u.email = "empty-#{u.login}@none.com"
460 460 if not u.save
461 461 @import_log << "Errors\n"
462 462 u.errors.each { |attr,msg| @import_log << "#{attr} - #{msg}\n" }
463 463 end
464 464 end
465 465
466 466 end
467 467
468 468 def logout_users(users)
469 469 users.each do |user|
470 470 contest_stat = user.contest_stat(true)
471 471 if contest_stat and !contest_stat.forced_logout
472 472 contest_stat.forced_logout = true
473 473 contest_stat.save
474 474 end
475 475 end
476 476 end
477 477
478 478 def send_contest_update_notification_email(user, contest)
479 479 contest_title_name = GraderConfiguration['contest.name']
480 480 contest_name = contest.name
481 481 mail_subject = t('contest.notification.email_subject', {
482 482 :contest_title_name => contest_title_name,
483 483 :contest_name => contest_name })
484 484 mail_body = t('contest.notification.email_body', {
485 485 :full_name => user.full_name,
486 486 :contest_title_name => contest_title_name,
487 487 :contest_name => contest.name,
488 488 })
489 489
490 490 logger.info mail_body
491 491 send_mail(user.email, mail_subject, mail_body)
492 492 end
493 493
494 494 def find_contest_and_user_from_contest_id(id)
495 495 if id!='none'
496 496 @contest = Contest.find(id)
497 497 else
498 498 @contest = nil
499 499 end
500 500 if @contest
501 501 @users = @contest.users
502 502 else
503 503 @users = User.find_users_with_no_contest
504 504 end
505 505 return [@contest, @users]
506 506 end
507 507
508 508 def gen_csv_from_scorearray(scorearray,problem)
509 509 CSV.generate do |csv|
510 510 #add header
511 511 header = ['User','Name', 'Activated?', 'Logged in', 'Contest']
512 512 problem.each { |p| header << p.name }
513 513 header += ['Total','Passed']
514 514 csv << header
515 515 #add data
516 516 scorearray.each do |sc|
517 517 total = num_passed = 0
518 518 row = Array.new
519 519 sc.each_index do |i|
520 520 if i == 0
521 521 row << sc[i].login
522 522 row << sc[i].full_name
523 523 row << sc[i].activated
524 524 row << (sc[i].try(:contest_stat).try(:started_at).nil? ? 'no' : 'yes')
525 525 row << sc[i].contests.collect {|c| c.name}.join(', ')
526 526 else
527 527 row << sc[i][0]
528 528 total += sc[i][0]
529 529 num_passed += 1 if sc[i][1]
530 530 end
531 531 end
532 532 row << total
533 533 row << num_passed
534 534 csv << row
535 535 end
536 536 end
537 537 end
538 +
539 + private
540 + def user_params
541 + params.require(:user).permit(:login,:full_name,:hashed_password,:salt,:alias,:email,:site_id,:country_id,:activated,:enabled,:remark,:last_ip,:section)
538 542 end
543 + end
@@ -1,226 +1,226
1 1 require 'digest/sha1'
2 2 require 'net/pop'
3 3 require 'net/https'
4 4 require 'net/http'
5 5 require 'json'
6 6
7 7 class User < ActiveRecord::Base
8 8
9 9 has_and_belongs_to_many :roles
10 10
11 11 has_many :test_requests, :order => "submitted_at DESC"
12 12
13 13 has_many :messages,
14 14 :class_name => "Message",
15 15 :foreign_key => "sender_id",
16 16 :order => 'created_at DESC'
17 17
18 18 has_many :replied_messages,
19 19 :class_name => "Message",
20 20 :foreign_key => "receiver_id",
21 21 :order => 'created_at DESC'
22 22
23 23 has_one :contest_stat, :class_name => "UserContestStat", :dependent => :destroy
24 24
25 25 belongs_to :site
26 26 belongs_to :country
27 27
28 28 has_and_belongs_to_many :contests, :uniq => true, :order => 'name'
29 29
30 30 scope :activated_users, :conditions => {:activated => true}
31 31
32 32 validates_presence_of :login
33 33 validates_uniqueness_of :login
34 - validates_format_of :login, :with => /^[\_A-Za-z0-9]+$/
34 + validates_format_of :login, :with => /\A[\_A-Za-z0-9]+\z/
35 35 validates_length_of :login, :within => 3..30
36 36
37 37 validates_presence_of :full_name
38 38 validates_length_of :full_name, :minimum => 1
39 39
40 40 validates_presence_of :password, :if => :password_required?
41 41 validates_length_of :password, :within => 4..20, :if => :password_required?
42 42 validates_confirmation_of :password, :if => :password_required?
43 43
44 44 validates_format_of :email,
45 45 :with => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i,
46 46 :if => :email_validation?
47 47 validate :uniqueness_of_email_from_activated_users,
48 48 :if => :email_validation?
49 49 validate :enough_time_interval_between_same_email_registrations,
50 50 :if => :email_validation?
51 51
52 52 # these are for ytopc
53 53 # disable for now
54 54 #validates_presence_of :province
55 55
56 56 attr_accessor :password
57 57
58 58 before_save :encrypt_new_password
59 59 before_save :assign_default_site
60 60 before_save :assign_default_contest
61 61
62 62 # this is for will_paginate
63 63 cattr_reader :per_page
64 64 @@per_page = 50
65 65
66 66 def self.authenticate(login, password)
67 67 user = find_by_login(login)
68 68 if user
69 69 return user if user.authenticated?(password)
70 70 if user.authenticated_by_cucas?(password) or user.authenticated_by_pop3?(password)
71 71 user.password = password
72 72 user.save
73 73 return user
74 74 end
75 75 end
76 76 end
77 77
78 78 def authenticated?(password)
79 79 if self.activated
80 80 hashed_password == User.encrypt(password,self.salt)
81 81 else
82 82 false
83 83 end
84 84 end
85 85
86 86 def authenticated_by_pop3?(password)
87 87 Net::POP3.enable_ssl
88 88 pop = Net::POP3.new('pops.it.chula.ac.th')
89 89 authen = true
90 90 begin
91 91 pop.start(login, password)
92 92 pop.finish
93 93 return true
94 94 rescue
95 95 return false
96 96 end
97 97 end
98 98
99 99 def authenticated_by_cucas?(password)
100 100 url = URI.parse('https://www.cas.chula.ac.th/cas/api/?q=studentAuthenticate')
101 101 appid = '41508763e340d5858c00f8c1a0f5a2bb'
102 102 appsecret ='d9cbb5863091dbe186fded85722a1e31'
103 103 post_args = {
104 104 'appid' => appid,
105 105 'appsecret' => appsecret,
106 106 'username' => login,
107 107 'password' => password
108 108 }
109 109
110 110 #simple call
111 111 begin
112 112 http = Net::HTTP.new('www.cas.chula.ac.th', 443)
113 113 http.use_ssl = true
114 114 http.verify_mode = OpenSSL::SSL::VERIFY_NONE
115 115 result = [ ]
116 116 http.start do |http|
117 117 req = Net::HTTP::Post.new('/cas/api/?q=studentAuthenticate')
118 118 param = "appid=#{appid}&appsecret=#{appsecret}&username=#{login}&password=#{password}"
119 119 resp = http.request(req,param)
120 120 result = JSON.parse resp.body
121 121 end
122 122 return true if result["type"] == "beanStudent"
123 123 rescue => e
124 124 return false
125 125 end
126 126 return false
127 127 end
128 128
129 129 def admin?
130 130 self.roles.detect {|r| r.name == 'admin' }
131 131 end
132 132
133 133 def email_for_editing
134 134 if self.email==nil
135 135 "(unknown)"
136 136 elsif self.email==''
137 137 "(blank)"
138 138 else
139 139 self.email
140 140 end
141 141 end
142 142
143 143 def email_for_editing=(e)
144 144 self.email=e
145 145 end
146 146
147 147 def alias_for_editing
148 148 if self.alias==nil
149 149 "(unknown)"
150 150 elsif self.alias==''
151 151 "(blank)"
152 152 else
153 153 self.alias
154 154 end
155 155 end
156 156
157 157 def alias_for_editing=(e)
158 158 self.alias=e
159 159 end
160 160
161 161 def activation_key
162 162 if self.hashed_password==nil
163 163 encrypt_new_password
164 164 end
165 165 Digest::SHA1.hexdigest(self.hashed_password)[0..7]
166 166 end
167 167
168 168 def verify_activation_key(key)
169 169 key == activation_key
170 170 end
171 171
172 172 def self.random_password(length=5)
173 173 chars = 'abcdefghjkmnopqrstuvwxyz'
174 174 password = ''
175 175 length.times { password << chars[rand(chars.length - 1)] }
176 176 password
177 177 end
178 178
179 179 def self.find_non_admin_with_prefix(prefix='')
180 180 users = User.find(:all)
181 181 return users.find_all { |u| !(u.admin?) and u.login.index(prefix)==0 }
182 182 end
183 183
184 184 # Contest information
185 185
186 186 def self.find_users_with_no_contest()
187 187 users = User.find(:all)
188 188 return users.find_all { |u| u.contests.length == 0 }
189 189 end
190 190
191 191
192 192 def contest_time_left
193 193 if GraderConfiguration.contest_mode?
194 194 return nil if site==nil
195 195 return site.time_left
196 196 elsif GraderConfiguration.indv_contest_mode?
197 197 time_limit = GraderConfiguration.contest_time_limit
198 198 if time_limit == nil
199 199 return nil
200 200 end
201 201 if contest_stat==nil or contest_stat.started_at==nil
202 202 return (Time.now.gmtime + time_limit) - Time.now.gmtime
203 203 else
204 204 finish_time = contest_stat.started_at + time_limit
205 205 current_time = Time.now.gmtime
206 206 if current_time > finish_time
207 207 return 0
208 208 else
209 209 return finish_time - current_time
210 210 end
211 211 end
212 212 else
213 213 return nil
214 214 end
215 215 end
216 216
217 217 def contest_finished?
218 218 if GraderConfiguration.contest_mode?
219 219 return false if site==nil
220 220 return site.finished?
221 221 elsif GraderConfiguration.indv_contest_mode?
222 222 return false if self.contest_stat(true)==nil
223 223 return contest_time_left == 0
224 224 else
225 225 return false
226 226 end
@@ -1,42 +1,42
1 1 CafeGrader::Application.configure do
2 2 # Settings specified here will take precedence over those in config/application.rb
3 3
4 4 # In the development environment your application's code is reloaded on
5 5 # every request. This slows down response time but is perfect for development
6 6 # since you don't have to restart the web server when you make code changes.
7 7 config.cache_classes = false
8 8
9 9 # Log error messages when you accidentally call methods on nil. //DEPRICATED
10 10 # config.whiny_nils = true // DEPRICATED
11 11
12 12 # Show full error reports and disable caching
13 13 config.consider_all_requests_local = true
14 14 config.action_controller.perform_caching = false
15 15
16 16 # Don't care if the mailer can't send
17 17 config.action_mailer.raise_delivery_errors = false
18 18
19 19 # Print deprecation notices to the Rails logger
20 20 config.active_support.deprecation = :log
21 21
22 22 # Only use best-standards-support built into browsers
23 23 config.action_dispatch.best_standards_support = :builtin
24 24
25 25 # Raise exception on mass assignment protection for Active Record models
26 - config.active_record.mass_assignment_sanitizer = :strict
26 + # config.active_record.mass_assignment_sanitizer = :strict //DEPRICATED
27 27
28 28 # Log the query plan for queries taking more than this (works // DEPRICATED
29 29 # with SQLite, MySQL, and PostgreSQL) // DEPRICATED
30 30 # config.active_record.auto_explain_threshold_in_seconds = 0.5 // DEPRICATED
31 31
32 32 # Do not compress assets
33 33 config.assets.compress = false
34 34
35 35 # Expands the lines which load the assets
36 36 config.assets.debug = true
37 37
38 38 # Prevents assets from rendering twice
39 39 config.serve_static_assets = true
40 40
41 41 config.eager_load = false
42 42 end
@@ -1,39 +1,39
1 1 CafeGrader::Application.configure do
2 2 # Settings specified here will take precedence over those in config/application.rb
3 3
4 4 # The test environment is used exclusively to run your application's
5 5 # test suite. You never need to work with it otherwise. Remember that
6 6 # your test database is "scratch space" for the test suite and is wiped
7 7 # and recreated between test runs. Don't rely on the data there!
8 8 config.cache_classes = true
9 9
10 10 # Configure static asset server for tests with Cache-Control for performance
11 11 config.serve_static_assets = true
12 12 config.static_cache_control = "public, max-age=3600"
13 13
14 14 # Log error messages when you accidentally call methods on nil
15 15 config.whiny_nils = true
16 16
17 17 # Show full error reports and disable caching
18 18 config.consider_all_requests_local = true
19 19 config.action_controller.perform_caching = false
20 20
21 21 # Raise exceptions instead of rendering exception templates
22 22 config.action_dispatch.show_exceptions = false
23 23
24 24 # Disable request forgery protection in test environment
25 25 config.action_controller.allow_forgery_protection = false
26 26
27 27 # Tell Action Mailer not to deliver emails to the real world.
28 28 # The :test delivery method accumulates sent emails in the
29 29 # ActionMailer::Base.deliveries array.
30 30 config.action_mailer.delivery_method = :test
31 31
32 32 # Raise exception on mass assignment protection for Active Record models
33 - config.active_record.mass_assignment_sanitizer = :strict
33 + #config.active_record.mass_assignment_sanitizer = :strict // DEPRICATED
34 34
35 35 # Print deprecation notices to the stderr
36 36 config.active_support.deprecation = :stderr
37 37
38 38 config.eager_load = false
39 39 end
You need to be logged in to leave comments. Login now