# HG changeset patch # User Nattee Niparnan # Date 2017-06-17 05:49:44 # Node ID 50e8e6077bb9de59ce237d9955d4b333accde1fb # Parent 241769f05803825f5bd09abc6b443494966084cf # Parent 23fc3f2d9ad1b6518d830a04158a8a70a7649962 update master diff --git a/.gitignore b/.gitignore --- a/.gitignore +++ b/.gitignore @@ -31,3 +31,5 @@ #ignore rvm setting file .ruby-gemset .ruby-version + +/config/secrets.yml diff --git a/Gemfile b/Gemfile --- a/Gemfile +++ b/Gemfile @@ -1,27 +1,34 @@ source 'https://rubygems.org' -gem 'rails', '~>3.2' +#rails +gem 'rails', '~>4.2.0' +gem 'activerecord-session_store' -gem 'select2-rails' # Bundle edge Rails instead: # gem 'rails', :git => 'git://github.com/rails/rails.git' +#---------------- database --------------------- +#the database gem 'mysql2' +#for testing +gem 'sqlite3' +#for dumping database into yaml +gem 'yaml_db' # Gems used only for assets and not required # in production environments by default. -group :assets do - gem 'sass-rails', '~> 3.2.6' - gem 'coffee-rails', '~> 3.2.2' +gem 'sass-rails' +gem 'coffee-rails' # See https://github.com/sstephenson/execjs#readme for more supported runtimes # gem 'therubyracer', :platforms => :ruby - gem 'uglifier' -end +gem 'uglifier' -gem 'prototype-rails' +gem 'haml' +gem 'haml-rails' +# gem 'prototype-rails' # To use ActiveModel has_secure_password # gem 'bcrypt-ruby', '~> 3.0.0' @@ -44,7 +51,7 @@ # jquery addition gem 'jquery-rails' -gem 'jquery-ui-sass-rails' +gem 'jquery-ui-rails' gem 'jquery-timepicker-addon-rails' gem 'jquery-tablesorter' gem 'jquery-countdown-rails' @@ -62,19 +69,23 @@ gem 'momentjs-rails' gem 'rails_bootstrap_sortable' +#----------- user interface ----------------- +#select 2 +gem 'select2-rails' #ace editor gem 'ace-rails-ap' +#paginator +gem 'will_paginate', '~> 3.0.7' -gem 'haml' -gem 'haml-rails' gem 'mail' gem 'rdiscount' -gem 'test-unit' -gem 'will_paginate', '~> 3.0.7' gem 'dynamic_form' gem 'in_place_editing' gem 'verification', :git => 'https://github.com/sikachu/verification.git' -group :test, :development do - gem 'rspec-rails', '~> 2.99.0' -end + +#---------------- testiing ----------------------- +gem 'minitest-reporters' + +#---------------- for console -------------------- +gem 'fuzzy-string-match' diff --git a/Gemfile.lock b/Gemfile.lock --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,46 +1,63 @@ GIT remote: https://github.com/sikachu/verification.git - revision: 76eaf51b13276ecae54bd9cd115832595d2ff56d + revision: ff31697b940d7b0e2ec65f08764215c96104e76d specs: verification (1.0.3) - actionpack (>= 3.0.0, < 5.0) - activesupport (>= 3.0.0, < 5.0) + actionpack (>= 3.0.0, < 5.1) + activesupport (>= 3.0.0, < 5.1) GEM remote: https://rubygems.org/ specs: - ace-rails-ap (4.0.2) - actionmailer (3.2.22.5) - actionpack (= 3.2.22.5) - mail (~> 2.5.4) - actionpack (3.2.22.5) - activemodel (= 3.2.22.5) - activesupport (= 3.2.22.5) - builder (~> 3.0.0) + RubyInline (3.12.4) + ZenTest (~> 4.3) + ZenTest (4.11.1) + ace-rails-ap (4.1.1) + actionmailer (4.2.7.1) + actionpack (= 4.2.7.1) + actionview (= 4.2.7.1) + activejob (= 4.2.7.1) + mail (~> 2.5, >= 2.5.4) + rails-dom-testing (~> 1.0, >= 1.0.5) + actionpack (4.2.7.1) + actionview (= 4.2.7.1) + activesupport (= 4.2.7.1) + rack (~> 1.6) + rack-test (~> 0.6.2) + rails-dom-testing (~> 1.0, >= 1.0.5) + rails-html-sanitizer (~> 1.0, >= 1.0.2) + actionview (4.2.7.1) + activesupport (= 4.2.7.1) + builder (~> 3.1) erubis (~> 2.7.0) - journey (~> 1.0.4) - rack (~> 1.4.5) - rack-cache (~> 1.2) - rack-test (~> 0.6.1) - sprockets (~> 2.2.1) - activemodel (3.2.22.5) - activesupport (= 3.2.22.5) - builder (~> 3.0.0) - activerecord (3.2.22.5) - activemodel (= 3.2.22.5) - activesupport (= 3.2.22.5) - arel (~> 3.0.2) - tzinfo (~> 0.3.29) - activeresource (3.2.22.5) - activemodel (= 3.2.22.5) - activesupport (= 3.2.22.5) - activesupport (3.2.22.5) - i18n (~> 0.6, >= 0.6.4) - multi_json (~> 1.0) - arel (3.0.3) - autoprefixer-rails (6.0.3) + rails-dom-testing (~> 1.0, >= 1.0.5) + rails-html-sanitizer (~> 1.0, >= 1.0.2) + activejob (4.2.7.1) + activesupport (= 4.2.7.1) + globalid (>= 0.3.0) + activemodel (4.2.7.1) + activesupport (= 4.2.7.1) + builder (~> 3.1) + activerecord (4.2.7.1) + activemodel (= 4.2.7.1) + activesupport (= 4.2.7.1) + arel (~> 6.0) + activerecord-session_store (1.0.0) + actionpack (>= 4.0, < 5.1) + activerecord (>= 4.0, < 5.1) + multi_json (~> 1.11, >= 1.11.2) + rack (>= 1.5.2, < 3) + railties (>= 4.0, < 5.1) + activesupport (4.2.7.1) + i18n (~> 0.7) + json (~> 1.7, >= 1.7.7) + minitest (~> 5.1) + thread_safe (~> 0.3, >= 0.3.4) + tzinfo (~> 1.1) + ansi (1.5.0) + arel (6.0.4) + autoprefixer-rails (6.6.0) execjs - json best_in_place (3.0.3) actionpack (>= 3.2) railties (>= 3.2) @@ -48,138 +65,148 @@ sass (~> 3.2) bootstrap-switch-rails (3.3.3) bootstrap-toggle-rails (2.2.1.0) - builder (3.0.4) - coffee-rails (3.2.2) + builder (3.2.2) + coffee-rails (4.2.1) coffee-script (>= 2.2.0) - railties (~> 3.2.0) - coffee-script (2.3.0) + railties (>= 4.0.0, < 5.2.x) + coffee-script (2.4.1) coffee-script-source execjs - coffee-script-source (1.9.0) - diff-lcs (1.2.5) + coffee-script-source (1.12.2) + concurrent-ruby (1.0.4) dynamic_form (1.1.4) erubis (2.7.0) - execjs (2.3.0) - haml (4.0.6) + execjs (2.7.0) + fuzzy-string-match (1.0.0) + RubyInline (>= 3.8.6) + globalid (0.3.7) + activesupport (>= 4.1.0) + haml (4.0.7) tilt - haml-rails (0.4) - actionpack (>= 3.1, < 4.1) - activesupport (>= 3.1, < 4.1) - haml (>= 3.1, < 4.1) - railties (>= 3.1, < 4.1) - hike (1.2.3) + haml-rails (0.9.0) + actionpack (>= 4.0.1) + activesupport (>= 4.0.1) + haml (>= 4.0.6, < 5.0) + html2haml (>= 1.0.1) + railties (>= 4.0.1) + html2haml (2.0.0) + erubis (~> 2.7.0) + haml (~> 4.0.0) + nokogiri (~> 1.6.0) + ruby_parser (~> 3.5) i18n (0.7.0) in_place_editing (1.2.0) - journey (1.0.4) jquery-countdown-rails (2.0.2) - jquery-rails (3.1.2) - railties (>= 3.0, < 5.0) + jquery-rails (4.2.1) + rails-dom-testing (>= 1, < 3) + railties (>= 4.2.0) thor (>= 0.14, < 2.0) - jquery-tablesorter (1.13.4) - railties (>= 3.1, < 5) + jquery-tablesorter (1.23.3) + railties (>= 3.2, < 6) jquery-timepicker-addon-rails (1.4.1) railties (>= 3.1) - jquery-ui-rails (4.0.3) - jquery-rails - railties (>= 3.1.0) - jquery-ui-sass-rails (4.0.3.0) - jquery-rails - jquery-ui-rails (= 4.0.3) - railties (>= 3.1.0) + jquery-ui-rails (6.0.1) + railties (>= 3.2.16) json (1.8.3) - mail (2.5.4) - mime-types (~> 1.16) - treetop (~> 1.4.8) - mime-types (1.25.1) - momentjs-rails (2.11.1) + loofah (2.0.3) + nokogiri (>= 1.5.9) + mail (2.6.4) + mime-types (>= 1.16, < 4) + mime-types (3.1) + mime-types-data (~> 3.2015) + mime-types-data (3.2016.0521) + mini_portile2 (2.1.0) + minitest (5.10.1) + minitest-reporters (1.1.13) + ansi + builder + minitest (>= 5.0) + ruby-progressbar + momentjs-rails (2.15.1) railties (>= 3.1) multi_json (1.12.1) - mysql2 (0.3.20) - polyglot (0.3.5) - power_assert (0.2.2) - prototype-rails (3.2.1) - rails (~> 3.2) - rack (1.4.7) - rack-cache (1.6.1) - rack (>= 0.4) - rack-ssl (1.3.4) - rack + mysql2 (0.4.5) + nokogiri (1.6.8.1) + mini_portile2 (~> 2.1.0) + rack (1.6.5) rack-test (0.6.3) rack (>= 1.0) - rails (3.2.22.5) - actionmailer (= 3.2.22.5) - actionpack (= 3.2.22.5) - activerecord (= 3.2.22.5) - activeresource (= 3.2.22.5) - activesupport (= 3.2.22.5) - bundler (~> 1.0) - railties (= 3.2.22.5) - rails_bootstrap_sortable (2.0.0) - momentjs-rails (~> 2, >= 2.8.3) - railties (3.2.22.5) - actionpack (= 3.2.22.5) - activesupport (= 3.2.22.5) - rack-ssl (~> 1.3.2) + rails (4.2.7.1) + actionmailer (= 4.2.7.1) + actionpack (= 4.2.7.1) + actionview (= 4.2.7.1) + activejob (= 4.2.7.1) + activemodel (= 4.2.7.1) + activerecord (= 4.2.7.1) + activesupport (= 4.2.7.1) + bundler (>= 1.3.0, < 2.0) + railties (= 4.2.7.1) + sprockets-rails + rails-deprecated_sanitizer (1.0.3) + activesupport (>= 4.2.0.alpha) + rails-dom-testing (1.0.8) + activesupport (>= 4.2.0.beta, < 5.0) + nokogiri (~> 1.6) + rails-deprecated_sanitizer (>= 1.0.1) + rails-html-sanitizer (1.0.3) + loofah (~> 2.0) + rails_bootstrap_sortable (2.0.1) + momentjs-rails (>= 2.8.3) + railties (4.2.7.1) + actionpack (= 4.2.7.1) + activesupport (= 4.2.7.1) rake (>= 0.8.7) - rdoc (~> 3.4) - thor (>= 0.14.6, < 2.0) - rake (11.2.2) - rdiscount (2.1.8) - rdoc (3.12.2) - json (~> 1.4) - rouge (1.8.0) - rspec-collection_matchers (1.1.2) - rspec-expectations (>= 2.99.0.beta1) - rspec-core (2.99.2) - rspec-expectations (2.99.2) - diff-lcs (>= 1.1.3, < 2.0) - rspec-mocks (2.99.3) - rspec-rails (2.99.0) - actionpack (>= 3.0) - activemodel (>= 3.0) - activesupport (>= 3.0) - railties (>= 3.0) - rspec-collection_matchers - rspec-core (~> 2.99.0) - rspec-expectations (~> 2.99.0) - rspec-mocks (~> 2.99.0) - sass (3.4.11) - sass-rails (3.2.6) - railties (~> 3.2.0) - sass (>= 3.1.10) - tilt (~> 1.3) - select2-rails (4.0.1) + thor (>= 0.18.1, < 2.0) + rake (12.0.0) + rdiscount (2.2.0.1) + rouge (2.0.7) + ruby-progressbar (1.8.1) + ruby_parser (3.8.3) + sexp_processor (~> 4.1) + sass (3.4.23) + sass-rails (5.0.6) + railties (>= 4.0.0, < 6) + sass (~> 3.1) + sprockets (>= 2.8, < 4.0) + sprockets-rails (>= 2.0, < 4.0) + tilt (>= 1.1, < 3) + select2-rails (4.0.3) thor (~> 0.14) - sprockets (2.2.3) - hike (~> 1.2) - multi_json (~> 1.0) - rack (~> 1.0) - tilt (~> 1.1, != 1.3.0) - test-unit (3.0.9) - power_assert - thor (0.19.1) - tilt (1.4.1) - treetop (1.4.15) - polyglot - polyglot (>= 0.3.1) - tzinfo (0.3.51) - uglifier (2.7.0) - execjs (>= 0.3.0) - json (>= 1.8.0) - will_paginate (3.0.7) + sexp_processor (4.7.0) + sprockets (3.7.1) + concurrent-ruby (~> 1.0) + rack (> 1, < 3) + sprockets-rails (3.2.0) + actionpack (>= 4.0) + activesupport (>= 4.0) + sprockets (>= 3.0.0) + sqlite3 (1.3.12) + thor (0.19.4) + thread_safe (0.3.5) + tilt (2.0.5) + tzinfo (1.2.2) + thread_safe (~> 0.1) + uglifier (3.0.4) + execjs (>= 0.3.0, < 3) + will_paginate (3.0.12) + yaml_db (0.4.2) + rails (>= 3.0, < 5.1) + rake (>= 0.8.7) PLATFORMS ruby DEPENDENCIES ace-rails-ap + activerecord-session_store autoprefixer-rails best_in_place (~> 3.0.1) bootstrap-sass (~> 3.2.0) bootstrap-switch-rails bootstrap-toggle-rails - coffee-rails (~> 3.2.2) + coffee-rails dynamic_form + fuzzy-string-match haml haml-rails in_place_editing @@ -187,22 +214,22 @@ jquery-rails jquery-tablesorter jquery-timepicker-addon-rails - jquery-ui-sass-rails + jquery-ui-rails mail + minitest-reporters momentjs-rails mysql2 - prototype-rails - rails (~> 3.2) + rails (~> 4.2.0) rails_bootstrap_sortable rdiscount rouge - rspec-rails (~> 2.99.0) - sass-rails (~> 3.2.6) + sass-rails select2-rails - test-unit + sqlite3 uglifier verification! will_paginate (~> 3.0.7) + yaml_db BUNDLED WITH - 1.12.5 + 1.13.6 diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -12,7 +12,7 @@ // //= require jquery //= require jquery_ujs -//= require jquery.ui.all +//= require jquery-ui //= require bootstrap-sprockets //= require moment //= require bootstrap-sortable @@ -28,9 +28,6 @@ //= require custom //= require jquery.countdown //-------------- addition from local_jquery ----------- -//= require jquery.ui.datepicker -//= require jquery.ui.slider -//= require jquery-ui-timepicker-addon //= require jquery-tablesorter //= require best_in_place //= require best_in_place.jquery-ui diff --git a/app/assets/javascripts/local_jquery.js b/app/assets/javascripts/local_jquery.js --- a/app/assets/javascripts/local_jquery.js +++ b/app/assets/javascripts/local_jquery.js @@ -1,13 +1,3 @@ -//= require jquery -//= require jquery_ujs -//= require jquery.ui.all -//= require jquery.ui.datepicker -//= require jquery.ui.slider -//= require jquery-ui-timepicker-addon -//= require jquery-tablesorter -//= require best_in_place -//= require best_in_place.jquery-ui - $(document).ready(function() { /* Activating Best In Place */ jQuery(".best_in_place").best_in_place(); diff --git a/app/assets/stylesheets/application.css.scss b/app/assets/stylesheets/application.css.scss --- a/app/assets/stylesheets/application.css.scss +++ b/app/assets/stylesheets/application.css.scss @@ -14,11 +14,11 @@ * # *= require_self */ -@import "jquery.ui.all"; -@import "jquery.ui.core"; -@import "jquery.ui.theme"; -@import "jquery.ui.datepicker"; -@import "jquery.ui.slider"; +@import "jquery-ui"; +//@import "jquery.ui.core"; +//@import "jquery.ui.theme"; +//@import "jquery.ui.datepicker"; +//@import "jquery.ui.slider"; @import "jquery-ui-timepicker-addon"; @import "jquery-tablesorter/theme.metro-dark"; @import "jquery.countdown"; diff --git a/app/controllers/announcements_controller.rb b/app/controllers/announcements_controller.rb --- a/app/controllers/announcements_controller.rb +++ b/app/controllers/announcements_controller.rb @@ -7,8 +7,7 @@ # GET /announcements # GET /announcements.xml def index - @announcements = Announcement.find(:all, - :order => "created_at DESC") + @announcements = Announcement.order(created_at: :desc) respond_to do |format| format.html # index.html.erb @@ -46,7 +45,7 @@ # POST /announcements # POST /announcements.xml def create - @announcement = Announcement.new(params[:announcement]) + @announcement = Announcement.new(announcement_params) respond_to do |format| if @announcement.save @@ -66,7 +65,7 @@ @announcement = Announcement.find(params[:id]) respond_to do |format| - if @announcement.update_attributes(params[:announcement]) + if @announcement.update_attributes(announcement_params) flash[:notice] = 'Announcement was successfully updated.' format.html { redirect_to(@announcement) } format.js {} @@ -108,4 +107,10 @@ format.xml { head :ok } end end + + private + + def announcement_params + params.require(:announcement).permit(:author, :body, :published, :frontpage, :contest_only, :title) + end end diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -1,7 +1,7 @@ class ApplicationController < ActionController::Base protect_from_forgery - before_filter :current_user + before_filter :current_user SINGLE_USER_MODE_CONF_KEY = 'system.single_user_mode' MULTIPLE_IP_LOGIN_CONF_KEY = 'right.multiple_ip_login' @@ -20,7 +20,7 @@ def admin_authorization return false unless authenticate - user = User.find(session[:user_id], :include => ['roles']) + user = User.includes(:roles).find(session[:user_id]) unless user.admin? unauthorized_redirect return false @@ -37,6 +37,18 @@ end end + def testcase_authorization + #admin always has privileged + puts "haha" + if @current_user.admin? + return true + end + + puts "hehe" + puts GraderConfiguration["right.view_testcase"] + unauthorized_redirect unless GraderConfiguration["right.view_testcase"] + end + protected def authenticate @@ -101,10 +113,10 @@ return false unless authenticate user = User.find(session[:user_id]) unless user.roles.detect { |role| - role.rights.detect{ |right| - right.controller == self.class.controller_name and - (right.action == 'all' or right.action == action_name) - } + role.rights.detect{ |right| + right.controller == self.class.controller_name and + (right.action == 'all' or right.action == action_name) + } } flash[:notice] = 'You are not authorized to view the page you requested' #request.env['HTTP_REFERER'] ? (redirect_to :back) : (redirect_to :controller => 'login') diff --git a/app/controllers/configurations_controller.rb b/app/controllers/configurations_controller.rb --- a/app/controllers/configurations_controller.rb +++ b/app/controllers/configurations_controller.rb @@ -5,8 +5,8 @@ def index - @configurations = GraderConfiguration.find(:all, - :order => '`key`') + @configurations = GraderConfiguration.order(:key) + @group = GraderConfiguration.pluck("grader_configurations.key").map{ |x| x[0...(x.index('.'))] }.uniq.sort end def reload @@ -18,7 +18,7 @@ @config = GraderConfiguration.find(params[:id]) User.clear_last_login if @config.key == GraderConfiguration::MULTIPLE_IP_LOGIN_KEY and @config.value == 'true' and params[:grader_configuration][:value] == 'false' respond_to do |format| - if @config.update_attributes(params[:grader_configuration]) + if @config.update_attributes(configuration_params) format.json { head :ok } else format.json { respond_with_bip(@config) } @@ -26,4 +26,9 @@ end end +private + def configuration_params + params.require(:grader_configuration).permit(:key,:value_type,:value,:description) + end + end diff --git a/app/controllers/contest_management_controller.rb b/app/controllers/contest_management_controller.rb --- a/app/controllers/contest_management_controller.rb +++ b/app/controllers/contest_management_controller.rb @@ -11,9 +11,9 @@ redirect_to :action => 'index' and return end - @users = User.find(:all) + @users = User.all @start_times = {} - UserContestStat.find(:all).each do |stat| + UserContestStat.all.each do |stat| @start_times[stat.user_id] = stat.started_at end end diff --git a/app/controllers/contests_controller.rb b/app/controllers/contests_controller.rb --- a/app/controllers/contests_controller.rb +++ b/app/controllers/contests_controller.rb @@ -66,7 +66,7 @@ @contest = Contest.find(params[:id]) respond_to do |format| - if @contest.update_attributes(params[:contest]) + if @contest.update_attributes(contests_params) flash[:notice] = 'Contest was successfully updated.' format.html { redirect_to(@contest) } format.xml { head :ok } @@ -89,4 +89,10 @@ end end + private + + def contests_params + params.require(:contest).permit(:title,:enabled,:name) + end + end diff --git a/app/controllers/graders_controller.rb b/app/controllers/graders_controller.rb --- a/app/controllers/graders_controller.rb +++ b/app/controllers/graders_controller.rb @@ -35,10 +35,8 @@ @terminated_processes = GraderProcess.find_terminated_graders - @last_task = Task.find(:first, - :order => 'created_at DESC') - @last_test_request = TestRequest.find(:first, - :order => 'created_at DESC') + @last_task = Task.last + @last_test_request = TestRequest.last @submission = Submission.order("id desc").limit(20) @backlog_submission = Submission.where('graded_at is null') end @@ -57,7 +55,7 @@ end def clear_all - GraderProcess.find(:all).each do |p| + GraderProcess.all.each do |p| p.destroy end redirect_to :action => 'list' diff --git a/app/controllers/heartbeat_controller.rb b/app/controllers/heartbeat_controller.rb --- a/app/controllers/heartbeat_controller.rb +++ b/app/controllers/heartbeat_controller.rb @@ -2,11 +2,11 @@ before_filter :admin_authorization, :only => ['index'] def edit - @user = User.find_by_login(params[:id]) - unless @user - render text: "LOGIN_NOT_FOUND" - return - end + #@user = User.find_by_login(params[:id]) + #unless @user + # render text: "LOGIN_NOT_FOUND" + # return + #end #hb = HeartBeat.where(user_id: @user.id, ip_address: request.remote_ip).first #puts "status = #{params[:status]}" @@ -19,9 +19,24 @@ #else # HeartBeat.creae(user_id: @user.id, ip_address: request.remote_ip) #end - HeartBeat.create(user_id: @user.id, ip_address: request.remote_ip, status: params[:status]) + #HeartBeat.create(user_id: @user.id, ip_address: request.remote_ip, status: params[:status]) + + res = GraderConfiguration['right.heartbeat_response'] + res.strip! if res + full = GraderConfiguration['right.heartbeat_response_full'] + full.strip! if full - render text: (GraderConfiguration['right.heartbeat_response'] || 'OK') + if full and full != '' + l = Login.where(ip_address: request.remote_ip).last + @user = l.user + if @user.solve_all_available_problems? + render text: (full || 'OK') + else + render text: (res || 'OK') + end + else + render text: (GraderConfiguration['right.heartbeat_response'] || 'OK') + end end def index diff --git a/app/controllers/main_controller.rb b/app/controllers/main_controller.rb --- a/app/controllers/main_controller.rb +++ b/app/controllers/main_controller.rb @@ -45,7 +45,7 @@ # @hidelogin = true # end - @announcements = Announcement.find_for_frontpage + @announcements = Announcement.frontpage render :action => 'login', :layout => 'empty' end @@ -88,10 +88,10 @@ if @submission.valid? if @submission.save == false - flash[:notice] = 'Error saving your submission' + flash[:notice] = 'Error saving your submission' elsif Task.create(:submission_id => @submission.id, :status => Task::STATUS_INQUEUE) == false - flash[:notice] = 'Error adding your submission to task queue' + flash[:notice] = 'Error adding your submission to task queue' end else prepare_list_information @@ -106,7 +106,7 @@ (submission.problem != nil) and (submission.problem.available)) send_data(submission.source, - {:filename => submission.download_filename, + {:filename => submission.download_filename, :type => 'text/plain'}) else flash[:notice] = 'Error viewing source' @@ -124,23 +124,6 @@ end end - def submission - @user = User.find(session[:user_id]) - @problems = @user.available_problems - if params[:id]==nil - @problem = nil - @submissions = nil - else - @problem = Problem.find_by_id(params[:id]) - if (@problem == nil) or (not @problem.available) - redirect_to :action => 'list' - flash[:notice] = 'Error: submissions for that problem are not viewable.' - return - end - @submissions = Submission.find_all_by_user_problem(@user.id, @problem.id) - end - end - def result if !GraderConfiguration.show_grading_result redirect_to :action => 'list' and return @@ -217,9 +200,9 @@ def prepare_announcements(recent=nil) if GraderConfiguration.show_tasks_to?(@user) - @announcements = Announcement.find_published(true) + @announcements = Announcement.published(true) else - @announcements = Announcement.find_published + @announcements = Announcement.published end if recent!=nil recent_id = recent.to_i diff --git a/app/controllers/problems_controller.rb b/app/controllers/problems_controller.rb --- a/app/controllers/problems_controller.rb +++ b/app/controllers/problems_controller.rb @@ -1,13 +1,14 @@ class ProblemsController < ApplicationController - before_filter :authenticate, :authorization + before_action :authenticate, :authorization + before_action :testcase_authorization, only: [:show_testcase] in_place_edit_for :problem, :name in_place_edit_for :problem, :full_name in_place_edit_for :problem, :full_score def index - @problems = Problem.find(:all, :order => 'date_added DESC') + @problems = Problem.order(date_added: :desc) end # GETs should be safe (see http://www.w3.org/2001/tag/doc/whenToUseGet.html) @@ -27,7 +28,7 @@ end def create - @problem = Problem.new(params[:problem]) + @problem = Problem.new(problem_params) @description = Description.new(params[:description]) if @description.body!='' if !@description.save @@ -46,7 +47,7 @@ end def quick_create - @problem = Problem.new(params[:problem]) + @problem = Problem.new(problem_params) @problem.full_name = @problem.name if @problem.full_name == '' @problem.full_score = 100 @problem.available = false @@ -87,7 +88,7 @@ flash[:notice] = 'Error: Uploaded file is not PDF' render :action => 'edit' and return end - if @problem.update_attributes(params[:problem]) + if @problem.update_attributes(problem_params) flash[:notice] = 'Problem was successfully updated.' unless params[:file] == nil or params[:file] == '' flash[:notice] = 'Problem was successfully updated and a new PDF file is uploaded.' @@ -134,9 +135,16 @@ end end + def toggle_view_testcase + @problem = Problem.find(params[:id]) + @problem.update_attributes(view_testcase: !(@problem.view_testcase?) ) + respond_to do |format| + format.js { } + end + end + def turn_all_off - Problem.find(:all, - :conditions => "available = 1").each do |problem| + Problem.available.all.each do |problem| problem.available = false problem.save end @@ -144,8 +152,7 @@ end def turn_all_on - Problem.find(:all, - :conditions => "available = 0").each do |problem| + Problem.where.not(available: true).each do |problem| problem.available = true problem.save end @@ -176,7 +183,7 @@ end def manage - @problems = Problem.find(:all, :order => 'date_added DESC') + @problems = Problem.order(date_added: :desc) end def do_manage @@ -278,4 +285,10 @@ def get_problems_stat end + private + + def problem_params + params.require(:problem).permit(:name, :full_name, :full_score, :date_added, :available, :test_allowed,:output_only, :url, :description) + end + end diff --git a/app/controllers/report_controller.rb b/app/controllers/report_controller.rb --- a/app/controllers/report_controller.rb +++ b/app/controllers/report_controller.rb @@ -9,18 +9,14 @@ before_filter(only: [:problem_hof]) { |c| return false unless authenticate - if GraderConfiguration["right.user_view_submission"] - return true; - end - - admin_authorization + admin_authorization unless GraderConfiguration["right.user_view_submission"] } def max_score end def current_score - @problems = Problem.find_available_problems + @problems = Problem.available_problems @users = User.includes(:contests).includes(:contest_stat).where(enabled: true) @scorearray = calculate_max_score(@problems, @users,0,0,true) @@ -38,25 +34,27 @@ #process parameters #problems @problems = [] - params[:problem_id].each do |id| - next unless id.strip != "" - pid = Problem.find_by_id(id.to_i) - @problems << pid if pid + if params[:problem_id] + params[:problem_id].each do |id| + next unless id.strip != "" + pid = Problem.find_by_id(id.to_i) + @problems << pid if pid + end end #users @users = if params[:user] == "all" then - User.find(:all, :include => [:contests, :contest_stat]) + User.includes(:contests).includes(:contest_stat) else User.includes(:contests).includes(:contest_stat).where(enabled: true) end #set up range from param - since_id = params.fetch(:min_id, 0).to_i - until_id = params.fetch(:max_id, 0).to_i + @since_id = params.fetch(:from_id, 0).to_i + @until_id = params.fetch(:to_id, 0).to_i #calculate the routine - @scorearray = calculate_max_score(@problems, @users,since_id,until_id) + @scorearray = calculate_max_score(@problems, @users, @since_id, @until_id) #rencer accordingly if params[:button] == 'download' then @@ -73,9 +71,9 @@ if params[:commit] == 'download csv' @problems = Problem.all else - @problems = Problem.find_available_problems + @problems = Problem.available_problems end - @users = User.includes(:contests, :contest_stat).where(enabled: true) #find(:all, :include => [:contests, :contest_stat]).where(enabled: true) + @users = User.includes(:contests, :contest_stat).where(enabled: true) @scorearray = Array.new @users.each do |u| ustat = Array.new diff --git a/app/controllers/site_controller.rb b/app/controllers/site_controller.rb --- a/app/controllers/site_controller.rb +++ b/app/controllers/site_controller.rb @@ -4,7 +4,7 @@ def login # Site administrator login - @countries = Country.find(:all, :include => :sites) + @countries = Country.includes(:sites).all @country_select = @countries.collect { |c| [c.name, c.id] } @country_select_with_all = [['Any',0]] @@ -59,4 +59,9 @@ end end + private + def site_params + params.require(:site).permit() + end + end diff --git a/app/controllers/sites_controller.rb b/app/controllers/sites_controller.rb --- a/app/controllers/sites_controller.rb +++ b/app/controllers/sites_controller.rb @@ -5,7 +5,7 @@ # GET /sites # GET /sites.xml def index - @sites = Site.find(:all, :order => 'country_id') + @sites = Site.order(:country_id) respond_to do |format| format.html # index.html.erb @@ -65,7 +65,7 @@ @site.clear_start_time_if_not_started respond_to do |format| - if @site.update_attributes(params[:site]) + if @site.update_attributes(site_params) flash[:notice] = 'Site was successfully updated.' format.html { redirect_to(@site) } format.xml { head :ok } @@ -88,4 +88,10 @@ end end + private + + def site_params + params.require(:site).permit(:name,:started,:start_time,:country_id,:password) + end + end diff --git a/app/controllers/submissions_controller.rb b/app/controllers/submissions_controller.rb --- a/app/controllers/submissions_controller.rb +++ b/app/controllers/submissions_controller.rb @@ -1,6 +1,7 @@ class SubmissionsController < ApplicationController - before_filter :authenticate - before_filter :submission_authorization, only: [:show, :direct_edit_submission] + before_action :authenticate + before_action :submission_authorization, only: [:show, :direct_edit_submission, :download, :edit] + before_action :admin_authorization, only: [:rejudge] # GET /submissions # GET /submissions.json @@ -19,7 +20,7 @@ flash[:notice] = 'Error: submissions for that problem are not viewable.' return end - @submissions = Submission.find_all_by_user_problem(@user.id, @problem.id) + @submissions = Submission.find_all_by_user_problem(@user.id, @problem.id).order(id: :desc) end end @@ -31,6 +32,20 @@ #log the viewing user = User.find(session[:user_id]) SubmissionViewLog.create(user_id: session[:user_id],submission_id: @submission.id) unless user.admin? + + @task = @submission.task + end + + def download + @submission = Submission.find(params[:id]) + send_data(@submission.source, {:filename => @submission.download_filename, :type => 'text/plain'}) + end + + def compiler_msg + @submission = Submission.find(params[:id]) + respond_to do |format| + format.js + end end #on-site new submission on specific problem @@ -60,63 +75,18 @@ end end -# # GET /submissions/new -# # GET /submissions/new.json -# def new -# @submission = Submission.new -# -# respond_to do |format| -# format.html # new.html.erb -# format.json { render json: @submission } -# end -# end -# -# -# # POST /submissions -# # POST /submissions.json -# def create -# @submission = Submission.new(params[:submission]) -# -# respond_to do |format| -# if @submission.save -# format.html { redirect_to @submission, notice: 'Submission was successfully created.' } -# format.json { render json: @submission, status: :created, location: @submission } -# else -# format.html { render action: "new" } -# format.json { render json: @submission.errors, status: :unprocessable_entity } -# end -# end -# end -# -# # PUT /submissions/1 -# # PUT /submissions/1.json -# def update -# @submission = Submission.find(params[:id]) -# -# respond_to do |format| -# if @submission.update_attributes(params[:submission]) -# format.html { redirect_to @submission, notice: 'Submission was successfully updated.' } -# format.json { head :no_content } -# else -# format.html { render action: "edit" } -# format.json { render json: @submission.errors, status: :unprocessable_entity } -# end -# end -# end -# -# # DELETE /submissions/1 -# # DELETE /submissions/1.json -# def destroy -# @submission = Submission.find(params[:id]) -# @submission.destroy -# -# respond_to do |format| -# format.html { redirect_to submissions_url } -# format.json { head :no_content } -# end -# end + # GET /submissions/:id/rejudge + def rejudge + @submission = Submission.find(params[:id]) + @task = @submission.task + @task.status_inqueue! if @task + respond_to do |format| + format.js + end + end protected + def submission_authorization #admin always has privileged if @current_user.admin? @@ -133,5 +103,6 @@ unauthorized_redirect return false end + end diff --git a/app/controllers/testcases_controller.rb b/app/controllers/testcases_controller.rb new file mode 100644 --- /dev/null +++ b/app/controllers/testcases_controller.rb @@ -0,0 +1,32 @@ +class TestcasesController < ApplicationController + before_action :set_testcase, only: [:download_input,:download_sol] + before_action :testcase_authorization + + def download_input + send_data @testcase.input, type: 'text/plain', filename: "#{@testcase.problem.name}.#{@testcase.num}.in" + end + + def download_sol + send_data @testcase.sol, type: 'text/plain', filename: "#{@testcase.problem.name}.#{@testcase.num}.sol" + end + + def show_problem + @problem = Problem.includes(:testcases).find(params[:problem_id]) + unless @current_user.admin? or @problem.view_testcase + flash[:error] = 'You cannot view the testcase of this problem' + redirect_to :controller => 'main', :action => 'list' + end + end + + + private + # Use callbacks to share common setup or constraints between actions. + def set_testcase + @testcase = Testcase.find(params[:id]) + end + + # Only allow a trusted parameter "white list" through. + def testcase_params + params[:testcase] + end +end diff --git a/app/controllers/user_admin_controller.rb b/app/controllers/user_admin_controller.rb --- a/app/controllers/user_admin_controller.rb +++ b/app/controllers/user_admin_controller.rb @@ -29,7 +29,7 @@ end def active - sessions = ActiveRecord::SessionStore::Session.find(:all, :conditions => ["updated_at >= ?", 60.minutes.ago]) + sessions = ActiveRecord::SessionStore::Session.where("updated_at >= ?", 60.minutes.ago) @users = [] sessions.each do |session| if session.data[:user_id] @@ -47,7 +47,7 @@ end def create - @user = User.new(params[:user]) + @user = User.new(user_params) @user.activated = true if @user.save flash[:notice] = 'User was successfully created.' @@ -74,27 +74,39 @@ if items.length>=2 login = items[0] full_name = items[1] + remark ='' + user_alias = '' added_random_password = false - if items.length>=3 + if items.length >= 3 and items[2].chomp(" ").length > 0; password = items[2].chomp(" ") - user_alias = (items.length>=4) ? items[3] : login else password = random_password - user_alias = (items.length>=4) ? items[3] : login - added_random_password = true + add_random_password=true; + end + + if items.length>= 4 and items[3].chomp(" ").length > 0; + user_alias = items[3].chomp(" ") + else + user_alias = login + end + + if items.length>=5 + remark = items[4].strip; end user = User.find_by_login(login) if (user) user.full_name = full_name user.password = password + user.remark = remark else user = User.new({:login => login, :full_name => full_name, :password => password, :password_confirmation => password, - :alias => user_alias}) + :alias => user_alias, + :remark => remark}) end user.activated = true user.save @@ -106,7 +118,7 @@ end end end - flash[:notice] = 'User(s) ' + note.join(', ') + + flash[:success] = 'User(s) ' + note.join(', ') + ' were successfully created. ' + '( (+) - created with random passwords.)' redirect_to :action => 'index' @@ -118,7 +130,7 @@ def update @user = User.find(params[:id]) - if @user.update_attributes(params[:user]) + if @user.update_attributes(user_params) flash[:notice] = 'User was successfully updated.' redirect_to :action => 'show', :id => @user else @@ -135,9 +147,9 @@ if params[:commit] == 'download csv' @problems = Problem.all else - @problems = Problem.find_available_problems + @problems = Problem.available_problems end - @users = User.includes(:contests, :contest_stat).where(enabled: true) #find(:all, :include => [:contests, :contest_stat]).where(enabled: true) + @users = User.includes(:contests, :contest_stat).where(enabled: true) @scorearray = Array.new @users.each do |u| ustat = Array.new @@ -164,9 +176,9 @@ if params[:commit] == 'download csv' @problems = Problem.all else - @problems = Problem.find_available_problems + @problems = Problem.available_problems end - @users = User.find(:all, :include => [:contests, :contest_stat]) + @users = User.includes(:contests).includes(:contest_stat).all @scorearray = Array.new #set up range from param since_id = params.fetch(:since_id, 0).to_i @@ -201,7 +213,7 @@ end def random_all_passwords - users = User.find(:all) + users = User.all @prefix = params[:prefix] || '' @non_admin_users = User.find_non_admin_with_prefix(@prefix) @changed = false @@ -324,7 +336,7 @@ # admin management def admin - @admins = User.find(:all).find_all {|user| user.admin? } + @admins = User.all.find_all {|user| user.admin? } end def grant_admin @@ -395,6 +407,39 @@ redirect_to :action => 'mass_mailing' end + #bulk manage + def bulk_manage + + begin + @users = User.where('login REGEXP ?',params[:regex]) if params[:regex] + @users.count if @users #i don't know why I have to call count, but if I won't exception is not raised + rescue Exception + flash[:error] = 'Regular Expression is malformed' + @users = nil + end + + if params[:commit] + @action = {} + @action[:set_enable] = params[:enabled] + @action[:enabled] = params[:enable] == "1" + @action[:gen_password] = params[:gen_password] + end + + if params[:commit] == "Perform" + if @action[:set_enable] + @users.update_all(enabled: @action[:enabled]) + end + if @action[:gen_password] + @users.each do |u| + password = random_password + u.password = password + u.password_confirmation = password + u.save + end + end + end + end + protected def random_password(length=5) @@ -521,7 +566,7 @@ row << sc[i].login row << sc[i].full_name row << sc[i].activated - row << (sc[i].try(:contest_stat).try(:started_at).nil? 'no' : 'yes') + row << (sc[i].try(:contest_stat).try(:started_at).nil? ? 'no' : 'yes') row << sc[i].contests.collect {|c| c.name}.join(', ') else row << sc[i][0] @@ -535,4 +580,9 @@ end end end + + private + def user_params + params.require(:user).permit(:login,:password,:password_confirmation,:email, :alias, :full_name,:remark) + end end diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -52,7 +52,7 @@ redirect_to :controller => 'main', :action => 'login' return end - @user = User.new(params[:user]) + @user = User.new(user_params) @user.password_confirmation = @user.password = User.random_password @user.activated = false if (@user.valid?) and (@user.save) @@ -209,6 +209,10 @@ #finally, we allow only admin admin_authorization end - + + private + def user_params + params.require(:user).permit(:login, :full_name, :email) + end end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -28,7 +28,7 @@ result = content_tag(:ul,left_menu.html_safe,class: 'nav navbar-nav') + content_tag(:ul,right_menu.html_safe,class: 'nav navbar-nav navbar-right') end - def add_menu(title, controller, action,html_option = {}) + def add_menu(title, controller, action, html_option = {}) link_option = {controller: controller, action: action} html_option[:class] = (html_option[:class] || '') + " active" if current_page?(link_option) content_tag(:li, link_to(title,link_option),html_option) @@ -196,4 +196,26 @@ markdown.to_html.html_safe end + + BOOTSTRAP_FLASH_MSG = { + success: 'alert-success', + error: 'alert-danger', + alert: 'alert-block', + notice: 'alert-info' + } + + def bootstrap_class_for(flash_type) + BOOTSTRAP_FLASH_MSG.fetch(flash_type.to_sym, flash_type.to_s) + end + + def flash_messages + flash.each do |msg_type, message| + concat(content_tag(:div, message, class: "alert #{bootstrap_class_for(msg_type)} fade in") do + concat content_tag(:button, 'x', class: "close", data: { dismiss: 'alert' }) + concat message + end) + end + nil + end + end diff --git a/app/helpers/testcases_helper.rb b/app/helpers/testcases_helper.rb new file mode 100644 --- /dev/null +++ b/app/helpers/testcases_helper.rb @@ -0,0 +1,2 @@ +module TestcasesHelper +end diff --git a/app/models/announcement.rb b/app/models/announcement.rb --- a/app/models/announcement.rb +++ b/app/models/announcement.rb @@ -1,21 +1,15 @@ class Announcement < ActiveRecord::Base - def self.find_published(contest_started=false) + def self.published(contest_started=false) if contest_started - Announcement.find(:all, - :conditions => "(published = 1) AND (frontpage = 0)", - :order => "created_at DESC") + where(published: true).where(frontpage: false).order(created_at: :desc) else - Announcement.find(:all, - :conditions => "(published = 1) AND (frontpage = 0) AND (contest_only = 0)", - :order => "created_at DESC") + where(published: true).where(frontpage: false).where(contest_only: false).order(created_at: :desc) end end - def self.find_for_frontpage - Announcement.find(:all, - :conditions => "(published = 1) AND (frontpage = 1)", - :order => "created_at DESC") + def self.frontpage + where(published: 1).where(frontpage: 1).order(created_at: :desc) end end diff --git a/app/models/contest.rb b/app/models/contest.rb --- a/app/models/contest.rb +++ b/app/models/contest.rb @@ -3,6 +3,6 @@ has_and_belongs_to_many :users has_and_belongs_to_many :problems - scope :enabled, :conditions => {:enabled => true} + scope :enabled, -> { where(enabled: true) } end diff --git a/app/models/grader_configuration.rb b/app/models/grader_configuration.rb --- a/app/models/grader_configuration.rb +++ b/app/models/grader_configuration.rb @@ -10,6 +10,8 @@ MULTICONTESTS_KEY = 'system.multicontests' CONTEST_TIME_LIMIT_KEY = 'contest.time_limit' MULTIPLE_IP_LOGIN_KEY = 'right.multiple_ip_login' + VIEW_TESTCASE = 'right.view_testcase' + SINGLE_USER_KEY = 'system.single_user_mode' cattr_accessor :config_cache cattr_accessor :task_grading_info_cache @@ -70,6 +72,10 @@ return (get(SYSTEM_MODE_CONF_KEY)=='analysis') end + def self.show_testcase + return get(VIEW_TESTCASE) + end + def self.allow_test_request(user) mode = get(SYSTEM_MODE_CONF_KEY) early_timeout = get(TEST_REQUEST_EARLY_TIMEOUT_KEY) @@ -152,7 +158,7 @@ def self.read_config GraderConfiguration.config_cache = {} - GraderConfiguration.find(:all).each do |conf| + GraderConfiguration.all.each do |conf| key = conf.key val = conf.value GraderConfiguration.config_cache[key] = GraderConfiguration.convert_type(val,conf.value_type) diff --git a/app/models/grader_process.rb b/app/models/grader_process.rb --- a/app/models/grader_process.rb +++ b/app/models/grader_process.rb @@ -1,11 +1,7 @@ class GraderProcess < ActiveRecord::Base def self.find_by_host_and_pid(host,pid) - return GraderProcess.find(:first, - :conditions => { - :host => host, - :pid => pid - }) + return GraderProcess.where(host:host).where(pid: pid).first end def self.register(host,pid,mode) @@ -27,20 +23,15 @@ end def self.find_running_graders - GraderProcess.find(:all, - :conditions => {:terminated => 0}) + where(terminated: false) end def self.find_terminated_graders - GraderProcess.find(:all, - :conditions => "`terminated`") + where(terminated: true) end def self.find_stalled_process - GraderProcess.find(:all, - :conditions => ["(`terminated` = 0) AND active AND " + - "(updated_at < ?)", - Time.now.gmtime - GraderProcess.stalled_time]) + where(terminated: false).where(active: true).where("updated_at < ?",Time.now.gmtime - GraderProcess.stalled_time) end def report_active(task=nil) diff --git a/app/models/language.rb b/app/models/language.rb --- a/app/models/language.rb +++ b/app/models/language.rb @@ -4,7 +4,7 @@ def self.cache_ext_hash @@languages_by_ext = {} - Language.find(:all).each do |language| + Language.all.each do |language| language.common_ext.split(',').each do |ext| @@languages_by_ext[ext] = language end diff --git a/app/models/login.rb b/app/models/login.rb --- a/app/models/login.rb +++ b/app/models/login.rb @@ -1,5 +1,4 @@ class Login < ActiveRecord::Base belongs_to :user - attr_accessible :ip_address, :logged_in_at, :user_id end diff --git a/app/models/message.rb b/app/models/message.rb --- a/app/models/message.rb +++ b/app/models/message.rb @@ -23,10 +23,8 @@ end def self.find_all_system_unreplied_messages - self.find(:all, - :conditions => 'ISNULL(receiver_id) ' + - 'AND (ISNULL(replied) OR replied=0)', - :order => 'created_at') + where('ISNULL(receiver_id) ' + + 'AND (ISNULL(replied) OR replied=0)') end def self.build_replying_message_hierarchy(*args) diff --git a/app/models/problem.rb b/app/models/problem.rb --- a/app/models/problem.rb +++ b/app/models/problem.rb @@ -6,16 +6,17 @@ has_many :testcases, :dependent => :destroy validates_presence_of :name - validates_format_of :name, :with => /^\w+$/ + validates_format_of :name, :with => /\A\w+\z/ validates_presence_of :full_name - scope :available, :conditions => {:available => true} + scope :available, -> { where(available: true) } DEFAULT_TIME_LIMIT = 1 DEFAULT_MEMORY_LIMIT = 32 - def self.find_available_problems - Problem.available.all(:order => "date_added DESC, name ASC") + def self.available_problems + available.order(date_added: :desc).order(:name) + #Problem.available.all(:order => "date_added DESC, name ASC") end def self.create_from_import_form_params(params, old_problem=nil) @@ -60,7 +61,9 @@ result = Hash.new #total number of submission result[:total_sub] = Submission.where(problem_id: self.id).count - result[:attempted_user] = Submission.where(problem_id: self.id).group_by(:user_id) + result[:attempted_user] = Submission.where(problem_id: self.id).group(:user_id) + result[:pass] = Submission.where(problem_id: self.id).where("points >= ?",self.full_score).count + return result end def long_name diff --git a/app/models/submission.rb b/app/models/submission.rb --- a/app/models/submission.rb +++ b/app/models/submission.rb @@ -13,14 +13,12 @@ validate :must_have_valid_problem validate :must_specify_language + has_one :task + before_save :assign_latest_number_if_new_recond def self.find_last_by_user_and_problem(user_id, problem_id) - last_sub = find(:first, - :conditions => {:user_id => user_id, - :problem_id => problem_id}, - :order => 'number DESC') - return last_sub + where("user_id = ? AND problem_id = ?",user_id,problem_id).last end def self.find_all_last_by_problem(problem_id) @@ -43,7 +41,7 @@ def self.find_last_for_all_available_problems(user_id) submissions = Array.new - problems = Problem.find_available_problems + problems = Problem.available_problems problems.each do |problem| sub = Submission.find_last_by_user_and_problem(user_id, problem.id) submissions << sub if sub!=nil @@ -52,20 +50,11 @@ end def self.find_by_user_problem_number(user_id, problem_id, number) - Submission.find(:first, - :conditions => { - :user_id => user_id, - :problem_id => problem_id, - :number => number - }) + where("user_id = ? AND problem_id = ? AND number = ?",user_id,problem_id,number).first end def self.find_all_by_user_problem(user_id, problem_id) - Submission.find(:all, - :conditions => { - :user_id => user_id, - :problem_id => problem_id, - }) + where("user_id = ? AND problem_id = ?",user_id,problem_id) end def download_filename diff --git a/app/models/submission_view_log.rb b/app/models/submission_view_log.rb --- a/app/models/submission_view_log.rb +++ b/app/models/submission_view_log.rb @@ -1,3 +1,3 @@ class SubmissionViewLog < ActiveRecord::Base - attr_accessible :submission_id, :user_id + #attr_accessible :submission_id, :user_id end diff --git a/app/models/task.rb b/app/models/task.rb --- a/app/models/task.rb +++ b/app/models/task.rb @@ -48,10 +48,7 @@ task = nil begin Task.transaction do - task = Task.find(:first, - :order => "created_at", - :conditions => {:status=> Task::STATUS_INQUEUE}, - :lock => true) + task = Task.where(status: Task::STATUS_INQUEUE).lock(true).first if task!=nil task.status = status task.save! diff --git a/app/models/test_request.rb b/app/models/test_request.rb --- a/app/models/test_request.rb +++ b/app/models/test_request.rb @@ -16,8 +16,7 @@ require 'fileutils' class TestRequest < Task - - set_table_name "test_requests" + self.table_name = "test_requests" belongs_to :user belongs_to :problem @@ -38,9 +37,7 @@ # since there will be only one grader grading TestRequest # we do not need locking (hopefully) - test_request = TestRequest.find(:first, - :order => "created_at", - :conditions => {:status=> Task::STATUS_INQUEUE}) + test_request = TestRequest.where(status: Task::STATUS_INQUEUE).first if test_request!=nil test_request.status = status test_request.save! diff --git a/app/models/testcase.rb b/app/models/testcase.rb --- a/app/models/testcase.rb +++ b/app/models/testcase.rb @@ -1,4 +1,4 @@ class Testcase < ActiveRecord::Base belongs_to :problem - attr_accessible :group, :input, :num, :score, :sol + #attr_accessible :group, :input, :num, :score, :sol end diff --git a/app/models/user.rb b/app/models/user.rb --- a/app/models/user.rb +++ b/app/models/user.rb @@ -8,30 +8,28 @@ has_and_belongs_to_many :roles - has_many :test_requests, :order => "submitted_at DESC" + has_many :test_requests, -> {order(submitted_at: DESC)} - has_many :messages, + has_many :messages, -> { order(created_at: DESC) }, :class_name => "Message", - :foreign_key => "sender_id", - :order => 'created_at DESC' + :foreign_key => "sender_id" - has_many :replied_messages, + has_many :replied_messages, -> { order(created_at: DESC) }, :class_name => "Message", - :foreign_key => "receiver_id", - :order => 'created_at DESC' + :foreign_key => "receiver_id" has_one :contest_stat, :class_name => "UserContestStat", :dependent => :destroy belongs_to :site belongs_to :country - has_and_belongs_to_many :contests, :uniq => true, :order => 'name' + has_and_belongs_to_many :contests, -> { order(:name); uniq} - scope :activated_users, :conditions => {:activated => true} + scope :activated_users, -> {where activated: true} validates_presence_of :login validates_uniqueness_of :login - validates_format_of :login, :with => /^[\_A-Za-z0-9]+$/ + validates_format_of :login, :with => /\A[\_A-Za-z0-9]+\z/ validates_length_of :login, :within => 3..30 validates_presence_of :full_name @@ -129,14 +127,14 @@ end def self.find_non_admin_with_prefix(prefix='') - users = User.find(:all) + users = User.all return users.find_all { |u| !(u.admin?) and u.login.index(prefix)==0 } end # Contest information def self.find_users_with_no_contest() - users = User.find(:all) + users = User.all return users.find_all { |u| u.contests.length == 0 } end @@ -233,9 +231,18 @@ return contest_problems end + def solve_all_available_problems? + available_problems.each do |p| + u = self + sub = Submission.find_last_by_user_and_problem(u.id,p.id) + return false if !p or !sub or sub.points < p.full_score + end + return true + end + def available_problems if not GraderConfiguration.multicontests? - return Problem.find_available_problems + return Problem.available_problems else contest_problems = [] pin = {} diff --git a/app/views/announcements/edit.html.erb b/app/views/announcements/edit.html.erb deleted file mode 100644 --- a/app/views/announcements/edit.html.erb +++ /dev/null @@ -1,47 +0,0 @@ -

