Description:
merge with algo-bm, take cheat report
Commit status:
[Not Reviewed]
References:
merge java
Comments:
0 Commit comments 0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
Add another comment

r526:f7b4a30e2f5d - - 12 files changed: 252 inserted, 6 deleted

@@ -0,0 +1,77
1 + - content_for :header do
2 + = stylesheet_link_tag 'tablesorter-theme.cafe'
3 + = javascript_include_tag 'local_jquery'
4 +
5 + %script{:type=>"text/javascript"}
6 + $(function () {
7 + $('#since_datetime').datetimepicker({ showButtonPanel: true, dateFormat: "yy-mm-dd", controlType: "slider"} );
8 + $('#until_datetime').datetimepicker({ showButtonPanel: true, dateFormat: "yy-mm-dd", controlType: "slider"} );
9 + $('#my_table').tablesorter({widthFixed: true, widgets: ['zebra']});
10 + $('#my_table2').tablesorter({widthFixed: true, widgets: ['zebra']});
11 + $('#sub_table').tablesorter({widthFixed: true, widgets: ['zebra']});
12 + });
13 +
14 + %h1 Login status
15 +
16 + =render partial: 'report_menu'
17 + =render partial: 'date_range', locals: {param_text: 'Login date range:', title: 'Query login stat in the range' }
18 +
19 + %h2 Suspect
20 +
21 + %table.tablesorter-cafe#my_table
22 + %thead
23 + %tr
24 + %th login
25 + %th full name
26 + %th login count
27 + %tbody
28 + - @ml.each do |l|
29 + %tr{class: cycle('info-even','info-odd')}
30 + %td= link_to l[:login], controller: 'users', action: 'profile', id: l[:id]
31 + %td= l[:full_name]
32 + %td= l[:count]
33 +
34 +
35 + %h2 Multiple Logins Report
36 + This section reports all logins record that have either multiple ip per login or multiple login per ip.
37 +
38 + %table.tablesorter-cafe#my_table2
39 + %thead
40 + %tr
41 + %th login
42 + %th full name
43 + %th IP
44 + %th time
45 + %tbody
46 + - @mld.each do |l|
47 + %tr{class: cycle('info-even','info-odd')}
48 + %td= link_to l.user[:login], controller: 'users', action: 'profile', id: l[:user_id]
49 + %td= l.user[:full_name]
50 + %td= l[:ip_address]
51 + %td= l[:created_at]
52 +
53 + %h2 Multiple IP Submissions Report
54 + This section reports all submission records that have USER_ID matchs ID that logins on multiple IP
55 + and that have IP_ADDRESS that has multiple ID logins
56 +
57 + Be noted that when submission IP address is not available, this might exclude
58 + submissions that come from ID that login on multiple-login IP
59 +
60 + %table.tablesorter-cafe#sub_table
61 + %thead
62 + %tr
63 + %th login
64 + %th full name
65 + %th IP
66 + %th problem
67 + %th Submission
68 + %th time
69 + %tbody
70 + - @subs.each do |s|
71 + %tr{class: cycle('info-even','info-odd')}
72 + %td= link_to s.user[:login], controller: 'users', action: 'profile', id: s[:user_id]
73 + %td= s.user[:full_name]
74 + %td= s[:ip_address]
75 + %td= s.problem.name
76 + %td= link_to(s.id, controller: 'graders' , action: 'submission', id: s.id)
77 + %td= s[:submitted_at]
@@ -0,0 +1,9
1 + class ChangeUseridOnLogin < ActiveRecord::Migration
2 + def up
3 + change_column :logins, :user_id, :integer
4 + end
5 +
6 + def down
7 + change_column :logins, :user_id, :string
8 + end
9 + end
@@ -1,16 +1,17
1 class ApplicationController < ActionController::Base
1 class ApplicationController < ActionController::Base
2 protect_from_forgery
2 protect_from_forgery
3
3
4 SINGLE_USER_MODE_CONF_KEY = 'system.single_user_mode'
4 SINGLE_USER_MODE_CONF_KEY = 'system.single_user_mode'
5 + MULTIPLE_IP_LOGIN_CONF_KEY = 'right.multiple_ip_login'
5
6
6 def admin_authorization
7 def admin_authorization
7 return false unless authenticate
8 return false unless authenticate
8 user = User.find(session[:user_id], :include => ['roles'])
9 user = User.find(session[:user_id], :include => ['roles'])
9 unless user.admin?
10 unless user.admin?
10 flash[:notice] = 'You are not authorized to view the page you requested'
11 flash[:notice] = 'You are not authorized to view the page you requested'
11 redirect_to :controller => 'main', :action => 'login' unless user.admin?
12 redirect_to :controller => 'main', :action => 'login' unless user.admin?
12 return false
13 return false
13 end
14 end
14 return true
15 return true
15 end
16 end
16
17
@@ -52,24 +53,41
52 return true if user.admin?
53 return true if user.admin?
53 begin
54 begin
54 if user.contest_stat(true).forced_logout
55 if user.contest_stat(true).forced_logout
55 flash[:notice] = 'You have been automatically logged out.'
56 flash[:notice] = 'You have been automatically logged out.'
56 redirect_to :controller => 'main', :action => 'index'
57 redirect_to :controller => 'main', :action => 'index'
57 end
58 end
58 rescue
59 rescue
59 end
60 end
60 end
61 end
61 return true
62 return true
62 end
63 end
63
64
65 + def authenticate_by_ip_address
66 + #this assume that we have already authenticate normally
67 + unless GraderConfiguration[MULTIPLE_IP_LOGIN_CONF_KEY]
68 + user = User.find(session[:user_id])
69 + if (not user.admin? and user.last_ip and user.last_ip != request.remote_ip)
70 + flash[:notice] = "You cannot use the system from #{request.remote_ip}. Your last ip is #{user.last_ip}"
71 + redirect_to :controller => 'main', :action => 'login'
72 + return false
73 + end
74 + unless user.last_ip
75 + user.last_ip = request.remote_ip
76 + user.save
77 + end
78 + end
79 + return true
80 + end
81 +
64 def authorization
82 def authorization
65 return false unless authenticate
83 return false unless authenticate
66 user = User.find(session[:user_id])
84 user = User.find(session[:user_id])
67 unless user.roles.detect { |role|
85 unless user.roles.detect { |role|
68 role.rights.detect{ |right|
86 role.rights.detect{ |right|
69 right.controller == self.class.controller_name and
87 right.controller == self.class.controller_name and
70 (right.action == 'all' or right.action == action_name)
88 (right.action == 'all' or right.action == action_name)
71 }
89 }
72 }
90 }
73 flash[:notice] = 'You are not authorized to view the page you requested'
91 flash[:notice] = 'You are not authorized to view the page you requested'
74 #request.env['HTTP_REFERER'] ? (redirect_to :back) : (redirect_to :controller => 'login')
92 #request.env['HTTP_REFERER'] ? (redirect_to :back) : (redirect_to :controller => 'login')
75 redirect_to :controller => 'main', :action => 'login'
93 redirect_to :controller => 'main', :action => 'login'
@@ -7,22 +7,23
7 def index
7 def index
8 @configurations = GraderConfiguration.find(:all,
8 @configurations = GraderConfiguration.find(:all,
9 :order => '`key`')
9 :order => '`key`')
10 end
10 end
11
11
12 def reload
12 def reload
13 GraderConfiguration.reload
13 GraderConfiguration.reload
14 redirect_to :action => 'index'
14 redirect_to :action => 'index'
15 end
15 end
16
16
17 def update
17 def update
18 @config = GraderConfiguration.find(params[:id])
18 @config = GraderConfiguration.find(params[:id])
19 + User.clear_last_login if @config.key = 'multiple_ip_login' and @config.value == 'true' and params[:grader_configuration][:value] == 'false'
19 respond_to do |format|
20 respond_to do |format|
20 if @config.update_attributes(params[:grader_configuration])
21 if @config.update_attributes(params[:grader_configuration])
21 format.json { head :ok }
22 format.json { head :ok }
22 else
23 else
23 format.json { respond_with_bip(@config) }
24 format.json { respond_with_bip(@config) }
24 end
25 end
25 end
26 end
26 end
27 end
27
28
28 end
29 end
@@ -4,24 +4,26
4 before_filter :check_viewability, :except => [:index, :login]
4 before_filter :check_viewability, :except => [:index, :login]
5
5
6 append_before_filter :confirm_and_update_start_time,
6 append_before_filter :confirm_and_update_start_time,
7 :except => [:index,
7 :except => [:index,
8 :login,
8 :login,
9 :confirm_contest_start]
9 :confirm_contest_start]
10
10
11 # to prevent log in box to be shown when user logged out of the
11 # to prevent log in box to be shown when user logged out of the
12 # system only in some tab
12 # system only in some tab
13 prepend_before_filter :reject_announcement_refresh_when_logged_out,
13 prepend_before_filter :reject_announcement_refresh_when_logged_out,
14 :only => [:announcements]
14 :only => [:announcements]
15
15
16 + before_filter :authenticate_by_ip_address, :only => [:list]
17 +
16 # COMMENTED OUT: filter in each action instead
18 # COMMENTED OUT: filter in each action instead
17 # before_filter :verify_time_limit, :only => [:submit]
19 # before_filter :verify_time_limit, :only => [:submit]
18
20
19 verify :method => :post, :only => [:submit],
21 verify :method => :post, :only => [:submit],
20 :redirect_to => { :action => :index }
22 :redirect_to => { :action => :index }
21
23
22 # COMMENT OUT: only need when having high load
24 # COMMENT OUT: only need when having high load
23 # caches_action :index, :login
25 # caches_action :index, :login
24
26
25 # NOTE: This method is not actually needed, 'config/routes.rb' has
27 # NOTE: This method is not actually needed, 'config/routes.rb' has
26 # assigned action login as a default action.
28 # assigned action login as a default action.
27 def index
29 def index
@@ -1,15 +1,16
1 class ReportController < ApplicationController
1 class ReportController < ApplicationController
2
2
3 - before_filter :admin_authorization, only: [:login_stat,:submission_stat, :stuck]
3 + before_filter :admin_authorization, only: [:login_stat,:submission_stat, :stuck, :cheat_report, :cheat_scruntinize]
4 +
4 before_filter(only: [:problem_hof]) { |c|
5 before_filter(only: [:problem_hof]) { |c|
5 return false unless authenticate
6 return false unless authenticate
6
7
7 if GraderConfiguration["right.user_view_submission"]
8 if GraderConfiguration["right.user_view_submission"]
8 return true;
9 return true;
9 end
10 end
10
11
11 admin_authorization
12 admin_authorization
12 }
13 }
13
14
14 def login_stat
15 def login_stat
15 @logins = Array.new
16 @logins = Array.new
@@ -243,13 +244,136
243 if last != r.ip_address
244 if last != r.ip_address
244 count = 1
245 count = 1
245 last = r.ip_address
246 last = r.ip_address
246 first = r
247 first = r
247 else
248 else
248 @ip << first if count == 1
249 @ip << first if count == 1
249 @ip << r
250 @ip << r
250 count += 1
251 count += 1
251 end
252 end
252 end
253 end
253 end
254 end
254
255
256 + def cheat_report
257 + date_and_time = '%Y-%m-%d %H:%M'
258 + begin
259 + md = params[:since_datetime].match(/(\d+)-(\d+)-(\d+) (\d+):(\d+)/)
260 + @since_time = Time.zone.local(md[1].to_i,md[2].to_i,md[3].to_i,md[4].to_i,md[5].to_i)
261 + rescue
262 + @since_time = Time.zone.now.ago( 90.minutes)
255 end
263 end
264 + begin
265 + md = params[:until_datetime].match(/(\d+)-(\d+)-(\d+) (\d+):(\d+)/)
266 + @until_time = Time.zone.local(md[1].to_i,md[2].to_i,md[3].to_i,md[4].to_i,md[5].to_i)
267 + rescue
268 + @until_time = Time.zone.now
269 + end
270 +
271 + #multi login
272 + @ml = Login.joins(:user).where("logins.created_at >= ? and logins.created_at <= ?",@since_time,@until_time).select('users.login,count(distinct ip_address) as count,users.full_name').group("users.id").having("count > 1")
273 +
274 + st = <<-SQL
275 + SELECT l2.*
276 + FROM logins l2 INNER JOIN
277 + (SELECT u.id,COUNT(DISTINCT ip_address) as count,u.login,u.full_name
278 + FROM logins l
279 + INNER JOIN users u ON l.user_id = u.id
280 + WHERE l.created_at >= '#{@since_time.in_time_zone("UTC")}' and l.created_at <= '#{@until_time.in_time_zone("UTC")}'
281 + GROUP BY u.id
282 + HAVING count > 1
283 + ) ml ON l2.user_id = ml.id
284 + WHERE l2.created_at >= '#{@since_time.in_time_zone("UTC")}' and l2.created_at <= '#{@until_time.in_time_zone("UTC")}'
285 + UNION
286 + SELECT l2.*
287 + FROM logins l2 INNER JOIN
288 + (SELECT l.ip_address,COUNT(DISTINCT u.id) as count
289 + FROM logins l
290 + INNER JOIN users u ON l.user_id = u.id
291 + WHERE l.created_at >= '#{@since_time.in_time_zone("UTC")}' and l.created_at <= '#{@until_time.in_time_zone("UTC")}'
292 + GROUP BY l.ip_address
293 + HAVING count > 1
294 + ) ml on ml.ip_address = l2.ip_address
295 + INNER JOIN users u ON l2.user_id = u.id
296 + WHERE l2.created_at >= '#{@since_time.in_time_zone("UTC")}' and l2.created_at <= '#{@until_time.in_time_zone("UTC")}'
297 + ORDER BY ip_address,created_at
298 + SQL
299 + @mld = Login.find_by_sql(st)
300 +
301 + st = <<-SQL
302 + SELECT s.id,s.user_id,s.ip_address,s.submitted_at,s.problem_id
303 + FROM submissions s INNER JOIN
304 + (SELECT u.id,COUNT(DISTINCT ip_address) as count,u.login,u.full_name
305 + FROM logins l
306 + INNER JOIN users u ON l.user_id = u.id
307 + WHERE l.created_at >= ? and l.created_at <= ?
308 + GROUP BY u.id
309 + HAVING count > 1
310 + ) ml ON s.user_id = ml.id
311 + WHERE s.submitted_at >= ? and s.submitted_at <= ?
312 + UNION
313 + SELECT s.id,s.user_id,s.ip_address,s.submitted_at,s.problem_id
314 + FROM submissions s INNER JOIN
315 + (SELECT l.ip_address,COUNT(DISTINCT u.id) as count
316 + FROM logins l
317 + INNER JOIN users u ON l.user_id = u.id
318 + WHERE l.created_at >= ? and l.created_at <= ?
319 + GROUP BY l.ip_address
320 + HAVING count > 1
321 + ) ml on ml.ip_address = s.ip_address
322 + WHERE s.submitted_at >= ? and s.submitted_at <= ?
323 + ORDER BY ip_address,submitted_at
324 + SQL
325 + @subs = Submission.joins(:problem).find_by_sql([st,@since_time,@until_time,
326 + @since_time,@until_time,
327 + @since_time,@until_time,
328 + @since_time,@until_time])
329 +
330 + end
331 +
332 + def cheat_scruntinize
333 + #convert date & time
334 + date_and_time = '%Y-%m-%d %H:%M'
335 + begin
336 + md = params[:since_datetime].match(/(\d+)-(\d+)-(\d+) (\d+):(\d+)/)
337 + @since_time = Time.zone.local(md[1].to_i,md[2].to_i,md[3].to_i,md[4].to_i,md[5].to_i)
338 + rescue
339 + @since_time = Time.zone.now.ago( 90.minutes)
340 + end
341 + begin
342 + md = params[:until_datetime].match(/(\d+)-(\d+)-(\d+) (\d+):(\d+)/)
343 + @until_time = Time.zone.local(md[1].to_i,md[2].to_i,md[3].to_i,md[4].to_i,md[5].to_i)
344 + rescue
345 + @until_time = Time.zone.now
346 + end
347 +
348 + #convert sid
349 + @sid = params[:SID].split(/[,\s]/) if params[:SID]
350 + unless @sid and @sid.size > 0
351 + return
352 + redirect_to actoin: :cheat_scruntinize
353 + flash[:notice] = 'Please enter at least 1 student id'
354 + end
355 + mark = Array.new(@sid.size,'?')
356 + condition = "(u.login = " + mark.join(' OR u.login = ') + ')'
357 +
358 + @st = <<-SQL
359 + SELECT l.created_at as submitted_at ,-1 as id,u.login,u.full_name,l.ip_address,"" as problem_id,"" as points,l.user_id
360 + FROM logins l INNER JOIN users u on l.user_id = u.id
361 + WHERE l.created_at >= ? AND l.created_at <= ? AND #{condition}
362 + UNION
363 + SELECT s.submitted_at,s.id,u.login,u.full_name,s.ip_address,s.problem_id,s.points,s.user_id
364 + FROM submissions s INNER JOIN users u ON s.user_id = u.id
365 + WHERE s.submitted_at >= ? AND s.submitted_at <= ? AND #{condition}
366 + ORDER BY submitted_at
367 + SQL
368 +
369 + p = [@st,@since_time,@until_time] + @sid + [@since_time,@until_time] + @sid
370 + @logs = Submission.joins(:problem).find_by_sql(p)
371 +
372 +
373 +
374 +
375 +
376 + end
377 +
378 +
379 + end
@@ -1,3 +1,5
1 class Login < ActiveRecord::Base
1 class Login < ActiveRecord::Base
2 + belongs_to :user
3 +
2 attr_accessible :ip_address, :logged_in_at, :user_id
4 attr_accessible :ip_address, :logged_in_at, :user_id
3 end
5 end
@@ -298,24 +298,28
298 return contest_problems + other_avaiable_problems
298 return contest_problems + other_avaiable_problems
299 end
299 end
300 end
300 end
301
301
302 def can_view_problem?(problem)
302 def can_view_problem?(problem)
303 if not GraderConfiguration.multicontests?
303 if not GraderConfiguration.multicontests?
304 return problem.available
304 return problem.available
305 else
305 else
306 return problem_in_user_contests? problem
306 return problem_in_user_contests? problem
307 end
307 end
308 end
308 end
309
309
310 + def self.clear_last_login
311 + User.update_all(:last_ip => nil)
312 + end
313 +
310 protected
314 protected
311 def encrypt_new_password
315 def encrypt_new_password
312 return if password.blank?
316 return if password.blank?
313 self.salt = (10+rand(90)).to_s
317 self.salt = (10+rand(90)).to_s
314 self.hashed_password = User.encrypt(self.password,self.salt)
318 self.hashed_password = User.encrypt(self.password,self.salt)
315 end
319 end
316
320
317 def assign_default_site
321 def assign_default_site
318 # have to catch error when migrating (because self.site is not available).
322 # have to catch error when migrating (because self.site is not available).
319 begin
323 begin
320 if self.site==nil
324 if self.site==nil
321 self.site = Site.find_by_name('default')
325 self.site = Site.find_by_name('default')
@@ -1,23 +1,23
1
1
2 = form_tag({session: :url }) do
2 = form_tag({session: :url }) do
3 .submitbox
3 .submitbox
4 %table
4 %table
5 %tr
5 %tr
6 %td{colspan: 6, style: 'font-weight: bold'}= title
6 %td{colspan: 6, style: 'font-weight: bold'}= title
7 %tr
7 %tr
8 %td{style: 'width: 120px; font-weight: bold'}= param_text
8 %td{style: 'width: 120px; font-weight: bold'}= param_text
9 %td{align: 'right'} since:
9 %td{align: 'right'} since:
10 - %td= text_field_tag 'since_datetime'
10 + %td= text_field_tag 'since_datetime', @since_time
11 %tr
11 %tr
12 %td
12 %td
13 %td{align: 'right'} until:
13 %td{align: 'right'} until:
14 - %td= text_field_tag 'until_datetime'
14 + %td= text_field_tag 'until_datetime', @until_time
15 %tr
15 %tr
16 %td
16 %td
17 %td
17 %td
18 %td Blank mean no condition
18 %td Blank mean no condition
19 %tr
19 %tr
20 %td
20 %td
21 %td
21 %td
22 %td= submit_tag 'query'
22 %td= submit_tag 'query'
23
23
@@ -1,8 +1,9
1
1
2 .task-menu
2 .task-menu
3 Reports
3 Reports
4 %br/
4 %br/
5 = link_to '[Hall of Fame]', :action => 'problem_hof'
5 = link_to '[Hall of Fame]', :action => 'problem_hof'
6 = link_to '[Struggle]', :action => 'stuck'
6 = link_to '[Struggle]', :action => 'stuck'
7 - = link_to '[Login]', :action => 'login_stat'
7 + = link_to '[Cheat Detection]', :action => 'cheat_report'
8 + = link_to '[Cheat Detail]', :action => 'cheat_scruntinize'
8 = link_to '[Multiple Login]', :action => 'multiple_login'
9 = link_to '[Multiple Login]', :action => 'multiple_login'
@@ -2,25 +2,25
2 # This file is auto-generated from the current state of the database. Instead
2 # This file is auto-generated from the current state of the database. Instead
3 # of editing this file, please use the migrations feature of Active Record to
3 # of editing this file, please use the migrations feature of Active Record to
4 # incrementally modify your database, and then regenerate this schema definition.
4 # incrementally modify your database, and then regenerate this schema definition.
5 #
5 #
6 # Note that this schema.rb definition is the authoritative source for your
6 # Note that this schema.rb definition is the authoritative source for your
7 # database schema. If you need to create the application database on another
7 # database schema. If you need to create the application database on another
8 # system, you should be using db:schema:load, not running all the migrations
8 # system, you should be using db:schema:load, not running all the migrations
9 # from scratch. The latter is a flawed and unsustainable approach (the more migrations
9 # from scratch. The latter is a flawed and unsustainable approach (the more migrations
10 # you'll amass, the slower it'll run and the greater likelihood for issues).
10 # you'll amass, the slower it'll run and the greater likelihood for issues).
11 #
11 #
12 # It's strongly recommended to check this file into your version control system.
12 # It's strongly recommended to check this file into your version control system.
13
13
14 - ActiveRecord::Schema.define(:version => 20150203153534) do
14 + ActiveRecord::Schema.define(:version => 20150618085823) do
15
15
16 create_table "announcements", :force => true do |t|
16 create_table "announcements", :force => true do |t|
17 t.string "author"
17 t.string "author"
18 t.text "body", :limit => 16777215
18 t.text "body", :limit => 16777215
19 t.boolean "published"
19 t.boolean "published"
20 t.datetime "created_at", :null => false
20 t.datetime "created_at", :null => false
21 t.datetime "updated_at", :null => false
21 t.datetime "updated_at", :null => false
22 t.boolean "frontpage", :default => false
22 t.boolean "frontpage", :default => false
23 t.boolean "contest_only", :default => false
23 t.boolean "contest_only", :default => false
24 t.string "title"
24 t.string "title"
25 t.string "notes"
25 t.string "notes"
26 end
26 end
@@ -78,25 +78,25
78 end
78 end
79
79
80 add_index "grader_processes", ["host", "pid"], :name => "index_grader_processes_on_ip_and_pid"
80 add_index "grader_processes", ["host", "pid"], :name => "index_grader_processes_on_ip_and_pid"
81
81
82 create_table "languages", :force => true do |t|
82 create_table "languages", :force => true do |t|
83 t.string "name", :limit => 10
83 t.string "name", :limit => 10
84 t.string "pretty_name"
84 t.string "pretty_name"
85 t.string "ext", :limit => 10
85 t.string "ext", :limit => 10
86 t.string "common_ext"
86 t.string "common_ext"
87 end
87 end
88
88
89 create_table "logins", :force => true do |t|
89 create_table "logins", :force => true do |t|
90 - t.string "user_id"
90 + t.integer "user_id"
91 t.string "ip_address"
91 t.string "ip_address"
92 t.datetime "created_at", :null => false
92 t.datetime "created_at", :null => false
93 t.datetime "updated_at", :null => false
93 t.datetime "updated_at", :null => false
94 end
94 end
95
95
96 create_table "messages", :force => true do |t|
96 create_table "messages", :force => true do |t|
97 t.integer "sender_id"
97 t.integer "sender_id"
98 t.integer "receiver_id"
98 t.integer "receiver_id"
99 t.integer "replying_message_id"
99 t.integer "replying_message_id"
100 t.text "body", :limit => 16777215
100 t.text "body", :limit => 16777215
101 t.boolean "replied"
101 t.boolean "replied"
102 t.datetime "created_at", :null => false
102 t.datetime "created_at", :null => false
@@ -233,17 +233,18
233 t.string "hashed_password"
233 t.string "hashed_password"
234 t.string "salt", :limit => 5
234 t.string "salt", :limit => 5
235 t.string "alias"
235 t.string "alias"
236 t.string "email"
236 t.string "email"
237 t.integer "site_id"
237 t.integer "site_id"
238 t.integer "country_id"
238 t.integer "country_id"
239 t.boolean "activated", :default => false
239 t.boolean "activated", :default => false
240 t.datetime "created_at"
240 t.datetime "created_at"
241 t.datetime "updated_at"
241 t.datetime "updated_at"
242 t.string "section"
242 t.string "section"
243 t.boolean "enabled", :default => true
243 t.boolean "enabled", :default => true
244 t.string "remark"
244 t.string "remark"
245 + t.string "last_ip"
245 end
246 end
246
247
247 add_index "users", ["login"], :name => "index_users_on_login", :unique => true
248 add_index "users", ["login"], :name => "index_users_on_login", :unique => true
248
249
249 end
250 end
@@ -52,24 +52,31
52 :default_value => 'false',
52 :default_value => 'false',
53 :description => 'If the server is in contest mode and this option is true, on the log in of the admin a menu for site selections is shown.'
53 :description => 'If the server is in contest mode and this option is true, on the log in of the admin a menu for site selections is shown.'
54 },
54 },
55
55
56 {
56 {
57 :key => 'right.user_hall_of_fame',
57 :key => 'right.user_hall_of_fame',
58 :value_type => 'boolean',
58 :value_type => 'boolean',
59 :default_value => 'false',
59 :default_value => 'false',
60 :description => 'If true, any user can access hall of fame page.'
60 :description => 'If true, any user can access hall of fame page.'
61 },
61 },
62
62
63 {
63 {
64 + :key => 'right.multiple_ip_login',
65 + :value_type => 'boolean',
66 + :default_value => 'true',
67 + :description => 'When change from true to false, a user can login from the first IP they logged into afterward.'
68 + },
69 +
70 + {
64 :key => 'right.user_view_submission',
71 :key => 'right.user_view_submission',
65 :value_type => 'boolean',
72 :value_type => 'boolean',
66 :default_value => 'false',
73 :default_value => 'false',
67 :description => 'If true, any user can view submissions of every one.'
74 :description => 'If true, any user can view submissions of every one.'
68 },
75 },
69
76
70 # If Configuration['system.online_registration'] is true, the
77 # If Configuration['system.online_registration'] is true, the
71 # system allows online registration, and will use these
78 # system allows online registration, and will use these
72 # information for sending confirmation emails.
79 # information for sending confirmation emails.
73 {
80 {
74 :key => 'system.online_registration.smtp',
81 :key => 'system.online_registration.smtp',
75 :value_type => 'string',
82 :value_type => 'string',
You need to be logged in to leave comments. Login now