Editing announcement

- -<%= error_messages_for :announcement %> - -<%= form_for(@announcement) do |f| %> -

- Title
- <%= f.text_field :title %> -

- -

- Notes (shown internally, used to organize announcements)
- <%= f.text_field :notes %> -

- -

- Body
- <%= f.text_area :body %> -

- -

- Author
- <%= f.text_field :author %> -

- -

- Published
- <%= f.check_box :published %> -

- -

- Show on front page?
- <%= f.check_box :frontpage %> -

- -

- Show only in contest?
- <%= f.check_box :contest_only %> -

- -

- <%= f.submit "Update" %> -

-<% end %> - -<%= link_to 'Show', @announcement %> | -<%= link_to 'Back', announcements_path %> diff --git a/app/views/application/_submission.html.haml b/app/views/application/_submission.html.haml --- a/app/views/application/_submission.html.haml +++ b/app/views/application/_submission.html.haml @@ -1,8 +1,8 @@ %tr %td{:align => "center"} - = submission_counter+1 - %td{:align => "center"} + = submission.number + %td.text-right = link_to "##{submission.id}", submission_path(submission.id) %td = l submission.submitted_at, format: :long diff --git a/app/views/application/_submission_short.html.haml b/app/views/application/_submission_short.html.haml --- a/app/views/application/_submission_short.html.haml +++ b/app/views/application/_submission_short.html.haml @@ -2,25 +2,25 @@ - if submission.nil? = "-" - else - - if submission.graded_at.nil? + - unless submission.graded_at = t 'main.submitted_at' = format_short_time(submission.submitted_at.localtime) - else - = t 'main.graded_at' - = "#{format_short_time(submission.graded_at.localtime)}, " + %strong= t 'main.graded_at' + = "#{format_short_time(submission.graded_at.localtime)} " + %br - if GraderConfiguration['ui.show_score'] - = t 'main.score' + %strong=t 'main.score' = "#{(submission.points*100/submission.problem.full_score).to_i} " = " [" %tt = submission.grader_comment = "]" + %br + %strong View: - if GraderConfiguration.show_grading_result - = " | " = link_to '[detailed result]', :action => 'result', :id => submission.id - = " | " - = link_to("[#{t 'main.cmp_msg'}]", {:action => 'compiler_msg', :id => submission.id}, {:popup => true}) - = " | " - = link_to("[#{t 'main.src_link'}]",{:action => 'source', :id => submission.id}) - //= " | " - //= link_to "[#{t 'main.submissions_link'}]", main_submission_path(submission.problem.id) + = link_to "#{t 'main.cmp_msg'}", {:action => 'compiler_msg', :id => submission.id}, {popup: true,class: 'btn btn-xs btn-info'} + = link_to "#{t 'main.src_link'}", download_submission_path(submission.id), class: 'btn btn-xs btn-info' + = link_to "#{t 'main.submissions_link'}", problem_submissions_path(problem_id), class: 'btn btn-xs btn-info' + diff --git a/app/views/configurations/index.html.haml b/app/views/configurations/index.html.haml --- a/app/views/configurations/index.html.haml +++ b/app/views/configurations/index.html.haml @@ -3,24 +3,27 @@ %h1 System configuration -%table.info - %tr.info-head - %th Key - %th Type - %th Value - %th Description - - @configurations.each do |conf| - - @grader_configuration = conf - %tr{:class => cycle("info-odd", "info-even")} - %td - /= in_place_editor_field :grader_configuration, :key, {}, :rows=>1 - = @grader_configuration.key - %td - /= in_place_editor_field :grader_configuration, :value_type, {}, :rows=>1 - = @grader_configuration.value_type - %td - = best_in_place @grader_configuration, :value, ok_button: "ok", cancel_button: "cancel" - %td= conf.description +- @group.each do |g| + %h2= g + %table.table.table-striped + %thead + %th{style: 'width: 25%'} Key + %th{style: 'width: 10%'}Type + %th{style: 'width: 15%'} Value + %th Description + - @configurations.each do |conf| + - next if conf.key[0...(conf.key.index('.'))] != g + - @grader_configuration = conf + %tr + %td + /= in_place_editor_field :grader_configuration, :key, {}, :rows=>1 + = @grader_configuration.key + %td + /= in_place_editor_field :grader_configuration, :value_type, {}, :rows=>1 + = @grader_configuration.value_type + %td + = best_in_place @grader_configuration, :value, ok_button: "ok", cancel_button: "cancel" + %td= conf.description - if GraderConfiguration.config_cached? %br/ diff --git a/app/views/graders/list.html.haml b/app/views/graders/list.html.haml --- a/app/views/graders/list.html.haml +++ b/app/views/graders/list.html.haml @@ -54,8 +54,8 @@ - @submission.each do |sub| %tr.inactive %td= link_to sub.id, submission_path(sub.id) - %td= ("" unless sub.user) || link_to sub.try(:user).try(:full_name), stat_user_path(sub.user.id) - %td= ("" unless sub.problem) || link_to sub.try(:problem).try(:full_name), stat_problem_path(sub.problem.id) + %td= ("" unless sub.user) || link_to(sub.try(:user).try(:full_name), stat_user_path(sub.user.id)) + %td= ("" unless sub.problem) || link_to(sub.try(:problem).try(:full_name), stat_problem_path(sub.problem.id)) %td= "#{time_ago_in_words(sub.submitted_at)} ago" %td= sub.graded_at ? "#{time_ago_in_words(sub.graded_at)} ago" : " " %td= sub.grader_comment @@ -72,8 +72,8 @@ - @backlog_submission.each do |sub| %tr.inactive %td= link_to sub.id, submission_path(sub.id) - %td= ("" unless sub.user) || link_to sub.try(:user).try(:full_name), stat_user_path(sub.user.id) - %td= ("" unless sub.problem) || link_to sub.try(:problem).try(:full_name), stat_problem_path(sub.problem.id) + %td= ("" unless sub.user) || link_to( sub.try(:user).try(:full_name), stat_user_path(sub.user.id)) + %td= ("" unless sub.problem) || link_to( sub.try(:problem).try(:full_name), stat_problem_path(sub.problem.id)) %td= "#{time_ago_in_words(sub.submitted_at)} ago" %td= sub.graded_at ? "#{time_ago_in_words(sub.graded_at)} ago" : " " %td= sub.grader_comment diff --git a/app/views/layouts/_header.html.haml b/app/views/layouts/_header.html.haml --- a/app/views/layouts/_header.html.haml +++ b/app/views/layouts/_header.html.haml @@ -2,20 +2,26 @@ %nav .container-fluid .navbar-header + %button.navbar-toggle.collapsed{ data: {toggle: 'collapse', target: '#navbar-collapse'} } + %span.sr-only Togggle Navigation + %span.icon-bar + %span.icon-bar + %span.icon-bar %a.navbar-brand{href: main_list_path} %span.glyphicon.glyphicon-home MAIN - .collapse.navbar-collapse + .collapse.navbar-collapse#navbar-collapse %ul.nav.navbar-nav + / submission - if (@current_user!=nil) and (GraderConfiguration.show_tasks_to?(@current_user)) - //= add_menu("#{I18n.t 'menu.tasks'}", 'tasks', 'list') %li.dropdown %a.dropdown-toggle{href: '#', data: {toggle:'dropdown'}, aria: {haspopup:"true", expanded:"false"}, role: "button"} = "#{I18n.t 'menu.submissions'}" %span.caret %ul.dropdown-menu - = add_menu("View", 'main', 'submission') + = add_menu("View", 'submissions', 'index') = add_menu("Self Test", 'test', 'index') + / hall of fame - if GraderConfiguration['right.user_hall_of_fame'] = add_menu("#{I18n.t 'menu.hall_of_fame'}", 'report', 'problem_hof') / display MODE button (with countdown in contest mode) @@ -32,6 +38,7 @@ $("#countdown").countdown({until: "+#{@current_user.contest_time_left.to_i}s", layout: 'Time left: {hnn}:{mnn}:{snn}'}); / admin section - if (@current_user!=nil) and (session[:admin]) + / management %li.dropdown %a.dropdown-toggle{href: '#', data: {toggle:'dropdown'}, aria: {haspopup:"true", expanded:"false"}, role: "button"} Manage @@ -47,12 +54,14 @@ %li.divider{role: 'separator'} = add_menu( 'Sites', 'sites', 'index') = add_menu( 'Contests', 'contest_management', 'index') + / report %li.dropdown %a.dropdown-toggle{href: '#', data: {toggle:'dropdown'}, aria: {haspopup:"true", expanded:"false"}, role: "button"} Report %span.caret %ul.dropdown-menu - = add_menu( 'Results', 'report', 'current_score') + = add_menu( 'Current Score', 'report', 'current_score') + = add_menu( 'Score Report', 'report', 'max_score') = add_menu( 'Report', 'report', 'multiple_login') - if (ungraded = Submission.where('graded_at is null').where('submitted_at < ?', 1.minutes.ago).count) > 0 =link_to "#{ungraded} backlogs!", diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml --- a/app/views/layouts/application.html.haml +++ b/app/views/layouts/application.html.haml @@ -11,5 +11,6 @@ %body = render 'layouts/header' - = content_tag(:p,flash[:notice],class: 'alert alert-success') if flash[:notice]!=nil + /= content_tag(:p,flash[:notice],class: 'alert alert-success') if flash[:notice]!=nil + = flash_messages = yield diff --git a/app/views/main/_login_box.html.haml b/app/views/main/_login_box.html.haml --- a/app/views/main/_login_box.html.haml +++ b/app/views/main/_login_box.html.haml @@ -12,7 +12,7 @@ %hr/ %div{ :style => "border: solid 1px gray; padding: 4px; background: #eeeeff;"} - = form_tag :controller => 'login', :action => 'login' do + = form_tag login_login_path do %table %tr %td{:align => "right"} diff --git a/app/views/main/_problem.html.haml b/app/views/main/_problem.html.haml --- a/app/views/main/_problem.html.haml +++ b/app/views/main/_problem.html.haml @@ -1,8 +1,12 @@ %tr %td - = "#{problem.name}" + - if @current_user and @current_user.admin? + = link_to problem.name, stat_problem_path(problem) + - else + = "#{problem.name}" %td = "#{problem.full_name}" + %br = link_to_description_if_any "[#{t 'main.problem_desc'}] ".html_safe, problem %td diff --git a/app/views/main/_submission_box.html.haml b/app/views/main/_submission_box.html.haml --- a/app/views/main/_submission_box.html.haml +++ b/app/views/main/_submission_box.html.haml @@ -8,7 +8,7 @@ %li= msg .form-group = label_tag :submission, 'Problem:' - = select 'submission', 'problem_id', [[(t 'main.specified_in_header'),'-1']] + @problems.collect {|p| ["[#{p.name}] #{p.full_name}", p.id]}, {:selected => '-1'}, { class: 'select2 form-control' } + = select 'submission', 'problem_id', [[(t 'main.specified_in_header'),'-1']] + @problems.collect {|p| ["[#{p.name}] #{p.full_name}", p.id]}, {:selected => '-1'}, { class: 'select2 form-control', style: "width: 100%" } .form-group = label_tag :file, 'File:' .input-group diff --git a/app/views/main/_submission_short.html.haml b/app/views/main/_submission_short.html.haml --- a/app/views/main/_submission_short.html.haml +++ b/app/views/main/_submission_short.html.haml @@ -3,14 +3,14 @@ = "-" - else - unless submission.graded_at - =t 'main.submitted_at' + = t 'main.submitted_at' = format_short_time(submission.submitted_at.localtime) - else %strong= t 'main.graded_at' = "#{format_short_time(submission.graded_at.localtime)} " %br - if GraderConfiguration['ui.show_score'] - =t 'main.score' + %strong=t 'main.score' = "#{(submission.points*100/submission.problem.full_score).to_i} " = " [" %tt @@ -20,7 +20,10 @@ %strong View: - if GraderConfiguration.show_grading_result = link_to '[detailed result]', :action => 'result', :id => submission.id - = link_to "#{t 'main.cmp_msg'}", {:action => 'compiler_msg', :id => submission.id}, {popup: true,class: 'btn btn-xs btn-info'} + /= link_to "#{t 'main.cmp_msg'}", {:action => 'compiler_msg', :id => submission.id}, {popup: true,class: 'btn btn-xs btn-info'} + = link_to "#{t 'main.cmp_msg'}", compiler_msg_submission_path(submission.id), {popup: true,remote: true,class: 'btn btn-xs btn-info'} = link_to "#{t 'main.src_link'}",{:action => 'source', :id => submission.id}, class: 'btn btn-xs btn-info' = link_to "#{t 'main.submissions_link'}", problem_submissions_path(problem_id), class: 'btn btn-xs btn-info' + - if GraderConfiguration.show_testcase + = link_to "testcases", show_problem_testcases_path(problem_id), class: 'btn btn-xs btn-info' diff --git a/app/views/main/list.html.haml b/app/views/main/list.html.haml --- a/app/views/main/list.html.haml +++ b/app/views/main/list.html.haml @@ -43,6 +43,7 @@ .panel.panel-info .panel-heading Announcement + = link_to 'Manage', announcements_path, class: 'btn btn-xs btn-default' %ul.list-group = render :partial => 'announcement', :collection => @announcements @@ -50,3 +51,14 @@ = "Announcement.refreshUrl = '#{url_for :controller => 'main', :action => 'announcements'}';" Announcement.registerRefreshEventTimer(); +.modal.fade#compiler{tabindex: -1,role: 'dialog'} + .modal-dialog.modal-lg{role:'document'} + .modal-content + .modal-header + %button.close{type: 'button', data: {dismissed: :modal}, aria: {label: 'close'}} + %span{aria: {hidden: 'true'}, data: {dismiss: 'modal'}} × + %h4 Compiler message + .modal-body + %pre#compiler_msg + .modal-footer + %button.btn.btn-default{type: 'button', data: {dismiss: 'modal'}} Close diff --git a/app/views/main/submission.html.haml b/app/views/main/submission.html.haml deleted file mode 100644 --- a/app/views/main/submission.html.haml +++ /dev/null @@ -1,31 +0,0 @@ -= user_title_bar(@user) - -.panel.panel-info - .panel-heading - Select Problems - .panel-body - .form-inline - = select 'submission', - 'problem_id', - @problems.collect {|p| ["[#{p.name}] #{p.full_name}", main_submission_url(p.id)]}, - { selected: (@problem ? main_submission_url(@problem) : -1) }, - { class: 'select2 form-control'} - %button.btn.btn-primary.btn-sm.go-button#problem_go{data: {source: '#submission_problem_id'}} Go - -- if @problem!=nil - %h2= "Task: #{@problem.full_name} (#{@problem.name})" - -- if @submissions!=nil - - if @submissions.length>0 - %table.table - %thead - %th No. - %th # - %th At - %th Source - %th Result - %th{:width => "300px"} Compiler message - %th - = render :partial => 'submission', :collection => @submissions - - else - No submission diff --git a/app/views/problems/_form.html.erb b/app/views/problems/_form.html.erb deleted file mode 100644 --- a/app/views/problems/_form.html.erb +++ /dev/null @@ -1,54 +0,0 @@ -<%= error_messages_for 'problem' %> - - -


-<%= text_field 'problem', 'name' %>

- -


-<%= text_field 'problem', 'full_name' %>

- -


-<%= text_field 'problem', 'full_score' %>

- -


-<%= date_select 'problem', 'date_added' %>

- -<% -# TODO: these should be put in model Problem, but I can't think of -# nice default values for them. These values look fine only -# in this case (of lazily adding new problems). -@problem.available = true if @problem!=nil and @problem.available==nil -@problem.test_allowed = true if @problem!=nil and @problem.test_allowed==nil -@problem.output_only = false if @problem!=nil and @problem.output_only==nil -%> - -

- -<%= check_box :problem, :available %> - - -<%= check_box :problem, :test_allowed %> - - -<%= check_box :problem, :output_only %> -

- -<%= error_messages_for 'description' %> - -


-<%= text_area :description, :body, :rows => 10, :cols => 80 %>

- -

-<%= select "description", - "markdowned", - [['True',true],['False',false]], - {:selected => (@description) ? @description.markdowned : false } -%>

- -


-<%= text_field 'problem', 'url' %>

- -

Task PDF <%= file_field_tag 'file' %>

- - - diff --git a/app/views/problems/edit.html.erb b/app/views/problems/edit.html.erb deleted file mode 100644 --- a/app/views/problems/edit.html.erb +++ /dev/null @@ -1,9 +0,0 @@ -

Editing problem

- -<%= form_for @problem,url:{action: 'update'},html: {multipart: true} do %> - <%= render :partial => 'form' %> - <%= submit_tag 'Edit' %> -<% end %> - -<%= link_to 'Show', :action => 'show', :id => @problem %> | -<%= link_to 'Back', problems_path %> diff --git a/app/views/problems/index.html.haml b/app/views/problems/index.html.haml --- a/app/views/problems/index.html.haml +++ b/app/views/problems/index.html.haml @@ -26,6 +26,9 @@ Avail? %sup{class: 'text-primary',data: {toggle: 'tooltip'}, title: 'Let user submits to this problem?' } [?] %th.text-center + View Data? + %sup{class: 'text-primary',data: {toggle: 'tooltip'}, title: 'Let user view the testcase of this problem?' } [?] + %th.text-center Test? %sup{class: 'text-primary',data: {toggle: 'tooltip'}, title: 'Let user uses test interface on this problem?' } [?] - if GraderConfiguration.multicontests? @@ -38,6 +41,7 @@ %td.text-right= problem.full_score #in_place_editor_field :problem, :full_score, {}, :rows=>1 %td= problem.date_added %td= toggle_button(@problem.available?, toggle_problem_path(@problem), "problem-avail-#{@problem.id}") + %td= toggle_button(@problem.view_testcase?, toggle_view_testcase_problem_path(@problem), "problem-view-testcase-#{@problem.id}") %td= toggle_button(@problem.test_allowed?, toggle_test_problem_path(@problem), "problem-test-#{@problem.id}") - if GraderConfiguration.multicontests? %td diff --git a/app/views/problems/show.html.erb b/app/views/problems/show.html.erb --- a/app/views/problems/show.html.erb +++ b/app/views/problems/show.html.erb @@ -21,4 +21,4 @@

<%= link_to 'Edit', :action => 'edit', :id => @problem %> | -<%= link_to 'Back', :action => 'list' %> +<%= link_to 'Back', problems_path %> diff --git a/app/views/problems/toggle_view_testcase.js.haml b/app/views/problems/toggle_view_testcase.js.haml new file mode 100644 --- /dev/null +++ b/app/views/problems/toggle_view_testcase.js.haml @@ -0,0 +1,2 @@ += render partial: 'toggle_button', + locals: {button_id: "#problem-view-testcase-#{@problem.id}",button_on: @problem.view_testcase?} diff --git a/app/views/report/_score_table.html.haml b/app/views/report/_score_table.html.haml --- a/app/views/report/_score_table.html.haml +++ b/app/views/report/_score_table.html.haml @@ -3,12 +3,12 @@ %tr %th Login %th Name - %th Activated? - %th Logged_in - %th Contest(s) + / %th Activated? + / %th Logged_in + / %th Contest(s) %th Remark - @problems.each do |p| - %th.text-right= p.name + %th.text-right= p.name.gsub('_',' ') %th.text-right Total %th.text-right Passed %tbody @@ -17,11 +17,11 @@ - total,num_passed = 0,0 - sc.each_index do |i| - if i == 0 - %td= link_to sc[i].login, controller: 'users', action: 'profile', id: sc[i] + %td= link_to sc[i].login, stat_user_path(sc[i]) %td= sc[i].full_name - %td= sc[i].activated - %td= sc[i].try(:contest_stat).try(:started_at) ? 'yes' : 'no' - %td= sc[i].contests.collect {|c| c.name}.join(', ') + / %td= sc[i].activated + / %td= sc[i].try(:contest_stat).try(:started_at) ? 'yes' : 'no' + / %td= sc[i].contests.collect {|c| c.name}.join(', ') %td= sc[i].remark - else %td.text-right= sc[i][0] diff --git a/app/views/report/_task_hof.html.haml b/app/views/report/_task_hof.html.haml --- a/app/views/report/_task_hof.html.haml +++ b/app/views/report/_task_hof.html.haml @@ -44,7 +44,7 @@ %tr %td.info_param Best Runtime %td - by #{link_to @best[:runtime][:user], controller:'users', action:'profile', id:@best[:memory][:user_id]} + by #{link_to @best[:runtime][:user], stat_user_path(@best[:runtime][:user_id])} %br using #{@best[:runtime][:lang]} %br @@ -62,7 +62,7 @@ title: "This counts only for submission with 100% score. Right now, java is excluded from memory usage competition. (Because it always uses 2GB memory...)"} [?] %td - by #{link_to @best[:memory][:user], controller:'users', action:'profile', id:@best[:memory][:user_id]} + by #{link_to @best[:memory][:user], stat_user_path(@best[:memory][:user_id])} %br using #{@best[:memory][:lang]} %br @@ -74,7 +74,7 @@ %tr %td.info_param Shortest Code %td - by #{link_to @best[:length][:user], controller:'users', action:'profile', id:@best[:length][:user_id]} + by #{link_to @best[:length][:user], stat_user_path(@best[:length][:user_id])} %br using #{@best[:length][:lang]} %br @@ -87,7 +87,7 @@ %td.info_param First solver %td - if @best[:first][:user] != '(NULL)' - #{link_to @best[:first][:user], controller:'users', action:'profile', id:@best[:first][:user_id]} is the first solver + #{link_to @best[:first][:user], stat_user_path(@best[:first][:user_id])} is the first solver %br using #{@best[:first][:lang]} %br @@ -113,23 +113,23 @@ %tr %td= lang %td - = link_to value[:runtime][:user], controller: 'users', action: 'profile', id: value[:runtime][:user_id] + = link_to value[:runtime][:user], stat_user_path(value[:runtime][:user_id]) %br = "#{(value[:runtime][:value] * 1000).to_i} @" = link_to "#" + value[:runtime][:sub_id].to_s, submission_path( value[:runtime][:sub_id]) %td - = link_to value[:memory][:user], controller: 'users', action: 'profile', id: value[:memory][:user_id] + = link_to value[:memory][:user], stat_user_path( value[:memory][:user_id]) %br = "#{number_with_delimiter(value[:memory][:value])} @" = link_to "#" + value[:memory][:sub_id].to_s, submission_path(value[:memory][:sub_id]) %td - = link_to value[:length][:user], controller: 'users', action: 'profile', id: value[:length][:user_id] + = link_to value[:length][:user], stat_user_path(value[:length][:user_id]) %br = "#{value[:length][:value]} @" = link_to "#" + value[:length][:sub_id].to_s, submission_path(value[:length][:sub_id]) %td - if value[:first][:user] != '(NULL)' #TODO: i know... this is wrong... - = link_to value[:first][:user], controller: 'users', action: 'profile', id: value[:first][:user_id] + = link_to value[:first][:user], stat_user_path(value[:first][:user_id]) %br = "#{value[:first][:value]} @" = link_to "#" + value[:first][:sub_id].to_s, submission_path( value[:first][:sub_id]) diff --git a/app/views/report/max_score.html.haml b/app/views/report/max_score.html.haml --- a/app/views/report/max_score.html.haml +++ b/app/views/report/max_score.html.haml @@ -22,10 +22,10 @@ Input minimum and maximum range of submission ID that should be included. A blank value for min and max means -1 and infinity, respectively. .form-group = label_tag :from, "Min" - = text_field_tag 'from_id', nil, class: "form-control" + = text_field_tag 'from_id', @since_id, class: "form-control" .form-group = label_tag :from, "Max" - = text_field_tag 'to_id', nil, class: "form-control" + = text_field_tag 'to_id', @until_id, class: "form-control" .col-md-4 .panel.panel-primary .panel-heading diff --git a/app/views/submissions/compiler_msg.js.haml b/app/views/submissions/compiler_msg.js.haml new file mode 100644 --- /dev/null +++ b/app/views/submissions/compiler_msg.js.haml @@ -0,0 +1,4 @@ +:plain + $("#compiler_msg").html("#{j @submission.compiler_message}"); + $("#compiler").modal(); + diff --git a/app/views/submissions/edit.html.haml b/app/views/submissions/edit.html.haml --- a/app/views/submissions/edit.html.haml +++ b/app/views/submissions/edit.html.haml @@ -1,7 +1,7 @@ %h2 Live submit %br -%textarea#text_haha{style: "display:none"}~ @source +%textarea#text_sourcecode{style: "display:none"}~ @source .container .row .col-md-12 @@ -28,10 +28,11 @@ .panel.panel-info .panel-heading Latest Submission Status + = link_to "Refresh",get_latest_submission_status_submissions_path(@submission.user,@problem), class: "btn btn-default btn-sm", remote: true if @submission .panel-body - if @submission = render :partial => 'submission_short', - :locals => {:submission => @submission, :problem_name => @problem.name } + :locals => {submission: @submission, problem_name: @problem.name, problem_id: @problem.id } .row .col-md-12 %h2 Console @@ -40,7 +41,7 @@ :javascript $(document).ready(function() { e = ace.edit("editor") - e.setValue($("#text_haha").val()); + e.setValue($("#text_sourcecode").val()); e.gotoLine(1); $("#language_id").trigger('change'); brython(); diff --git a/app/views/submissions/get_latest_submission_status.js.haml b/app/views/submissions/get_latest_submission_status.js.haml --- a/app/views/submissions/get_latest_submission_status.js.haml +++ b/app/views/submissions/get_latest_submission_status.js.haml @@ -1,2 +1,2 @@ -:javascript +:plain $("#latest_status").html("#{j render({partial: 'submission_short', locals: {submission: @submission, problem_name: @problem.name}})}") diff --git a/app/views/submissions/index.html.haml b/app/views/submissions/index.html.haml --- a/app/views/submissions/index.html.haml +++ b/app/views/submissions/index.html.haml @@ -18,7 +18,7 @@ %table.table %thead %th No. - %th # + %th.text-right # %th At %th Source %th Result diff --git a/app/views/submissions/rejudge.js.haml b/app/views/submissions/rejudge.js.haml new file mode 100644 --- /dev/null +++ b/app/views/submissions/rejudge.js.haml @@ -0,0 +1,2 @@ +:plain + $("body").prepend("
Submission #{@submission.id}'s task status has been changed to \"#{@task.status_str}\". It will be re-judged soon.
") diff --git a/app/views/submissions/show.html.haml b/app/views/submissions/show.html.haml --- a/app/views/submissions/show.html.haml +++ b/app/views/submissions/show.html.haml @@ -6,6 +6,8 @@ //%div.highlight{:style => "border: 1px solid black;"} //=@formatted_code.html_safe + + .containter .row .col-md-7 @@ -64,7 +66,7 @@ %tr %td.text-right %strong Points - %td #{@submission.points}/#{@submission.problem.full_score} + %td #{@submission.points}/#{@submission.try(:problem).try(:full_score)} %tr %td.text-right %strong Comment @@ -81,9 +83,30 @@ %td.text-right %strong Compiler result %td - %pre= @submission.compiler_message + %button.btn.btn-info.btn-xs{type: 'button', data: {toggle: 'modal', target: '#compiler'}} + view - if session[:admin] %tr %td.text-right %strong IP %td #{@submission.ip_address} + %tr + %td.text-right + %strong Grading Task Status + %td + = @task.status_str if @task + - if session[:admin] + = link_to "rejudge", rejudge_submission_path, data: {remote: true}, class: 'btn btn-info btn-xs' + + +.modal.fade#compiler{tabindex: -1,role: 'dialog'} + .modal-dialog.modal-lg{role:'document'} + .modal-content + .modal-header + %button.close{type: 'button', data: {dismissed: :modal}, aria: {label: 'close'}} + %span{aria: {hidden: 'true'}, data: {dismiss: 'modal'}} × + %h4 Compiler message + .modal-body + %pre#compiler_msg= @submission.compiler_message + .modal-footer + %button.btn.btn-default{type: 'button', data: {dismiss: 'modal'}} Close diff --git a/app/views/testcases/show_problem.html.haml b/app/views/testcases/show_problem.html.haml new file mode 100644 --- /dev/null +++ b/app/views/testcases/show_problem.html.haml @@ -0,0 +1,25 @@ +%h1 Test cases +%h2= @problem.long_name + +/navbar +%ul.nav.nav-pills{role: :tablist} + - @problem.testcases.each.with_index do |tc,id| + %li{role: :presentation, class: ('active' if id == 0)} + %a{href:"#tc#{tc.id}", role: 'tab', data: {toggle: 'tab'}}= tc.num + +/actual data +.tab-content + - @problem.testcases.each.with_index do |tc,id| + .tab-pane{id: "tc#{tc.id}",class: ('active' if id == 0)} + .row + .col-md-6 + %h3 Input + = link_to "Download",download_input_testcase_path(tc),class: 'btn btn-info btn-sm' + .col-md-6 + %h3 Output + = link_to "Download",download_sol_testcase_path(tc),class: 'btn btn-info btn-sm' + .row + .col-md-6 + %textarea{ rows: 25,readonly: true,style: "width:100%;resize=none;overflow-y: scroll;"}= tc.input + .col-md-6 + %textarea{ rows: 25,readonly: true,style: "width:100%;resize=none;overflow-y: scroll;"}= tc.sol diff --git a/app/views/user_admin/bulk_manage.html.haml b/app/views/user_admin/bulk_manage.html.haml new file mode 100644 --- /dev/null +++ b/app/views/user_admin/bulk_manage.html.haml @@ -0,0 +1,77 @@ +%h1 Bulk Manage User + += form_tag bulk_manage_user_admin_path +.row + .col-md-6 + .panel.panel-primary + .panel-title.panel-heading + Filter User + .panel-body + Filtering users whose login match the following MySQL regex + .form-group + = label_tag "regex", 'Regex Pattern' + = text_field_tag "regex", params[:regex], class: 'form-control' + %p + Example + %ul + %li + %code root + matches every user whose login contains "root" + %li + %code ^56 + matches every user whose login starts with "56" + %li + %code 21$ + matches every user whose login ends with "21" + .col-md-6 + .panel.panel-primary + .panel-title.panel-heading + Action + .panel-body + .row.form-group + .col-md-6 + %label.checkbox-inline + = check_box_tag "enabled", true, params[:enabled] + Change "Enabled" to + .col-md-3 + %label.radio-inline + = radio_button_tag "enable", 1, params[:enable] == '1', id: 'enable-yes' + Yes + .col-md-3 + %label.radio-inline + = radio_button_tag "enable", 0, params[:enable] == '0', id: 'enable-no' + No + .row.form-group + .col-md-6 + %label.checkbox-inline + = check_box_tag "gen_password", true, params[:gen_password] + Generate new random password + +.row + .col-md-12 + = submit_tag "Preview Result", class: 'btn btn-default' +- if @users + .row + .col-md-4 + - if @action + %h2 Confirmation + - if @action[:set_enable] + .alert.alert-info The following users will be set #{(@action[:enabled] ? 'enable' : 'disable')}. + - if @action[:gen_password] + .alert.alert-info The password of the following users will be randomly generated. + .row + .col-md-4 + = submit_tag "Perform", class: 'btn btn-primary' + .row + .col-md-12 + The pattern matches #{@users.count} following users. + %br + - @users.each do |user| + = user.login + = ' ' + = user.full_name + = ' ' + = "(#{user.remark})" if user.remark + %br + + diff --git a/app/views/user_admin/index.html.haml b/app/views/user_admin/index.html.haml --- a/app/views/user_admin/index.html.haml +++ b/app/views/user_admin/index.html.haml @@ -42,6 +42,7 @@ = link_to '+ New user', { :action => 'new' }, { class: 'btn btn-success '} = link_to '+ New list of users', { :action => 'new_list' }, { class: 'btn btn-success '} = link_to 'View administrators',{ :action => 'admin'}, { class: 'btn btn-default '} + = link_to 'Bulk Manage', bulk_manage_user_admin_path , { class: 'btn btn-default '} = link_to 'Random passwords',{ :action => 'random_all_passwords'}, { class: 'btn btn-default '} = link_to 'View active users',{ :action => 'active'}, { class: 'btn btn-default '} = link_to 'Mass mailing',{ :action => 'mass_mailing'}, { class: 'btn btn-default '} @@ -84,7 +85,7 @@ %th - for user in @users %tr - %td= link_to user.login, controller: :users, :action => 'profile', :id => user + %td= link_to user.login, stat_user_path(user) %td= user.full_name %td= user.email %td= user.remark diff --git a/app/views/user_admin/new_list.html.erb b/app/views/user_admin/new_list.html.erb --- a/app/views/user_admin/new_list.html.erb +++ b/app/views/user_admin/new_list.html.erb @@ -1,8 +1,9 @@

Adding list of users

<%= form_tag :action => 'create_from_list' do %> -<%= submit_tag 'create users' %>
-List of user information in this format: user_id,name(,passwd(,alias))
-Note that passwd and alias is optional.
+ <%= submit_tag 'create users',class: 'btn btn-success'%>
+List of user information in this format: user_id,name(,passwd(,alias(,remark)))
+Note that passwd, alias and remark is optional.
+When passwd or alias is empty, the original value will be used instead.
<%= text_area_tag 'user_list', nil, :rows => 50, :cols => 80 %> <% end %> diff --git a/config/environments/development.rb b/config/environments/development.rb --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -6,8 +6,8 @@ # since you don't have to restart the web server when you make code changes. config.cache_classes = false - # Log error messages when you accidentally call methods on nil. - config.whiny_nils = true + # Log error messages when you accidentally call methods on nil. //DEPRICATED + # config.whiny_nils = true // DEPRICATED # Show full error reports and disable caching config.consider_all_requests_local = true @@ -23,11 +23,11 @@ config.action_dispatch.best_standards_support = :builtin # Raise exception on mass assignment protection for Active Record models - config.active_record.mass_assignment_sanitizer = :strict + # config.active_record.mass_assignment_sanitizer = :strict //DEPRICATED - # Log the query plan for queries taking more than this (works - # with SQLite, MySQL, and PostgreSQL) - config.active_record.auto_explain_threshold_in_seconds = 0.5 + # Log the query plan for queries taking more than this (works // DEPRICATED + # with SQLite, MySQL, and PostgreSQL) // DEPRICATED + # config.active_record.auto_explain_threshold_in_seconds = 0.5 // DEPRICATED # Do not compress assets config.assets.compress = false @@ -36,5 +36,7 @@ config.assets.debug = true # Prevents assets from rendering twice - config.serve_static_assets = true + config.serve_static_files = true + + config.eager_load = false end diff --git a/config/environments/production.rb b/config/environments/production.rb --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -9,7 +9,7 @@ config.action_controller.perform_caching = true # Disable Rails's static asset server (Apache or nginx will already do this) - config.serve_static_assets = false + config.serve_static_files = false # Compress JavaScripts and CSS config.assets.compress = true @@ -64,4 +64,6 @@ # Log the query plan for queries taking more than this (works # with SQLite, MySQL, and PostgreSQL) # config.active_record.auto_explain_threshold_in_seconds = 0.5 + + config.eager_load = true end diff --git a/config/environments/test.rb b/config/environments/test.rb --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -8,7 +8,7 @@ config.cache_classes = true # Configure static asset server for tests with Cache-Control for performance - config.serve_static_assets = true + config.serve_static_files = true config.static_cache_control = "public, max-age=3600" # Log error messages when you accidentally call methods on nil @@ -30,8 +30,14 @@ config.action_mailer.delivery_method = :test # Raise exception on mass assignment protection for Active Record models - config.active_record.mass_assignment_sanitizer = :strict + #config.active_record.mass_assignment_sanitizer = :strict // DEPRICATED # Print deprecation notices to the stderr config.active_support.deprecation = :stderr + + config.eager_load = false + + #test order + config.active_support.test_order = :sorted + end diff --git a/config/initializers/mime_types.rb b/config/initializers/mime_types.rb --- a/config/initializers/mime_types.rb +++ b/config/initializers/mime_types.rb @@ -3,4 +3,3 @@ # Add new mime types for use in respond_to blocks: # Mime::Type.register "text/richtext", :rtf # Mime::Type.register_alias "text/html", :iphone -Mime::Type.register 'application/pdf', :pdf diff --git a/config/initializers/secret_token.rb b/config/initializers/secret_token.rb deleted file mode 100644 --- a/config/initializers/secret_token.rb +++ /dev/null @@ -1,7 +0,0 @@ -# Be sure to restart your server when you modify this file. - -# Your secret key for verifying the integrity of signed cookies. -# If you change this key, all old signed cookies will become invalid! -# Make sure the secret is at least 30 characters and all random, -# no regular words or you'll be exposed to dictionary attacks. -CafeGrader::Application.config.secret_token = '7f85485d3d652fc6336dfe3cd98917d9bd7a323b32096bf7635d26b98ccd0480816cc2d12b5c10805cecf7d8fb322104e2bda71eb60dd871c5c537e56a063038' diff --git a/config/routes.rb b/config/routes.rb --- a/config/routes.rb +++ b/config/routes.rb @@ -3,6 +3,9 @@ root :to => 'main#login' + #logins + get 'login/login', to: 'login#login' + resources :contests resources :sites @@ -17,6 +20,7 @@ member do get 'toggle' get 'toggle_test' + get 'toggle_view_testcase' get 'stat' end collection do @@ -25,6 +29,17 @@ get 'import' get 'manage' end + + end + + resources :testcases, only: [] do + member do + get 'download_input' + get 'download_sol' + end + collection do + get 'show_problem/:problem_id(/:test_num)' => 'testcases#show_problem', as: 'show_problem' + end end resources :grader_configuration, controller: 'configurations' @@ -37,6 +52,11 @@ end resources :submissions do + member do + get 'download' + get 'compiler_msg' + get 'rejudge' + end collection do get 'prob/:problem_id', to: 'submissions#index', as: 'problem' get 'direct_edit_problem/:problem_id', to: 'submissions#direct_edit_problem', as: 'direct_edit_problem' @@ -44,14 +64,15 @@ end end - match 'tasks/view/:file.:ext' => 'tasks#view' - match 'tasks/download/:id/:file.:ext' => 'tasks#download' - match 'heartbeat/:id/edit' => 'heartbeat#edit' + #main get "main/list" get 'main/submission(/:id)', to: 'main#submission', as: 'main_submission' + #user admin + get 'user_admin/bulk_manage', to: 'user_admin#bulk_manage', as: 'bulk_manage_user_admin' + #report get 'report/current_score', to: 'report#current_score', as: 'report_current_score' get 'report/problem_hof(/:id)', to: 'report#problem_hof', as: 'report_problem_hof' @@ -59,15 +80,19 @@ get 'report/max_score', to: 'report#max_score', as: 'report_max_score' post 'report/show_max_score', to: 'report#show_max_score', as: 'report_show_max_score' + + # + get 'tasks/view/:file.:ext' => 'tasks#view' + get 'tasks/download/:id/:file.:ext' => 'tasks#download' + get 'heartbeat/:id/edit' => 'heartbeat#edit' + #grader get 'graders/list', to: 'graders#list', as: 'grader_list' - - match 'heartbeat/:id/edit' => 'heartbeat#edit' # See how all your routes lay out with "rake routes" # This is a legacy wild controller route that's not recommended for RESTful applications. # Note: This route will make all actions in every controller accessible via GET requests. - match ':controller(/:action(/:id))(.:format)' + match ':controller(/:action(/:id))(.:format)', via: [:get, :post] end diff --git a/config/secrets.yml.SAMPLE b/config/secrets.yml.SAMPLE new file mode 100644 --- /dev/null +++ b/config/secrets.yml.SAMPLE @@ -0,0 +1,8 @@ +development: + secret_key_base: '444f426d08add8e2d7cbd76e2057e521e06091231eb4d5472af6ba5654ea1124ce6a636f549be6827ce09561c314181226ad840d44e4677e1077942ee0dc82bd' + +test: + secret_key_base: 'd52f411b06a79cc9f56d92e10d27e670cf0f0c3357e7caf9018ec23091b5c452ea9266c03a5c9e37b72c358702d4d460e957f90dcc553c9fc73a98adb520e781' + +production: + secret_key_base: '7f85485d3d652fc6336dfe3cd98917d9bd7a323b32096bf7635d26b98ccd0480816cc2d12b5c10805cecf7d8fb322104e2bda71eb60dd871c5c537e56a063038' diff --git a/db/migrate/20161031063337_add_config_view_test.rb b/db/migrate/20161031063337_add_config_view_test.rb new file mode 100644 --- /dev/null +++ b/db/migrate/20161031063337_add_config_view_test.rb @@ -0,0 +1,16 @@ +class AddConfigViewTest < ActiveRecord::Migration + def up + GraderConfiguration.create key: 'right.view_testcase', value_type: 'boolean', value:'true', description:'When true, any user can view/download test data' + #uglily and dirtily and shamelessly check other config and inifialize + GraderConfiguration.where(key: 'right.user_hall_of_fame').first_or_create(value_type: 'boolean', value: 'false', + description: 'If true, any user can access hall of fame page.') + GraderConfiguration.where(key: 'right.multiple_ip_login').first_or_create(value_type: 'boolean', value: 'false', + description: 'When change from true to false, a user can login from the first IP they logged into afterward.') + GraderConfiguration.where(key: 'right.user_view_submission').first_or_create(value_type: 'boolean', value: 'false', + description: 'If true, any user can view submissions of every one.') + end + + def down + GraderConfiguration.where(key: 'right.view_testcase').destroy_all; + end +end diff --git a/db/migrate/20170123162543_change_testcase_size.rb b/db/migrate/20170123162543_change_testcase_size.rb new file mode 100644 --- /dev/null +++ b/db/migrate/20170123162543_change_testcase_size.rb @@ -0,0 +1,6 @@ +class ChangeTestcaseSize < ActiveRecord::Migration + def change + change_column :testcases, :input, :text, :limit => 4294967295 + change_column :testcases, :sol, :text, :limit => 4294967295 + end +end diff --git a/db/migrate/20170124024527_add_view_testcase_to_problem.rb b/db/migrate/20170124024527_add_view_testcase_to_problem.rb new file mode 100644 --- /dev/null +++ b/db/migrate/20170124024527_add_view_testcase_to_problem.rb @@ -0,0 +1,5 @@ +class AddViewTestcaseToProblem < ActiveRecord::Migration + def change + add_column :problems, :view_testcase, :bool + end +end diff --git a/db/migrate/20170310110146_add_index_to_task.rb b/db/migrate/20170310110146_add_index_to_task.rb new file mode 100644 --- /dev/null +++ b/db/migrate/20170310110146_add_index_to_task.rb @@ -0,0 +1,5 @@ +class AddIndexToTask < ActiveRecord::Migration + def change + add_index :tasks, :submission_id + end +end diff --git a/db/migrate/20170427070345_add_heart_beat_full.rb b/db/migrate/20170427070345_add_heart_beat_full.rb new file mode 100644 --- /dev/null +++ b/db/migrate/20170427070345_add_heart_beat_full.rb @@ -0,0 +1,9 @@ +class AddHeartBeatFull < ActiveRecord::Migration + def up + GraderConfiguration.create key: 'right.heartbeat_response_full', value_type: 'string', value:'RESTART', description:'Heart beat response text when user got full score (set this value to the empty string to disable this feature)' + end + + def down + + end +end diff --git a/db/schema.rb b/db/schema.rb --- a/db/schema.rb +++ b/db/schema.rb @@ -9,272 +9,275 @@ # from scratch. The latter is a flawed and unsustainable approach (the more migrations # you'll amass, the slower it'll run and the greater likelihood for issues). # -# It's strongly recommended to check this file into your version control system. +# It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(:version => 20161014091417) do +ActiveRecord::Schema.define(version: 20170427070345) do - create_table "announcements", :force => true do |t| - t.string "author" - t.text "body" + create_table "announcements", force: :cascade do |t| + t.string "author", limit: 255 + t.text "body", limit: 65535 t.boolean "published" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.boolean "frontpage", :default => false - t.boolean "contest_only", :default => false - t.string "title" - t.string "notes" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.boolean "frontpage", default: false + t.boolean "contest_only", default: false + t.string "title", limit: 255 + t.string "notes", limit: 255 end - create_table "contests", :force => true do |t| - t.string "title" + create_table "contests", force: :cascade do |t| + t.string "title", limit: 255 t.boolean "enabled" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.string "name" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.string "name", limit: 255 end - create_table "contests_problems", :id => false, :force => true do |t| - t.integer "contest_id" - t.integer "problem_id" + create_table "contests_problems", id: false, force: :cascade do |t| + t.integer "contest_id", limit: 4 + t.integer "problem_id", limit: 4 end - create_table "contests_users", :id => false, :force => true do |t| - t.integer "contest_id" - t.integer "user_id" + create_table "contests_users", id: false, force: :cascade do |t| + t.integer "contest_id", limit: 4 + t.integer "user_id", limit: 4 end - create_table "countries", :force => true do |t| - t.string "name" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + create_table "countries", force: :cascade do |t| + t.string "name", limit: 255 + t.datetime "created_at", null: false + t.datetime "updated_at", null: false end - create_table "descriptions", :force => true do |t| - t.text "body" + create_table "descriptions", force: :cascade do |t| + t.text "body", limit: 65535 t.boolean "markdowned" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false end - create_table "grader_configurations", :force => true do |t| - t.string "key" - t.string "value_type" - t.string "value" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.text "description" + create_table "grader_configurations", force: :cascade do |t| + t.string "key", limit: 255 + t.string "value_type", limit: 255 + t.string "value", limit: 255 + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.text "description", limit: 65535 end - create_table "grader_processes", :force => true do |t| - t.string "host" - t.integer "pid" - t.string "mode" + create_table "grader_processes", force: :cascade do |t| + t.string "host", limit: 255 + t.integer "pid", limit: 4 + t.string "mode", limit: 255 t.boolean "active" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.integer "task_id" - t.string "task_type" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.integer "task_id", limit: 4 + t.string "task_type", limit: 255 t.boolean "terminated" end - add_index "grader_processes", ["host", "pid"], :name => "index_grader_processes_on_ip_and_pid" + add_index "grader_processes", ["host", "pid"], name: "index_grader_processes_on_ip_and_pid", using: :btree - create_table "heart_beats", :force => true do |t| - t.integer "user_id" - t.string "ip_address" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.string "status" + create_table "heart_beats", force: :cascade do |t| + t.integer "user_id", limit: 4 + t.string "ip_address", limit: 255 + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.string "status", limit: 255 end - add_index "heart_beats", ["updated_at"], :name => "index_heart_beats_on_updated_at" + add_index "heart_beats", ["updated_at"], name: "index_heart_beats_on_updated_at", using: :btree - create_table "languages", :force => true do |t| - t.string "name", :limit => 10 - t.string "pretty_name" - t.string "ext", :limit => 10 - t.string "common_ext" + create_table "languages", force: :cascade do |t| + t.string "name", limit: 10 + t.string "pretty_name", limit: 255 + t.string "ext", limit: 10 + t.string "common_ext", limit: 255 end - create_table "logins", :force => true do |t| - t.integer "user_id" - t.string "ip_address" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + create_table "logins", force: :cascade do |t| + t.integer "user_id", limit: 4 + t.string "ip_address", limit: 255 + t.datetime "created_at", null: false + t.datetime "updated_at", null: false end - create_table "messages", :force => true do |t| - t.integer "sender_id" - t.integer "receiver_id" - t.integer "replying_message_id" - t.text "body" + create_table "messages", force: :cascade do |t| + t.integer "sender_id", limit: 4 + t.integer "receiver_id", limit: 4 + t.integer "replying_message_id", limit: 4 + t.text "body", limit: 65535 t.boolean "replied" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false end - create_table "problems", :force => true do |t| - t.string "name", :limit => 30 - t.string "full_name" - t.integer "full_score" + create_table "problems", force: :cascade do |t| + t.string "name", limit: 30 + t.string "full_name", limit: 255 + t.integer "full_score", limit: 4 t.date "date_added" t.boolean "available" - t.string "url" - t.integer "description_id" + t.string "url", limit: 255 + t.integer "description_id", limit: 4 t.boolean "test_allowed" t.boolean "output_only" - t.string "description_filename" + t.string "description_filename", limit: 255 + t.boolean "view_testcase" end - create_table "rights", :force => true do |t| - t.string "name" - t.string "controller" - t.string "action" + create_table "rights", force: :cascade do |t| + t.string "name", limit: 255 + t.string "controller", limit: 255 + t.string "action", limit: 255 end - create_table "rights_roles", :id => false, :force => true do |t| - t.integer "right_id" - t.integer "role_id" + create_table "rights_roles", id: false, force: :cascade do |t| + t.integer "right_id", limit: 4 + t.integer "role_id", limit: 4 end - add_index "rights_roles", ["role_id"], :name => "index_rights_roles_on_role_id" + add_index "rights_roles", ["role_id"], name: "index_rights_roles_on_role_id", using: :btree - create_table "roles", :force => true do |t| - t.string "name" + create_table "roles", force: :cascade do |t| + t.string "name", limit: 255 end - create_table "roles_users", :id => false, :force => true do |t| - t.integer "role_id" - t.integer "user_id" + create_table "roles_users", id: false, force: :cascade do |t| + t.integer "role_id", limit: 4 + t.integer "user_id", limit: 4 end - add_index "roles_users", ["user_id"], :name => "index_roles_users_on_user_id" + add_index "roles_users", ["user_id"], name: "index_roles_users_on_user_id", using: :btree - create_table "sessions", :force => true do |t| - t.string "session_id" - t.text "data" + create_table "sessions", force: :cascade do |t| + t.string "session_id", limit: 255 + t.text "data", limit: 65535 t.datetime "updated_at" end - add_index "sessions", ["session_id"], :name => "index_sessions_on_session_id" - add_index "sessions", ["updated_at"], :name => "index_sessions_on_updated_at" + add_index "sessions", ["session_id"], name: "index_sessions_on_session_id", using: :btree + add_index "sessions", ["updated_at"], name: "index_sessions_on_updated_at", using: :btree - create_table "sites", :force => true do |t| - t.string "name" + create_table "sites", force: :cascade do |t| + t.string "name", limit: 255 t.boolean "started" t.datetime "start_time" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.integer "country_id" - t.string "password" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.integer "country_id", limit: 4 + t.string "password", limit: 255 end - create_table "submission_view_logs", :force => true do |t| - t.integer "user_id" - t.integer "submission_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + create_table "submission_view_logs", force: :cascade do |t| + t.integer "user_id", limit: 4 + t.integer "submission_id", limit: 4 + t.datetime "created_at", null: false + t.datetime "updated_at", null: false end - create_table "submissions", :force => true do |t| - t.integer "user_id" - t.integer "problem_id" - t.integer "language_id" - t.text "source" - t.binary "binary" + create_table "submissions", force: :cascade do |t| + t.integer "user_id", limit: 4 + t.integer "problem_id", limit: 4 + t.integer "language_id", limit: 4 + t.text "source", limit: 65535 + t.binary "binary", limit: 65535 t.datetime "submitted_at" t.datetime "compiled_at" - t.text "compiler_message" + t.text "compiler_message", limit: 65535 t.datetime "graded_at" - t.integer "points" - t.text "grader_comment" - t.integer "number" - t.string "source_filename" - t.float "max_runtime" - t.integer "peak_memory" - t.integer "effective_code_length" - t.string "ip_address" + t.integer "points", limit: 4 + t.text "grader_comment", limit: 65535 + t.integer "number", limit: 4 + t.string "source_filename", limit: 255 + t.float "max_runtime", limit: 24 + t.integer "peak_memory", limit: 4 + t.integer "effective_code_length", limit: 4 + t.string "ip_address", limit: 255 end - add_index "submissions", ["user_id", "problem_id", "number"], :name => "index_submissions_on_user_id_and_problem_id_and_number", :unique => true - add_index "submissions", ["user_id", "problem_id"], :name => "index_submissions_on_user_id_and_problem_id" + add_index "submissions", ["user_id", "problem_id", "number"], name: "index_submissions_on_user_id_and_problem_id_and_number", unique: true, using: :btree + add_index "submissions", ["user_id", "problem_id"], name: "index_submissions_on_user_id_and_problem_id", using: :btree - create_table "tasks", :force => true do |t| - t.integer "submission_id" + create_table "tasks", force: :cascade do |t| + t.integer "submission_id", limit: 4 t.datetime "created_at" - t.integer "status" + t.integer "status", limit: 4 t.datetime "updated_at" end - create_table "test_pairs", :force => true do |t| - t.integer "problem_id" - t.text "input", :limit => 16777215 - t.text "solution", :limit => 16777215 - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + add_index "tasks", ["submission_id"], name: "index_tasks_on_submission_id", using: :btree + + create_table "test_pairs", force: :cascade do |t| + t.integer "problem_id", limit: 4 + t.text "input", limit: 16777215 + t.text "solution", limit: 16777215 + t.datetime "created_at", null: false + t.datetime "updated_at", null: false end - create_table "test_requests", :force => true do |t| - t.integer "user_id" - t.integer "problem_id" - t.integer "submission_id" - t.string "input_file_name" - t.string "output_file_name" - t.string "running_stat" - t.integer "status" - t.datetime "updated_at", :null => false + create_table "test_requests", force: :cascade do |t| + t.integer "user_id", limit: 4 + t.integer "problem_id", limit: 4 + t.integer "submission_id", limit: 4 + t.string "input_file_name", limit: 255 + t.string "output_file_name", limit: 255 + t.string "running_stat", limit: 255 + t.integer "status", limit: 4 + t.datetime "updated_at", null: false t.datetime "submitted_at" t.datetime "compiled_at" - t.text "compiler_message" + t.text "compiler_message", limit: 65535 t.datetime "graded_at" - t.string "grader_comment" - t.datetime "created_at", :null => false - t.float "running_time" - t.string "exit_status" - t.integer "memory_usage" + t.string "grader_comment", limit: 255 + t.datetime "created_at", null: false + t.float "running_time", limit: 24 + t.string "exit_status", limit: 255 + t.integer "memory_usage", limit: 4 end - add_index "test_requests", ["user_id", "problem_id"], :name => "index_test_requests_on_user_id_and_problem_id" + add_index "test_requests", ["user_id", "problem_id"], name: "index_test_requests_on_user_id_and_problem_id", using: :btree - create_table "testcases", :force => true do |t| - t.integer "problem_id" - t.integer "num" - t.integer "group" - t.integer "score" - t.text "input" - t.text "sol" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + create_table "testcases", force: :cascade do |t| + t.integer "problem_id", limit: 4 + t.integer "num", limit: 4 + t.integer "group", limit: 4 + t.integer "score", limit: 4 + t.text "input", limit: 4294967295 + t.text "sol", limit: 4294967295 + t.datetime "created_at" + t.datetime "updated_at" end - add_index "testcases", ["problem_id"], :name => "index_testcases_on_problem_id" + add_index "testcases", ["problem_id"], name: "index_testcases_on_problem_id", using: :btree - create_table "user_contest_stats", :force => true do |t| - t.integer "user_id" + create_table "user_contest_stats", force: :cascade do |t| + t.integer "user_id", limit: 4 t.datetime "started_at" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false t.boolean "forced_logout" end - create_table "users", :force => true do |t| - t.string "login", :limit => 50 - t.string "full_name" - t.string "hashed_password" - t.string "salt", :limit => 5 - t.string "alias" - t.string "email" - t.integer "site_id" - t.integer "country_id" - t.boolean "activated", :default => false + create_table "users", force: :cascade do |t| + t.string "login", limit: 50 + t.string "full_name", limit: 255 + t.string "hashed_password", limit: 255 + t.string "salt", limit: 5 + t.string "alias", limit: 255 + t.string "email", limit: 255 + t.integer "site_id", limit: 4 + t.integer "country_id", limit: 4 + t.boolean "activated", default: false t.datetime "created_at" t.datetime "updated_at" - t.boolean "enabled", :default => true - t.string "remark" - t.string "last_ip" - t.string "section" + t.boolean "enabled", default: true + t.string "remark", limit: 255 + t.string "last_ip", limit: 255 + t.string "section", limit: 255 end - add_index "users", ["login"], :name => "index_users_on_login", :unique => true + add_index "users", ["login"], name: "index_users_on_login", unique: true, using: :btree end diff --git a/db/seeds.rb b/db/seeds.rb --- a/db/seeds.rb +++ b/db/seeds.rb @@ -53,6 +53,7 @@ :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.' }, + #---------------------------- right -------------------------------- { :key => 'right.user_hall_of_fame', :value_type => 'boolean', @@ -74,6 +75,33 @@ :description => 'If true, any user can view submissions of every one.' }, + { + :key => 'right.bypass_agreement', + :value_type => 'boolean', + :default_value => 'true', + :description => 'When false, a user must accept usage agreement before login' + }, + + { + :key => 'right.heartbeat_response', + :value_type => 'string', + :default_value => 'OK', + :description => 'Heart beat response text' + }, + + { + :key => 'right.heartbeat_response_full', + :value_type => 'string', + :default_value => 'OK', + :description => 'Heart beat response text when user got full score (set this value to the empty string to disable this feature)' + }, + + { + :key => 'right.view_testcase', + :value_type => 'boolean', + :default_value => 'false', + :description => 'When true, any user can view/download test data' + }, # If Configuration['system.online_registration'] is true, the # system allows online registration, and will use these # information for sending confirmation emails. diff --git a/lib/grader_script.rb b/lib/grader_script.rb --- a/lib/grader_script.rb +++ b/lib/grader_script.rb @@ -49,10 +49,25 @@ output = `#{cmd}` Dir.chdir(cur_dir) - + return "import CMD: #{cmd}\n" + output end return '' end + def self.call_import_testcase(problem_name) + if GraderScript.grader_control_enabled? + cur_dir = `pwd`.chomp + Dir.chdir(GRADER_ROOT_DIR) + + script_name = File.join(GRADER_ROOT_DIR, "scripts/load_testcase") + cmd = "#{script_name} #{problem_name}" + + output = `#{cmd}` + + Dir.chdir(cur_dir) + return "Testcase import result:\n" + output + end + end + end diff --git a/lib/tasks/fixtures.rake b/lib/tasks/fixtures.rake new file mode 100644 --- /dev/null +++ b/lib/tasks/fixtures.rake @@ -0,0 +1,41 @@ +# Original from http://snippets.dzone.com/posts/show/4468 by MichaelBoutros +# +# Optimized version which uses to_yaml for content creation and checks +# that models are ActiveRecord::Base models before trying to fetch +# them from database. +namespace :db do + namespace :fixtures do + desc 'Dumps all models into fixtures.' + task :dump => :environment do + puts "rails root = #{Rails.root}" + models = Dir.glob(Rails.root.to_s + '/app/models/**.rb').map do |s| + Pathname.new(s).basename.to_s.gsub(/\.rb$/,'').camelize + end + + puts "Found models: " + models.join(', ') + + models.each do |m| + model = m.constantize + next unless model.ancestors.include?(ActiveRecord::Base) + + puts "Dumping model: " + m + entries = model.all.order(id: :asc) + + increment = 1 + + model_file = Rails.root.to_s + '/test/fixtures2/' + m.underscore.pluralize + '.yml' + File.open(model_file, 'w') do |f| + entries.each do |a| + attrs = a.attributes + attrs.delete_if{|k,v| v.blank?} + + output = {m + '_' + increment.to_s => attrs} + f << output.to_yaml.gsub(/^--- \n/,'') + "\n" + + increment += 1 + end + end + end + end + end +end diff --git a/lib/testdata_importer.rb b/lib/testdata_importer.rb --- a/lib/testdata_importer.rb +++ b/lib/testdata_importer.rb @@ -38,6 +38,9 @@ @log_msg << import_problem_pdf(dirname) @log_msg << import_full_score(dirname) + #import test data + @log_msg << GraderScript.call_import_testcase(@problem.name) + return true end diff --git a/spec/config_spec_helper.rb b/spec/config_spec_helper.rb deleted file mode 100644 --- a/spec/config_spec_helper.rb +++ /dev/null @@ -1,38 +0,0 @@ - -module ConfigSpecHelperMethods - - def find_or_create_and_set_config(key, type, value) - c = Configuration.find_by_key(key) - c ||= Configuration.new(:key => key, - :value_type => type) - c.value = value - c.save! - end - - def enable_multicontest - find_or_create_and_set_config(Configuration::MULTICONTESTS_KEY, - 'boolean','true') - end - - def disable_multicontest - find_or_create_and_set_config(Configuration::MULTICONTESTS_KEY, - 'boolean','false') - end - - def set_indv_contest_mode - find_or_create_and_set_config(Configuration::SYSTEM_MODE_CONF_KEY, - 'string','indv-contest') - end - - def set_standard_mode - find_or_create_and_set_config(Configuration::SYSTEM_MODE_CONF_KEY, - 'string','standard') - end - - def set_contest_time_limit(limit) - find_or_create_and_set_config(Configuration::CONTEST_TIME_LIMIT_KEY, - 'string',limit) - # clear old value - Configuration.contest_time_str = nil - end -end diff --git a/spec/controllers/main_controller_spec.rb b/spec/controllers/main_controller_spec.rb deleted file mode 100644 --- a/spec/controllers/main_controller_spec.rb +++ /dev/null @@ -1,193 +0,0 @@ -require 'delorean' - -require File.dirname(__FILE__) + '/../spec_helper' -require File.dirname(__FILE__) + '/../config_spec_helper' - -describe MainController, "when a user comes to list page" do - - it "should redirect user to login page when unlogged-in user try to access main/list" do - get 'list' - response.should redirect_to(:action => 'login') - end - -end - -describe MainController, "when a logged in user comes to list page, with multicontests off" do - integrate_views - - include ConfigSpecHelperMethods - - fixtures :users - fixtures :problems - fixtures :contests - - before(:each) do - disable_multicontest - end - - it "should list available problems" do - john = users(:john) - get "list", {}, {:user_id => john.id} - - response.should render_template 'main/list' - response.should have_text(/add/) - response.should have_text(/easy_problem/) - response.should have_text(/hard_problem/) - end - -end - -describe MainController, "when a logged in user comes to list page, with multicontests on" do - integrate_views - - include ConfigSpecHelperMethods - - fixtures :users - fixtures :problems - fixtures :contests - - before(:each) do - enable_multicontest - end - - it "should list only available public problems to users with no contest assigned" do - john = users(:john) - get "list", {}, {:user_id => john.id} - - response.should render_template('main/list') - response.should have_text(/add/) - response.should_not have_text(/easy_problem/) - response.should_not have_text(/hard_problem/) - end - - it "should list available problems on a specific contest" do - james = users(:james) - get "list", {}, {:user_id => james.id} - - response.should render_template('main/list') - response.should have_text(/add/) - response.should have_text(/easy_problem/) - response.should_not have_text(/hard_problem/) - end - - it "should shows available problems by contests" do - james = users(:james) - get "list", {}, {:user_id => james.id} - - response.should render_template('main/list') - response.should have_text(Regexp.new('Contest A.*easy_problem', Regexp::MULTILINE)) - end - - it "should shows available problems by contests; problems belonging to more the one contest should appear many times" do - jack = users(:jack) - get "list", {}, {:user_id => jack.id} - - response.should render_template('main/list') - response.should have_text(Regexp.new('Contest A.*easy_problem.*Contest B.*easy_problem', Regexp::MULTILINE)) - response.should have_text(Regexp.new('Contest B.*hard_problem', Regexp::MULTILINE)) - end -end - -describe MainController, "when a user loads sources and compiler messages" do - - before(:each) do - @problem = mock(Problem, :name => 'test', :output_only => false) - @language = mock(Language, :name => 'cpp', :ext => 'cpp') - @submission = mock(Submission, - :id => 1, - :user_id => 1, - :problem => @problem, - :language => @language, - :source => 'sample source', - :compiler_message => 'none') - - @user = mock(User, :id => 1, :login => 'john') - @user.should_receive(:update_start_time).at_most(:once) - - @another_user = mock(User, :id => 2, :login => 'mary') - @another_user.should_receive(:update_start_time).at_most(:once) - - User.should_receive(:find). - with(1).any_number_of_times. - and_return(@user) - User.should_receive(:find). - with(2).any_number_of_times. - and_return(@another_user) - Submission.should_receive(:find). - any_number_of_times.with(@submission.id.to_s). - and_return(@submission) - end - - it "should let user sees her own source" do - @submission.should_receive(:download_filename).and_return("foo.c") - get 'source', {:id => @submission.id}, {:user_id => 1} - response.should be_success - end - - it "should let user sees her own compiler message" do - get 'compiler_msg', {:id => @submission.id}, {:user_id => 1} - response.should be_success - end - - it "should not let user sees other user's source" do - get 'source', {:id => @submission.id}, {:user_id => 2} - flash[:notice].should =~ /[Ee]rror/ - response.should redirect_to(:action => 'list') - end - - it "should not let user sees other user's compiler message" do - get 'compiler_msg', {:id => @submission.id}, {:user_id => 2} - flash[:notice].should =~ /[Ee]rror/ - response.should redirect_to(:action => 'list') - end - -end - - -describe MainController, "during individual contest mode" do - - integrate_views - - include ConfigSpecHelperMethods - - fixtures :users - fixtures :problems - fixtures :contests - - before(:each) do - set_contest_time_limit('3:00') # 3 hours - set_indv_contest_mode - end - - it "should allow newly login user to see problem list" do - john = users(:john) - get "list", {}, {:user_id => john.id} - - response.should render_template 'main/list' - response.should have_text(/add/) - response.should have_text(/easy_problem/) - response.should have_text(/hard_problem/) - end - - it "should not show 'contest over' sign before the contest ends" do - john = users(:john) - get "list", {}, {:user_id => john.id} - - Delorean.time_travel_to(179.minutes.since) do - get "list", {}, {:user_id => john.id} - response.should_not have_text(/OVER/) - end - end - - it "should show 'contest over' sign after the contest ends" do - john = users(:john) - get "list", {}, {:user_id => john.id} - - Delorean.time_travel_to(181.minutes.since) do - get "list", {}, {:user_id => john.id} - response.should have_text(/OVER/) - end - end - -end - diff --git a/spec/controllers/sources_controller_spec.rb b/spec/controllers/sources_controller_spec.rb deleted file mode 100644 --- a/spec/controllers/sources_controller_spec.rb +++ /dev/null @@ -1,12 +0,0 @@ -require 'spec_helper' - -describe SourcesController do - - describe "GET 'direct_edit'" do - it "returns http success" do - get 'direct_edit' - response.should be_success - end - end - -end diff --git a/spec/controllers/submissions_controller_spec.rb b/spec/controllers/submissions_controller_spec.rb deleted file mode 100644 --- a/spec/controllers/submissions_controller_spec.rb +++ /dev/null @@ -1,160 +0,0 @@ -require 'spec_helper' - -# This spec was generated by rspec-rails when you ran the scaffold generator. -# It demonstrates how one might use RSpec to specify the controller code that -# was generated by Rails when you ran the scaffold generator. -# -# It assumes that the implementation code is generated by the rails scaffold -# generator. If you are using any extension libraries to generate different -# controller code, this generated spec may or may not pass. -# -# It only uses APIs available in rails and/or rspec-rails. There are a number -# of tools you can use to make these specs even more expressive, but we're -# sticking to rails and rspec-rails APIs to keep things simple and stable. -# -# Compared to earlier versions of this generator, there is very limited use of -# stubs and message expectations in this spec. Stubs are only used when there -# is no simpler way to get a handle on the object needed for the example. -# Message expectations are only used when there is no simpler way to specify -# that an instance is receiving a specific message. - -describe SubmissionsController do - - # This should return the minimal set of attributes required to create a valid - # Submission. As you add validations to Submission, be sure to - # adjust the attributes here as well. - let(:valid_attributes) { { } } - - # This should return the minimal set of values that should be in the session - # in order to pass any filters (e.g. authentication) defined in - # SubmissionsController. Be sure to keep this updated too. - let(:valid_session) { {} } - - describe "GET index" do - it "assigns all submissions as @submissions" do - submission = Submission.create! valid_attributes - get :index, {}, valid_session - assigns(:submissions).should eq([submission]) - end - end - - describe "GET show" do - it "assigns the requested submission as @submission" do - submission = Submission.create! valid_attributes - get :show, {:id => submission.to_param}, valid_session - assigns(:submission).should eq(submission) - end - end - - describe "GET new" do - it "assigns a new submission as @submission" do - get :new, {}, valid_session - assigns(:submission).should be_a_new(Submission) - end - end - - describe "GET edit" do - it "assigns the requested submission as @submission" do - submission = Submission.create! valid_attributes - get :edit, {:id => submission.to_param}, valid_session - assigns(:submission).should eq(submission) - end - end - - describe "POST create" do - describe "with valid params" do - it "creates a new Submission" do - expect { - post :create, {:submission => valid_attributes}, valid_session - }.to change(Submission, :count).by(1) - end - - it "assigns a newly created submission as @submission" do - post :create, {:submission => valid_attributes}, valid_session - assigns(:submission).should be_a(Submission) - assigns(:submission).should be_persisted - end - - it "redirects to the created submission" do - post :create, {:submission => valid_attributes}, valid_session - response.should redirect_to(Submission.last) - end - end - - describe "with invalid params" do - it "assigns a newly created but unsaved submission as @submission" do - # Trigger the behavior that occurs when invalid params are submitted - Submission.any_instance.stub(:save).and_return(false) - post :create, {:submission => { }}, valid_session - assigns(:submission).should be_a_new(Submission) - end - - it "re-renders the 'new' template" do - # Trigger the behavior that occurs when invalid params are submitted - Submission.any_instance.stub(:save).and_return(false) - post :create, {:submission => { }}, valid_session - response.should render_template("new") - end - end - end - - describe "PUT update" do - describe "with valid params" do - it "updates the requested submission" do - submission = Submission.create! valid_attributes - # Assuming there are no other submissions in the database, this - # specifies that the Submission created on the previous line - # receives the :update_attributes message with whatever params are - # submitted in the request. - Submission.any_instance.should_receive(:update_attributes).with({ "these" => "params" }) - put :update, {:id => submission.to_param, :submission => { "these" => "params" }}, valid_session - end - - it "assigns the requested submission as @submission" do - submission = Submission.create! valid_attributes - put :update, {:id => submission.to_param, :submission => valid_attributes}, valid_session - assigns(:submission).should eq(submission) - end - - it "redirects to the submission" do - submission = Submission.create! valid_attributes - put :update, {:id => submission.to_param, :submission => valid_attributes}, valid_session - response.should redirect_to(submission) - end - end - - describe "with invalid params" do - it "assigns the submission as @submission" do - submission = Submission.create! valid_attributes - # Trigger the behavior that occurs when invalid params are submitted - Submission.any_instance.stub(:save).and_return(false) - put :update, {:id => submission.to_param, :submission => { }}, valid_session - assigns(:submission).should eq(submission) - end - - it "re-renders the 'edit' template" do - submission = Submission.create! valid_attributes - # Trigger the behavior that occurs when invalid params are submitted - Submission.any_instance.stub(:save).and_return(false) - put :update, {:id => submission.to_param, :submission => { }}, valid_session - response.should render_template("edit") - end - end - end - - describe "DELETE destroy" do - it "destroys the requested submission" do - submission = Submission.create! valid_attributes - expect { - delete :destroy, {:id => submission.to_param}, valid_session - }.to change(Submission, :count).by(-1) - end - - it "redirects to the submissions list" do - submission = Submission.create! valid_attributes - delete :destroy, {:id => submission.to_param}, valid_session - response.should redirect_to(submissions_url) - end - end - -end diff --git a/spec/controllers/test_controller_spec.rb b/spec/controllers/test_controller_spec.rb deleted file mode 100644 --- a/spec/controllers/test_controller_spec.rb +++ /dev/null @@ -1,28 +0,0 @@ - -require File.dirname(__FILE__) + '/../spec_helper' - -describe TestController do - - before(:each) do - @john = mock(User, :id => "1", :login => 'john') - @john_result = mock(TestRequest, :id => "1", :user_id => @john.id) - @mary_result = mock(TestRequest, :id => "2", :user_id => @john.id + '1') - User.should_receive(:find).at_least(:once).with(@john.id).and_return(@john) - end - - it "should let user see her testing result" do - TestRequest.should_receive(:find).with(@john_result.id). - and_return(@john_result) - get 'result', {:id => @john_result.id}, {:user_id => @john.id} - response.should be_success - end - - it "should not let user see other's testing result" do - TestRequest.should_receive(:find).with(@mary_result.id). - and_return(@mary_result) - get 'result', {:id => @mary_result.id}, {:user_id => @john.id} - response.should redirect_to(:action => 'index') - end - -end - diff --git a/spec/controllers/user_admin_controller_spec.rb b/spec/controllers/user_admin_controller_spec.rb deleted file mode 100644 --- a/spec/controllers/user_admin_controller_spec.rb +++ /dev/null @@ -1,73 +0,0 @@ -require 'delorean' - -require File.dirname(__FILE__) + '/../spec_helper' -require File.dirname(__FILE__) + '/../config_spec_helper' - -describe UserAdminController, "when manage contest" do - - include ConfigSpecHelperMethods - - fixtures :users - fixtures :problems - fixtures :contests - fixtures :roles - - def change_users_contest_to(user_login_list, contest, reset_timer=false) - post_data = { - :contest => {:id => contest.id}, - :operation => 'assign', - :login_list => user_login_list - } - post_data[:reset_timer] = true if reset_timer - post 'manage_contest', post_data, {:user_id => @admin_user.id} - end - - before(:each) do - @admin_user = users(:mary) - @contest_b = contests(:contest_b) - @james = users(:james) - @jack = users(:jack) - - set_contest_time_limit('3:00') - set_indv_contest_mode - end - - it "should allow admin to see contest management page" do - get 'contest_management', {}, {:user_id => @admin_user.id} - - response.should render_template 'user_admin/contest_management' - end - - it "should change users' contest" do - change_users_contest_to("james\njack", @contest_b) - response.should redirect_to :action => 'contest_management' - - @james.contests(true).should include @contest_b - @jack.contests(true).should_not include @contest_a - end - - it "should reset users' timer when their contests change" do - @james.update_start_time - - Delorean.time_travel_to(190.minutes.since) do - @james.contest_finished?.should be_true - - change_users_contest_to("james", @contest_b, true) - - @james.contest_finished?.should be_false - end - end - - it "should set forced_logout flag for users when their contests change" do - @james.update_start_time - - Delorean.time_travel_to(190.minutes.since) do - @james.contest_finished?.should be_true - - change_users_contest_to("james", @contest_b, true) - - @james.contest_stat(true).forced_logout.should be_true - end - end - -end diff --git a/spec/controllers/users_controller_spec.rb b/spec/controllers/users_controller_spec.rb deleted file mode 100644 --- a/spec/controllers/users_controller_spec.rb +++ /dev/null @@ -1,100 +0,0 @@ - -require File.dirname(__FILE__) + '/../spec_helper' - -describe UsersController, "when a new user registers" do - - before(:each) do - # create john - - @john_info = {:login => 'john', - :full_name => 'John John', - :email => 'john@space.com'} - @john = User.new(@john_info) - - @john_activation_key = "123456" - - @john.should_receive(:activation_key). - any_number_of_times. - and_return(@john_activation_key) - - Configuration.new(:key => 'system.online_registration', - :value_type => 'boolean', - :value => 'true').save - - get :new - response.should render_template('users/new') - end - - it "should show the new form again when user information is invalid" do - User.should_receive(:new).with(any_args()).and_return(@john) - @john.should_receive(:activated=).with(false) - @john.should_receive(:valid?).and_return(false) - @john.should_not_receive(:save) - - post :register, :login => @john_info[:login], - :full_name => @john_info[:full_name], - :email => @john_info[:email] - - response.should render_template('users/new') - end - - it "should create unactivated user and send e-mail with activation key" do - User.should_receive(:new).with(any_args()).and_return(@john) - @john.should_receive(:activated=).with(false) - @john.should_receive(:valid?).and_return(true) - @john.should_receive(:save).and_return(true) - - smtp_mock = mock("smtp") - smtp_mock.should_receive(:send_message) do |msg,fr,to| - to.should == [@john_info[:email]] - msg.index(@john_activation_key).should_not be_nil - end - - Net::SMTP.should_receive(:start). - with(any_args()). - and_yield(smtp_mock) - - post :register, :login => @john_info[:login], - :full_name => @john_info[:full_name], - :email => @john_info[:email] - - response.should render_template('users/new_splash') - end - - it "should create unactivated user and return error page when e-mail sending error" do - User.should_receive(:new).with(any_args()).and_return(@john) - @john.should_receive(:activated=).with(false) - @john.should_receive(:valid?).and_return(true) - @john.should_receive(:save).and_return(true) - - smtp_mock = mock("smtp") - smtp_mock.should_receive(:send_message). - and_throw(:error) - - Net::SMTP.should_receive(:start). - with(any_args()). - and_yield(smtp_mock) - - post :register, :login => @john_info[:login], - :full_name => @john_info[:full_name], - :email => @john_info[:email] - - response.should render_template('users/email_error') - end - - it "should activate user with valid activation key" do - login = @john_info[:login] - User.should_receive(:find_by_login). - with(login). - and_return(@john) - User.should_not_receive(:find_by_email) - @john.should_receive(:valid?).and_return(true) - @john.should_receive(:activated=).with(true) - @john.should_receive(:save).and_return(true) - - get :confirm, :login => login, :activation => @john_activation_key - - response.should render_template('users/confirm') - end - -end diff --git a/spec/helpers/sources_helper_spec.rb b/spec/helpers/sources_helper_spec.rb deleted file mode 100644 --- a/spec/helpers/sources_helper_spec.rb +++ /dev/null @@ -1,15 +0,0 @@ -require 'spec_helper' - -# Specs in this file have access to a helper object that includes -# the SourcesHelper. For example: -# -# describe SourcesHelper do -# describe "string concat" do -# it "concats two strings with spaces" do -# expect(helper.concat_strings("this","that")).to eq("this that") -# end -# end -# end -describe SourcesHelper do - pending "add some examples to (or delete) #{__FILE__}" -end diff --git a/spec/helpers/submissions_helper_spec.rb b/spec/helpers/submissions_helper_spec.rb deleted file mode 100644 --- a/spec/helpers/submissions_helper_spec.rb +++ /dev/null @@ -1,15 +0,0 @@ -require 'spec_helper' - -# Specs in this file have access to a helper object that includes -# the SubmissionsHelper. For example: -# -# describe SubmissionsHelper do -# describe "string concat" do -# it "concats two strings with spaces" do -# expect(helper.concat_strings("this","that")).to eq("this that") -# end -# end -# end -describe SubmissionsHelper do - pending "add some examples to (or delete) #{__FILE__}" -end diff --git a/spec/integration/contest_managements_spec.rb b/spec/integration/contest_managements_spec.rb deleted file mode 100644 --- a/spec/integration/contest_managements_spec.rb +++ /dev/null @@ -1,136 +0,0 @@ -require 'spec_helper' -require 'config_spec_helper' -require 'delorean' - -describe "ContestManagements" do - include ConfigSpecHelperMethods - - fixtures :users - fixtures :problems - fixtures :contests - fixtures :roles - - before(:each) do - @admin_user = users(:mary) - @contest_b = contests(:contest_b) - @james = users(:james) - @jack = users(:jack) - - set_contest_time_limit('3:00') - set_indv_contest_mode - enable_multicontest - end - - it "should reset users' timer when their contests change" do - session = open_session - session.extend(MainSessionMethods) - - james_login_and_get_main_list(session) - session.response.should_not have_text(/OVER/) - - Delorean.time_travel_to(190.minutes.since) do - session.get_main_list - session.response.should have_text(/OVER/) - - session.get '/' # logout - session.get '/main/list' # clearly log out - session.response.should_not render_template 'main/list' - - admin_change_users_contest_to("james", @contest_b, true) - - james_login_and_get_main_list(session) - session.response.should_not have_text(/OVER/) - end - end - - it "should force users to log out when their contests change" do - session = open_session - session.extend(MainSessionMethods) - - james_login_and_get_main_list(session) - session.response.should_not have_text(/OVER/) - - Delorean.time_travel_to(190.minutes.since) do - session.get_main_list - session.response.should have_text(/OVER/) - - admin_change_users_contest_to("james", @contest_b, true) - - session.get '/main/list' - session.response.should_not render_template 'main/list' - session.should be_redirect - - Delorean.time_travel_to(200.minutes.since) do - james_login_and_get_main_list(session) - session.response.should_not have_text(/OVER/) - end - end - end - - it "should maintain admin logged-in sessions even when their contests change" do - session = open_session - session.extend(MainSessionMethods) - - session.login('mary', 'goodbye') - session.get_main_list - session.response.should_not have_text(/OVER/) - - Delorean.time_travel_to(190.minutes.since) do - session.get_main_list - session.response.should have_text(/OVER/) - - admin_change_users_contest_to("mary", @contest_b, true) - - session.get '/main/list' - session.response.should render_template 'main/list' - end - end - - private - - module MainSessionMethods - def login(login_name, password) - post '/login/login', :login => login_name, :password => password - assert_redirected_to '/main/list' - end - - def get_main_list - get '/main/list' - assert_template 'main/list' - end - - def get_main_list_and_assert_logout - get '/main/list' - assert_redirected_to '/main' - end - end - - module ContestManagementSessionMethods - def change_users_contest_to(user_login_list, contest, reset_timer=false) - post_data = { - :contest => {:id => contest.id}, - :operation => 'assign', - :login_list => user_login_list - } - post_data[:reset_timer] = true if reset_timer - post '/user_admin/manage_contest', post_data - end - end - - def admin_change_users_contest_to(user_list, contest, reset_timer) - admin_session = open_session - admin_session.extend(MainSessionMethods) - admin_session.extend(ContestManagementSessionMethods) - - admin_session.login('mary','goodbye') - admin_session.get '/main/list' - admin_session.change_users_contest_to(user_list, contest, reset_timer) - end - - def james_login_and_get_main_list(session) - session.login('james', 'morning') - session.get_main_list - end - -end - diff --git a/spec/models/configuration_spec.rb b/spec/models/configuration_spec.rb deleted file mode 100644 --- a/spec/models/configuration_spec.rb +++ /dev/null @@ -1,95 +0,0 @@ - -require File.dirname(__FILE__) + '/../spec_helper' - -describe Configuration, "when using cache" do - - before(:each) do - Configuration.cache = true - @int_config = mock(Configuration, - :id => 1, - :key => 'mode', - :value_type => 'integer', - :value => '30') - - @string_config = mock(Configuration, - :id => 2, - :key => 'title', - :value_type => 'string', - :value => 'Hello') - - @boolean_config = mock(Configuration, - :id => 3, - :key => 'single_user_mode', - :value_type => 'boolean', - :value => 'true') - end - - after(:each) do - Configuration.cache = false - end - - it "should retrieve int config" do - Configuration.should_receive(:find).once.with(:all). - and_return([@int_config, @string_config, @boolean_config]) - - Configuration.clear - val = Configuration.get('mode') - val.should == 30 - end - - it "should retrieve boolean config" do - Configuration.should_receive(:find).once.with(:all). - and_return([@int_config, @string_config, @boolean_config]) - - Configuration.clear - val = Configuration.get('single_user_mode') - val.should == true - end - - it "should retrieve string config" do - Configuration.should_receive(:find).once.with(:all). - and_return([@int_config, @string_config, @boolean_config]) - - Configuration.clear - val = Configuration.get('title') - val.should == "Hello" - end - - it "should retrieve config with []" do - Configuration.should_receive(:find).once.with(:all). - and_return([@int_config, @string_config, @boolean_config]) - - Configuration.clear - val = Configuration['title'] - val.should == "Hello" - end - - it "should read config table once" do - Configuration.should_receive(:find).once.with(:all). - and_return([@int_config, @string_config, @boolean_config]) - - Configuration.clear - val = Configuration.get('title') - val.should == "Hello" - val = Configuration.get('single_user_mode') - val.should == true - val = Configuration.get('mode') - val.should == 30 - end - - it "should be able to reload config" do - Configuration.should_receive(:find).twice.with(:all). - and_return([@int_config, @string_config, @boolean_config], - [mock(Configuration, - :key => 'title', :value_type => 'string', - :value => 'Goodbye')]) - - Configuration.clear - val = Configuration.get('title') - val.should == "Hello" - Configuration.reload - val = Configuration.get('title') - val.should == "Goodbye" - end - -end diff --git a/spec/models/login_spec.rb b/spec/models/login_spec.rb deleted file mode 100644 --- a/spec/models/login_spec.rb +++ /dev/null @@ -1,5 +0,0 @@ -require 'spec_helper' - -describe Login do - pending "add some examples to (or delete) #{__FILE__}" -end diff --git a/spec/models/site_spec.rb b/spec/models/site_spec.rb deleted file mode 100644 --- a/spec/models/site_spec.rb +++ /dev/null @@ -1,48 +0,0 @@ - -require File.dirname(__FILE__) + '/../spec_helper' - -describe Site do - - before(:each) do - start_time = Time.local(2008,5,10,9,00).gmtime - @site = Site.new({:name => 'Test site', - :started => true, - :start_time => start_time }) - @site.stub!(:start_time). - any_number_of_times. - and_return(start_time) - @site.stub!(:started).any_number_of_times.and_return(true) - end - - it "should report that the contest is not finished when the contest time limit is not set" do - Configuration.should_receive(:[]).with('contest.time_limit'). - and_return('unlimit') - @site.finished?.should == false - end - - it "should report that the contest is finished when the contest is over" do - Configuration.should_receive(:[]).with('contest.time_limit'). - and_return('5:00') - Time.stub!(:now). - and_return(Time.local(2008,5,10,14,01).gmtime) - @site.finished?.should == true end - - it "should report if the contest is finished correctly, when the contest is over, and the contest time contains some minutes" do - Configuration.should_receive(:[]).twice.with('contest.time_limit'). - and_return('5:15') - Time.stub!(:now). - and_return(Time.local(2008,5,10,14,14)) - @site.finished?.should == false - Time.stub!(:now). - and_return(Time.local(2008,5,10,14,16)) - @site.finished?.should == true - end - - it "should report that the contest is not finished, when the time is exactly at the finish time" do - Configuration.should_receive(:[]).with('contest.time_limit'). - and_return('5:00') - Time.stub!(:now).and_return(Time.local(2008,5,10,14,00)) - @site.finished?.should == false - end - -end diff --git a/spec/models/submission_spec.rb b/spec/models/submission_spec.rb deleted file mode 100644 --- a/spec/models/submission_spec.rb +++ /dev/null @@ -1,37 +0,0 @@ - -require File.dirname(__FILE__) + '/../spec_helper' - -describe Submission, "when verifying user submission" do - - before(:each) do - @submission = Submission.new - @submission.source = < 'cpp', :ext => 'cpp') - Language.should_receive(:find_by_name).with('C++').and_return(langcpp) - Submission.find_language_in_source(@submission.source).should == langcpp - end - - it "should find problem in source, when there is any" do - problem = stub(Problem, :name => 'testproblem') - Problem.should_receive(:find_by_name).with('testproblem').and_return(problem) - Submission.find_problem_in_source(@submission.source).should == problem - end - - it "should return nil when it cannot find problem in source" do - Submission.find_problem_in_source(< @user, - :problem => nil, - :submission => @submission, - :input_file_name => "somefile") - test_request.save.should == false - test_request.errors['problem'].should_not be_nil - end - - it "should validates that problem is available" do - @problem.should_receive(:available).and_return(false) - test_request = TestRequest.new(:user => @user, - :problem => @problem, - :submission => @submission, - :input_file_name => "somefile") - test_request.save.should == false - end - - it "should validates valid submission" do - @problem.should_receive(:available).and_return(true) - test_request = TestRequest.new(:user_id => @user.id, - :problem => @problem, - :submission => nil, - :input_file_name => "somefile") - test_request.save.should == false - end - -end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb deleted file mode 100644 --- a/spec/models/user_spec.rb +++ /dev/null @@ -1,163 +0,0 @@ -require File.dirname(__FILE__) + '/../spec_helper' -require File.dirname(__FILE__) + '/../config_spec_helper' - -describe User do - - before(:each) do - @password = "hello" - @salt = "123" - @john = stub_model(User, :salt => @salt, - :hashed_password => User.encrypt(@password,@salt)) - end - - it "should be authenticated if activated" do - @john.should_receive(:activated).and_return(true) - @john.authenticated?(@password).should == true - end - - it "should not be authenticated if inactivated" do - @john.should_receive(:activated).and_return(false) - @john.authenticated?(@password).should == false - end - - it "should not be authenticated if incorrect password is provided" do - @john.should_receive(:activated).and_return(true) - @john.should_receive(:hashed_password).and_return("byebye") - @john.authenticated?(@password).should == false - end - -end - -describe User, "during registration" do - - class User - public :encrypt_new_password - end - - before(:each) do - @john = User.new(:login => 'john', :password => 'hello') - @john.encrypt_new_password - end - - it "should produce and accept activation key" do - activation_key = @john.activation_key - - @john.verify_activation_key(activation_key).should == true - end - - it "should not accept invalid activation key" do - @john.verify_activation_key("12345").should == false - end -end - -describe User, "when re-register with the same e-mail" do - - before(:each) do - @mary_email = 'mary@in.th' - - @time_first_register = Time.local(2008,5,10,9,00).gmtime - - @mary_first = mock_model(User, - :login => 'mary1', - :password => 'hello', - :email => @mary_email, - :created_at => @time_first_register) - @mary_second = User.new(:login => 'mary2', - :password => 'hello', - :email => @mary_email) - User.stub!(:find_by_email). - with(@mary_email, {:order => "created_at DESC"}). - and_return(@mary_first) - end - - class User - public :enough_time_interval_between_same_email_registrations - end - - it "should not be allowed if the time interval is less than 5 mins" do - time_now = @time_first_register + 4.minutes - Time.stub!(:now).and_return(time_now) - - @mary_second.enough_time_interval_between_same_email_registrations - @mary_second.errors.length.should_not be_zero - end - - it "should be allowed if the time interval is more than 5 mins" do - time_now = @time_first_register + 6.minutes - Time.stub!(:now).and_return(time_now) - - @mary_second.enough_time_interval_between_same_email_registrations - @mary_second.errors.length.should be_zero - end - -end - -describe User, "as a class" do - - it "should be able to generate random password" do - password1 = User.random_password - password2 = User.random_password - - password1.should_not == password2 - end - -end - -describe User, "when requesting problem description," do - - include ConfigSpecHelperMethods - - fixtures :users - fixtures :problems - - before(:each) do - @james = users(:james) - @john = users(:john) - @jack = users(:jack) - @add = problems(:one) - @easy = problems(:easy) - @hard = problems(:hard) - end - - it "should check if a problem is in user's contests" do - @james.problem_in_user_contests?(@easy).should be_true - @james.problem_in_user_contests?(@hard).should be_false - - @john.problem_in_user_contests?(@easy).should be_false - @john.problem_in_user_contests?(@hard).should be_false - end - - it "should be able to view problem in user's contests, when multicontests is on" do - enable_multicontest - @james.can_view_problem?(@easy).should be_true - @jack.can_view_problem?(@easy).should be_true - @jack.can_view_problem?(@hard).should be_true - end - - it "should not be able to view problem not in user's contests, when multicontests is on" do - enable_multicontest - @james.can_view_problem?(@hard).should be_false - end - - it "with no assigned contest should not be able to view problem in contests when multicontests is on" do - enable_multicontest - @john.can_view_problem?(@add).should be_true - @john.can_view_problem?(@easy).should be_false - @john.can_view_problem?(@hard).should be_false - end - - it "should be able to view all available problems, when multicontests is off" do - disable_multicontest - @john.can_view_problem?(@easy).should be_true - @john.can_view_problem?(@hard).should be_true - @james.can_view_problem?(@easy).should be_true - @james.can_view_problem?(@hard).should be_true - end - - it "should be able to view public problems, when multicontests is on" do - enable_multicontest - @john.can_view_problem?(@add).should be_true - @james.can_view_problem?(@add).should be_true - end - -end diff --git a/spec/rcov.opts b/spec/rcov.opts deleted file mode 100644 --- a/spec/rcov.opts +++ /dev/null @@ -1,2 +0,0 @@ ---exclude "spec/*,gems/*" ---rails \ No newline at end of file diff --git a/spec/requests/submissions_spec.rb b/spec/requests/submissions_spec.rb deleted file mode 100644 --- a/spec/requests/submissions_spec.rb +++ /dev/null @@ -1,11 +0,0 @@ -require 'spec_helper' - -describe "Submissions" do - describe "GET /submissions" do - it "works! (now write some real specs)" do - # Run the generator again with the --webrat flag if you want to use webrat methods/matchers - get submissions_path - response.status.should be(200) - end - end -end diff --git a/spec/routing/submissions_routing_spec.rb b/spec/routing/submissions_routing_spec.rb deleted file mode 100644 --- a/spec/routing/submissions_routing_spec.rb +++ /dev/null @@ -1,35 +0,0 @@ -require "spec_helper" - -describe SubmissionsController do - describe "routing" do - - it "routes to #index" do - get("/submissions").should route_to("submissions#index") - end - - it "routes to #new" do - get("/submissions/new").should route_to("submissions#new") - end - - it "routes to #show" do - get("/submissions/1").should route_to("submissions#show", :id => "1") - end - - it "routes to #edit" do - get("/submissions/1/edit").should route_to("submissions#edit", :id => "1") - end - - it "routes to #create" do - post("/submissions").should route_to("submissions#create") - end - - it "routes to #update" do - put("/submissions/1").should route_to("submissions#update", :id => "1") - end - - it "routes to #destroy" do - delete("/submissions/1").should route_to("submissions#destroy", :id => "1") - end - - end -end diff --git a/spec/spec.opts b/spec/spec.opts deleted file mode 100644 --- a/spec/spec.opts +++ /dev/null @@ -1,4 +0,0 @@ ---colour ---format progress ---loadby mtime ---reverse diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb deleted file mode 100644 --- a/spec/spec_helper.rb +++ /dev/null @@ -1,38 +0,0 @@ -# This file is copied to spec/ when you run 'rails generate rspec:install' -ENV["RAILS_ENV"] ||= 'test' -require File.expand_path("../../config/environment", __FILE__) -require 'rspec/rails' -require 'rspec/autorun' - -# Requires supporting ruby files with custom matchers and macros, etc, -# in spec/support/ and its subdirectories. -Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f} - -RSpec.configure do |config| - # ## Mock Framework - # - # If you prefer to use mocha, flexmock or RR, uncomment the appropriate line: - # - # config.mock_with :mocha - # config.mock_with :flexmock - # config.mock_with :rr - - # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures - config.fixture_path = "#{::Rails.root}/spec/fixtures" - - # If you're not using ActiveRecord, or you'd prefer not to run each of your - # examples within a transaction, remove the following line or assign false - # instead of true. - config.use_transactional_fixtures = true - - # If true, the base class of anonymous controllers will be inferred - # automatically. This will be the default behavior in future versions of - # rspec-rails. - config.infer_base_class_for_anonymous_controllers = false - - # Run specs in random order to surface order dependencies. If you find an - # order dependency and want to debug it, you can fix the order by providing - # the seed, which is printed after each run. - # --seed 1234 - config.order = "random" -end diff --git a/spec/views/sources/direct_edit.html.haml_spec.rb b/spec/views/sources/direct_edit.html.haml_spec.rb deleted file mode 100644 --- a/spec/views/sources/direct_edit.html.haml_spec.rb +++ /dev/null @@ -1,5 +0,0 @@ -require 'spec_helper' - -describe "sources/direct_edit.html.haml" do - pending "add some examples to (or delete) #{__FILE__}" -end diff --git a/spec/views/submissions/edit.html.haml_spec.rb b/spec/views/submissions/edit.html.haml_spec.rb deleted file mode 100644 --- a/spec/views/submissions/edit.html.haml_spec.rb +++ /dev/null @@ -1,15 +0,0 @@ -require 'spec_helper' - -describe "submissions/edit" do - before(:each) do - @submission = assign(:submission, stub_model(Submission)) - end - - it "renders the edit submission form" do - render - - # Run the generator again with the --webrat flag if you want to use webrat matchers - assert_select "form[action=?][method=?]", submission_path(@submission), "post" do - end - end -end diff --git a/spec/views/submissions/index.html.haml_spec.rb b/spec/views/submissions/index.html.haml_spec.rb deleted file mode 100644 --- a/spec/views/submissions/index.html.haml_spec.rb +++ /dev/null @@ -1,15 +0,0 @@ -require 'spec_helper' - -describe "submissions/index" do - before(:each) do - assign(:submissions, [ - stub_model(Submission), - stub_model(Submission) - ]) - end - - it "renders a list of submissions" do - render - # Run the generator again with the --webrat flag if you want to use webrat matchers - end -end diff --git a/spec/views/submissions/new.html.haml_spec.rb b/spec/views/submissions/new.html.haml_spec.rb deleted file mode 100644 --- a/spec/views/submissions/new.html.haml_spec.rb +++ /dev/null @@ -1,15 +0,0 @@ -require 'spec_helper' - -describe "submissions/new" do - before(:each) do - assign(:submission, stub_model(Submission).as_new_record) - end - - it "renders new submission form" do - render - - # Run the generator again with the --webrat flag if you want to use webrat matchers - assert_select "form[action=?][method=?]", submissions_path, "post" do - end - end -end diff --git a/spec/views/submissions/show.html.haml_spec.rb b/spec/views/submissions/show.html.haml_spec.rb deleted file mode 100644 --- a/spec/views/submissions/show.html.haml_spec.rb +++ /dev/null @@ -1,12 +0,0 @@ -require 'spec_helper' - -describe "submissions/show" do - before(:each) do - @submission = assign(:submission, stub_model(Submission)) - end - - it "renders attributes in

" do - render - # Run the generator again with the --webrat flag if you want to use webrat matchers - end -end diff --git a/test/concurrent/task_test_setup.rb b/test/concurrent/task_test_setup.rb --- a/test/concurrent/task_test_setup.rb +++ b/test/concurrent/task_test_setup.rb @@ -2,7 +2,7 @@ require File.expand_path(File.dirname(__FILE__) + "/../../config/environment") def clear_all_tasks - Task.find(:all).each do |task| + Task.all.each do |task| task.destroy end end diff --git a/test/concurrent/task_test_teardown.rb b/test/concurrent/task_test_teardown.rb --- a/test/concurrent/task_test_teardown.rb +++ b/test/concurrent/task_test_teardown.rb @@ -2,13 +2,12 @@ require File.expand_path(File.dirname(__FILE__) + "/../../config/environment") def clear_all_tasks - Task.find(:all).each do |task| + Task.all.each do |task| task.destroy end end -puts Task.find(:all, - :conditions => {:status => Task::STATUS_COMPLETE}).length +puts Task.where(status: Task::STATUS_COMPLETE).length clear_all_tasks diff --git a/test/controllers/announcements_controller_test.rb b/test/controllers/announcements_controller_test.rb new file mode 100644 --- /dev/null +++ b/test/controllers/announcements_controller_test.rb @@ -0,0 +1,50 @@ +require 'test_helper' + +class AnnouncementsControllerTest < ActionController::TestCase + setup do + @announcement = announcements(:one) + @request.session[:user_id] = users(:admin).id + end + + test "should get index" do + get :index + assert_response :success + assert_not_nil assigns(:announcements) + end + + test "should get new" do + get :new + assert_response :success + end + + test "should create announcement" do + assert_difference('Announcement.count') do + post :create, announcement: { author: 'aa',body: 'bb', published: true, frontpage: true, title: 'test'} + end + + assert_redirected_to announcement_path(assigns(:announcement)) + end + + test "should show announcement" do + get :show, id: @announcement + assert_response :success + end + + test "should get edit" do + get :edit, id: @announcement + assert_response :success + end + + test "should update announcement" do + patch :update, id: @announcement, announcement: { author: 'aa',body: 'bb', published: true, frontpage: true, title: 'test'} + assert_redirected_to announcement_path(assigns(:announcement)) + end + + test "should destroy announcement" do + assert_difference('Announcement.count', -1) do + delete :destroy, id: @announcement + end + + assert_redirected_to announcements_path + end +end diff --git a/test/controllers/testcases_controller_test.rb b/test/controllers/testcases_controller_test.rb new file mode 100644 --- /dev/null +++ b/test/controllers/testcases_controller_test.rb @@ -0,0 +1,7 @@ +require 'test_helper' + +class TestcasesControllerTest < ActionController::TestCase + setup do + @testcase = testcases(:one) + end +end diff --git a/test/fixtures/configurations.yml b/test/fixtures/configurations.yml deleted file mode 100644 --- a/test/fixtures/configurations.yml +++ /dev/null @@ -1,7 +0,0 @@ -# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html - -# one: -# column: value -# -# two: -# column: value diff --git a/test/fixtures/grader_configurations.yml b/test/fixtures/grader_configurations.yml new file mode 100644 --- /dev/null +++ b/test/fixtures/grader_configurations.yml @@ -0,0 +1,144 @@ +GraderConfiguration_1: + key: system.single_user_mode + value_type: boolean + value: 'false' + description: Only admins can log in to the system when running under single user mode. + +GraderConfiguration_2: + key: ui.front.title + value_type: string + value: Grader + +GraderConfiguration_3: + key: ui.front.welcome_message + value_type: string + value: Welcome! + +GraderConfiguration_4: + key: ui.show_score + value_type: boolean + value: 'true' + +GraderConfiguration_5: + key: contest.time_limit + value_type: string + value: unlimited + description: Time limit in format hh:mm, or "unlimited" for contests with no time + limits. This config is CACHED. Restart the server before the change can take + effect. + +GraderConfiguration_6: + key: system.mode + value_type: string + value: standard + description: Current modes are "standard", "contest", "indv-contest", and "analysis". + + +GraderConfiguration_7: + key: contest.name + value_type: string + value: Grader + description: This name will be shown on the user header bar. + + +GraderConfiguration_8: + key: contest.multisites + value_type: boolean + value: 'false' + 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. + + +GraderConfiguration_9: + key: right.user_hall_of_fame + value_type: boolean + value: 'false' + description: If true, any user can access hall of fame page. + + +GraderConfiguration_10: + key: right.multiple_ip_login + value_type: boolean + value: 'true' + description: When change from true to false, a user can login from the first IP + they logged into afterward. + + +GraderConfiguration_11: + key: right.user_view_submission + value_type: boolean + value: 'false' + description: If true, any user can view submissions of every one. + + +GraderConfiguration_12: + key: right.bypass_agreement + value_type: boolean + value: 'true' + description: When false, a user must accept usage agreement before login + + +GraderConfiguration_13: + key: right.heartbeat_response + value_type: string + value: OK + description: Heart beat response text + + +GraderConfiguration_14: + key: right.view_testcase + value_type: boolean + value: 'false' + description: When true, any user can view/download test data + + +GraderConfiguration_15: + key: system.online_registration.smtp + value_type: string + value: smtp.somehost.com + + +GraderConfiguration_16: + key: system.online_registration.from + value_type: string + value: your.email@address + + +GraderConfiguration_17: + key: system.admin_email + value_type: string + value: admin@admin.email + + +GraderConfiguration_18: + key: system.user_setting_enabled + value_type: boolean + value: 'true' + description: If this option is true, users can change their settings + + +GraderConfiguration_19: + key: contest.test_request.early_timeout + value_type: boolean + value: 'false' + + +GraderConfiguration_20: + key: system.multicontests + value_type: boolean + value: 'false' + + +GraderConfiguration_21: + key: contest.confirm_indv_contest_start + value_type: boolean + value: 'false' + + +GraderConfiguration_22: + key: contest.default_contest_name + value_type: string + value: none + description: New user will be assigned to this contest automatically, if it exists. Set + to 'none' if there is no default contest. + diff --git a/test/fixtures/languages.yml b/test/fixtures/languages.yml --- a/test/fixtures/languages.yml +++ b/test/fixtures/languages.yml @@ -1,5 +1,36 @@ -# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html -one: - id: 1 -two: - id: 2 +Language_1: + name: c + pretty_name: C + ext: c + common_ext: c + +Language_2: + name: cpp + pretty_name: C++ + ext: cpp + common_ext: cpp,cc + +Language_3: + name: pas + pretty_name: Pascal + ext: pas + common_ext: pas + +Language_4: + name: ruby + pretty_name: Ruby + ext: rb + common_ext: rb + +Language_5: + name: python + pretty_name: Python + ext: py + common_ext: py + +Language_6: + name: java + pretty_name: Java + ext: java + common_ext: java + diff --git a/test/fixtures/users.yml b/test/fixtures/users.yml --- a/test/fixtures/users.yml +++ b/test/fixtures/users.yml @@ -13,10 +13,10 @@ salt: <%= salt %> activated: true -mary: - login: mary - full_name: mary - hashed_password: <%= User.encrypt("goodbye",salt) %> +admin: + login: admin + full_name: admin + hashed_password: <%= User.encrypt("admin",salt) %> salt: <%= salt %> roles: admin activated: true diff --git a/test/integration/admin_task_test.rb b/test/integration/admin_task_test.rb new file mode 100644 --- /dev/null +++ b/test/integration/admin_task_test.rb @@ -0,0 +1,7 @@ +require 'test_helper' + +class AdminTaskTest < ActionDispatch::IntegrationTest + # test "the truth" do + # assert true + # end +end diff --git a/test/integration/login_test.rb b/test/integration/login_test.rb new file mode 100644 --- /dev/null +++ b/test/integration/login_test.rb @@ -0,0 +1,40 @@ +require 'test_helper' + +class LoginTest < ActionDispatch::IntegrationTest + # test "the truth" do + # assert true + # end + + test "login with invalid information" do + get root_path + assert_response :success + post login_login_path, login: "root", password: "hahaha" + assert_redirected_to root_path + end + + test "normal user login" do + get root_path + assert_response :success + post login_login_path, {login: "john", password: "hello" } + assert_redirected_to main_list_path + end + + test "normal user login in single_user mode" do + GraderConfiguration.find_by(key: GraderConfiguration::SINGLE_USER_KEY).update_attributes(value: 'true') + GraderConfiguration.reload + get root_path + assert_response :success + post login_login_path, {login: "john", password: "hello" } + follow_redirect! + assert_redirected_to root_path + end + + test "root login in in single_user mode" do + GraderConfiguration.find_by(key: GraderConfiguration::SINGLE_USER_KEY).update_attributes(value: 'true') + GraderConfiguration.reload + get root_path + assert_response :success + post login_login_path, {login: "admin", password: "admin" } + assert_redirected_to main_list_path + end +end diff --git a/test/performance/browsing_test.rb b/test/performance/browsing_test.rb deleted file mode 100644 --- a/test/performance/browsing_test.rb +++ /dev/null @@ -1,12 +0,0 @@ -require 'test_helper' -require 'rails/performance_test_help' - -class BrowsingTest < ActionDispatch::PerformanceTest - # Refer to the documentation for all available options - # self.profile_options = { :runs => 5, :metrics => [:wall_time, :memory] - # :output => 'tmp/performance', :formats => [:flat] } - - def test_homepage - get '/' - end -end diff --git a/test/test_helper.rb b/test/test_helper.rb --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -2,7 +2,18 @@ require File.expand_path('../../config/environment', __FILE__) require 'rails/test_help' +#reporter for beautiful result +require "minitest/reporters" +Minitest::Reporters.use! + +module SignInHelper + def sign_in_as(user,password) + post login_login_path, {login: user, password: password } + end +end + class ActiveSupport::TestCase + include SignInHelper # Setup all fixtures in test/fixtures/*.(yml|csv) for all tests in alphabetical order. # # Note: You'll currently still have to declare fixtures explicitly in integration tests diff --git a/test/unit/.gitkeep b/test/unit/.gitkeep deleted file mode 100644 diff --git a/test/unit/announcement_test.rb b/test/unit/announcement_test.rb deleted file mode 100644 --- a/test/unit/announcement_test.rb +++ /dev/null @@ -1,8 +0,0 @@ -require File.dirname(__FILE__) + '/../test_helper' - -class AnnouncementTest < ActiveSupport::TestCase - # Replace this with your real tests. - def test_truth - assert true - end -end diff --git a/test/unit/configuration_test.rb b/test/unit/configuration_test.rb deleted file mode 100644 --- a/test/unit/configuration_test.rb +++ /dev/null @@ -1,8 +0,0 @@ -require File.dirname(__FILE__) + '/../test_helper' - -class ConfigurationTest < ActiveSupport::TestCase - # Replace this with your real tests. - def test_truth - assert true - end -end diff --git a/test/unit/contest_test.rb b/test/unit/contest_test.rb deleted file mode 100644 --- a/test/unit/contest_test.rb +++ /dev/null @@ -1,8 +0,0 @@ -require 'test_helper' - -class ContestTest < ActiveSupport::TestCase - # Replace this with your real tests. - test "the truth" do - assert true - end -end diff --git a/test/unit/country_test.rb b/test/unit/country_test.rb deleted file mode 100644 --- a/test/unit/country_test.rb +++ /dev/null @@ -1,8 +0,0 @@ -require File.dirname(__FILE__) + '/../test_helper' - -class CountryTest < ActiveSupport::TestCase - # Replace this with your real tests. - def test_truth - assert true - end -end diff --git a/test/unit/description_test.rb b/test/unit/description_test.rb deleted file mode 100644 --- a/test/unit/description_test.rb +++ /dev/null @@ -1,8 +0,0 @@ -require File.dirname(__FILE__) + '/../test_helper' - -class DescriptionTest < ActiveSupport::TestCase - # Replace this with your real tests. - def test_truth - assert true - end -end diff --git a/test/unit/grader_process_test.rb b/test/unit/grader_process_test.rb deleted file mode 100644 --- a/test/unit/grader_process_test.rb +++ /dev/null @@ -1,8 +0,0 @@ -require File.dirname(__FILE__) + '/../test_helper' - -class GraderProcessTest < ActiveSupport::TestCase - # Replace this with your real tests. - def test_truth - assert true - end -end diff --git a/test/unit/helpers/contest_management_helper_test.rb b/test/unit/helpers/contest_management_helper_test.rb deleted file mode 100644 --- a/test/unit/helpers/contest_management_helper_test.rb +++ /dev/null @@ -1,4 +0,0 @@ -require 'test_helper' - -class ContestManagementHelperTest < ActionView::TestCase -end diff --git a/test/unit/helpers/contests_helper_test.rb b/test/unit/helpers/contests_helper_test.rb deleted file mode 100644 --- a/test/unit/helpers/contests_helper_test.rb +++ /dev/null @@ -1,4 +0,0 @@ -require 'test_helper' - -class ContestsHelperTest < ActionView::TestCase -end diff --git a/test/unit/language_test.rb b/test/unit/language_test.rb deleted file mode 100644 --- a/test/unit/language_test.rb +++ /dev/null @@ -1,10 +0,0 @@ -require File.dirname(__FILE__) + '/../test_helper' - -class LanguageTest < Test::Unit::TestCase - fixtures :languages - - # Replace this with your real tests. - def test_truth - assert true - end -end diff --git a/test/unit/message_test.rb b/test/unit/message_test.rb deleted file mode 100644 --- a/test/unit/message_test.rb +++ /dev/null @@ -1,8 +0,0 @@ -require File.dirname(__FILE__) + '/../test_helper' - -class MessageTest < ActiveSupport::TestCase - # Replace this with your real tests. - def test_truth - assert true - end -end diff --git a/test/unit/problem_test.rb b/test/unit/problem_test.rb deleted file mode 100644 --- a/test/unit/problem_test.rb +++ /dev/null @@ -1,10 +0,0 @@ -require File.dirname(__FILE__) + '/../test_helper' - -class ProblemTest < Test::Unit::TestCase - fixtures :problems - - # Replace this with your real tests. - def test_truth - assert true - end -end diff --git a/test/unit/right_test.rb b/test/unit/right_test.rb deleted file mode 100644 --- a/test/unit/right_test.rb +++ /dev/null @@ -1,10 +0,0 @@ -require File.dirname(__FILE__) + '/../test_helper' - -class RightTest < Test::Unit::TestCase - fixtures :rights - - # Replace this with your real tests. - def test_truth - assert true - end -end diff --git a/test/unit/role_test.rb b/test/unit/role_test.rb deleted file mode 100644 --- a/test/unit/role_test.rb +++ /dev/null @@ -1,10 +0,0 @@ -require File.dirname(__FILE__) + '/../test_helper' - -class RoleTest < Test::Unit::TestCase - fixtures :roles - - # Replace this with your real tests. - def test_truth - assert true - end -end diff --git a/test/unit/site_test.rb b/test/unit/site_test.rb deleted file mode 100644 --- a/test/unit/site_test.rb +++ /dev/null @@ -1,8 +0,0 @@ -require File.dirname(__FILE__) + '/../test_helper' - -class SiteTest < ActiveSupport::TestCase - # Replace this with your real tests. - def test_truth - assert true - end -end diff --git a/test/unit/submission_test.rb b/test/unit/submission_test.rb deleted file mode 100644 --- a/test/unit/submission_test.rb +++ /dev/null @@ -1,10 +0,0 @@ -require File.dirname(__FILE__) + '/../test_helper' - -class SubmissionTest < Test::Unit::TestCase - fixtures :submissions - - # Replace this with your real tests. - def test_truth - assert true - end -end diff --git a/test/unit/task_test.rb b/test/unit/task_test.rb deleted file mode 100644 --- a/test/unit/task_test.rb +++ /dev/null @@ -1,41 +0,0 @@ -require File.dirname(__FILE__) + '/../test_helper' - -class TaskTest < Test::Unit::TestCase - fixtures :tasks - - self.use_transactional_fixtures = false - - def test_get_inqueue_simple - task1 = Task.get_inqueue_and_change_status(Task::STATUS_GRADING) - - assert_equal task1.id, 3, "should get the earliest task" - assert_equal task1.status, Task::STATUS_GRADING, "status changes" - - task2 = Task.get_inqueue_and_change_status(Task::STATUS_GRADING) - - assert_equal task2.id, 4, "should get the next task" - assert_equal task2.status, Task::STATUS_GRADING, "status changes" - end - - def generate_tasks(n) - n.times do |i| - Task.create(:submission_id => i, - :status => Task::STATUS_INQUEUE, - :create_at => Time.now + i.minutes) - end - end - - # use the process version in /test/concurrent instead - def UNUSED_test_get_inqueue_concurrent - ActiveRecord::Base.allow_concurrency = true - - task1 = Task.get_inqueue_and_change_status(Task::STATUS_GRADING) - - assert_equal task1.id, 3, "should get the earliest task" - assert_equal task1.status, Task::STATUS_GRADING, "status changes" - - ActiveRecord::Base.verify_active_connections! - end - -end - diff --git a/test/unit/test_pair_test.rb b/test/unit/test_pair_test.rb deleted file mode 100644 --- a/test/unit/test_pair_test.rb +++ /dev/null @@ -1,8 +0,0 @@ -require 'test_helper' - -class TestPairTest < ActiveSupport::TestCase - # Replace this with your real tests. - test "the truth" do - assert true - end -end diff --git a/test/unit/test_request_test.rb b/test/unit/test_request_test.rb deleted file mode 100644 --- a/test/unit/test_request_test.rb +++ /dev/null @@ -1,8 +0,0 @@ -require File.dirname(__FILE__) + '/../test_helper' - -class TestRequestTest < ActiveSupport::TestCase - # Replace this with your real tests. - def test_truth - assert true - end -end diff --git a/test/unit/user_contest_stat_test.rb b/test/unit/user_contest_stat_test.rb deleted file mode 100644 --- a/test/unit/user_contest_stat_test.rb +++ /dev/null @@ -1,8 +0,0 @@ -require 'test_helper' - -class UserContestStatTest < ActiveSupport::TestCase - # Replace this with your real tests. - test "the truth" do - assert true - end -end diff --git a/test/unit/user_test.rb b/test/unit/user_test.rb deleted file mode 100644 --- a/test/unit/user_test.rb +++ /dev/null @@ -1,10 +0,0 @@ -require File.dirname(__FILE__) + '/../test_helper' - -class UserTest < Test::Unit::TestCase - fixtures :users - - # Replace this with your real tests. - def test_truth - assert true - end -end