Description:
[web] added configurations git-svn-id: http://theory.cpe.ku.ac.th/grader/web/trunk@156 6386c4cd-e34a-4fa8-8920-d93eb39b512e
Commit status:
[Not Reviewed]
References:
Comments:
0 Commit comments 0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
Add another comment

r76:d35e4fe536bb - - 16 files changed: 282 inserted, 13 deleted

@@ -0,0 +1,20
1 + class ConfigurationsController < ApplicationController
2 +
3 + before_filter :authenticate
4 + before_filter { |controller| controller.authorization_by_roles(['admin'])}
5 +
6 + in_place_edit_for :configuration, :key
7 + in_place_edit_for :configuration, :type
8 + in_place_edit_for :configuration, :value
9 +
10 + def index
11 + @configurations = Configuration.find(:all,
12 + :order => '`key`')
13 + end
14 +
15 + def reload
16 + Configuration.reload
17 + redirect_to :action => 'index'
18 + end
19 +
20 + end
@@ -0,0 +1,2
1 + module ConfigurationsHelper
2 + end
@@ -0,0 +1,43
1 + class Configuration < ActiveRecord::Base
2 +
3 + @@configurations = nil
4 +
5 + def self.get(key)
6 + if @@configurations == nil
7 + self.read_config
8 + end
9 + return @@configurations[key]
10 + end
11 +
12 + def self.[](key)
13 + self.get(key)
14 + end
15 +
16 + def self.reload
17 + self.read_config
18 + end
19 +
20 + def self.clear
21 + @@configurations = nil
22 + end
23 +
24 + protected
25 + def self.read_config
26 + @@configurations = {}
27 + Configuration.find(:all).each do |conf|
28 + key = conf.key
29 + val = conf.value
30 + case conf.value_type
31 + when 'string'
32 + @@configurations[key] = val
33 +
34 + when 'integer'
35 + @@configurations[key] = val.to_i
36 +
37 + when 'boolean'
38 + @@configurations[key] = (val=='true')
39 + end
40 + end
41 + end
42 +
43 + end
@@ -0,0 +1,26
1 + - content_for :head do
2 + = javascript_include_tag :defaults
3 +
4 + %h1 Grader configuration
5 +
6 + %table
7 + %tr
8 + %th Key
9 + %th Type
10 + %th Value
11 +
12 + - @configurations.each do |conf|
13 + - @configuration = conf
14 + %tr
15 + %td
16 + = in_place_editor_field :configuration, :key, {}, :rows=>1
17 + %td
18 + = in_place_editor_field :configuration, :value_type, {}, :rows=>1
19 + %td
20 + = in_place_editor_field :configuration, :value, {}, :rows=>1
21 +
22 + %br/
23 + = link_to '[Reload configuration]', :action => 'reload'
24 + %br/
25 + Your config is saved, but it does not automatically take effect.
26 + You must reload.
@@ -0,0 +1,37
1 + class CreateConfigurations < ActiveRecord::Migration
2 + def self.up
3 + create_table :configurations do |t|
4 + t.column :key, :string
5 + t.column :value_type, :string
6 + t.column :value, :string
7 + t.timestamps
8 + end
9 +
10 + Configuration.reset_column_information
11 +
12 + Configuration.create(:key => 'system.single_user_mode',
13 + :value_type => 'boolean',
14 + :value => 'false')
15 +
16 + Configuration.create(:key => 'ui.front.title',
17 + :value_type => 'string',
18 + :value => 'Grader')
19 +
20 + Configuration.create(:key => 'ui.front.welcome_message',
21 + :value_type => 'string',
22 + :value => 'Welcome!')
23 +
24 + Configuration.create(:key => 'ui.show_score',
25 + :value_type => 'boolean',
26 + :value => 'true')
27 +
28 + Configuration.create(:key => 'contest.time_limit',
29 + :value_type => 'string',
30 + :value => 'unlimited')
31 +
32 + end
33 +
34 + def self.down
35 + drop_table :configurations
36 + end
37 + end
@@ -0,0 +1,90
1 +
2 + require File.dirname(__FILE__) + '/../spec_helper'
3 +
4 + describe Configuration do
5 +
6 + before(:each) do
7 + @int_config = mock(Configuration,
8 + :id => 1,
9 + :key => 'mode',
10 + :value_type => 'integer',
11 + :value => '30')
12 +
13 + @string_config = mock(Configuration,
14 + :id => 2,
15 + :key => 'title',
16 + :value_type => 'string',
17 + :value => 'Hello')
18 +
19 + @boolean_config = mock(Configuration,
20 + :id => 3,
21 + :key => 'single_user_mode',
22 + :value_type => 'boolean',
23 + :value => 'true')
24 + end
25 +
26 + it "should retrieve int config" do
27 + Configuration.should_receive(:find).once.with(:all).
28 + and_return([@int_config, @string_config, @boolean_config])
29 +
30 + Configuration.clear
31 + val = Configuration.get('mode')
32 + val.should == 30
33 + end
34 +
35 + it "should retrieve boolean config" do
36 + Configuration.should_receive(:find).once.with(:all).
37 + and_return([@int_config, @string_config, @boolean_config])
38 +
39 + Configuration.clear
40 + val = Configuration.get('single_user_mode')
41 + val.should == true
42 + end
43 +
44 + it "should retrieve string config" do
45 + Configuration.should_receive(:find).once.with(:all).
46 + and_return([@int_config, @string_config, @boolean_config])
47 +
48 + Configuration.clear
49 + val = Configuration.get('title')
50 + val.should == "Hello"
51 + end
52 +
53 + it "should retrieve config with []" do
54 + Configuration.should_receive(:find).once.with(:all).
55 + and_return([@int_config, @string_config, @boolean_config])
56 +
57 + Configuration.clear
58 + val = Configuration['title']
59 + val.should == "Hello"
60 + end
61 +
62 + it "should read config table once" do
63 + Configuration.should_receive(:find).once.with(:all).
64 + and_return([@int_config, @string_config, @boolean_config])
65 +
66 + Configuration.clear
67 + val = Configuration.get('title')
68 + val.should == "Hello"
69 + val = Configuration.get('single_user_mode')
70 + val.should == true
71 + val = Configuration.get('mode')
72 + val.should == 30
73 + end
74 +
75 + it "should be able to reload config" do
76 + Configuration.should_receive(:find).twice.with(:all).
77 + and_return([@int_config, @string_config, @boolean_config],
78 + [mock(Configuration,
79 + :key => 'title', :value_type => 'string',
80 + :value => 'Goodbye')])
81 +
82 + Configuration.clear
83 + val = Configuration.get('title')
84 + val.should == "Hello"
85 + Configuration.reload
86 + val = Configuration.get('title')
87 + val.should == "Goodbye"
88 + end
89 +
90 + end
@@ -0,0 +1,7
1 + # Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html
2 +
3 + # one:
4 + # column: value
5 + #
6 + # two:
7 + # column: value
@@ -0,0 +1,8
1 + require File.dirname(__FILE__) + '/../test_helper'
2 +
3 + class ConfigurationsControllerTest < ActionController::TestCase
4 + # Replace this with your real tests.
5 + def test_truth
6 + assert true
7 + end
8 + end
@@ -0,0 +1,8
1 + require File.dirname(__FILE__) + '/../test_helper'
2 +
3 + class ConfigurationTest < ActiveSupport::TestCase
4 + # Replace this with your real tests.
5 + def test_truth
6 + assert true
7 + end
8 + end
@@ -1,44 +1,56
1 # Filters added to this controller apply to all controllers in the application.
1 # Filters added to this controller apply to all controllers in the application.
2 # Likewise, all the methods added will be available for all controllers.
2 # Likewise, all the methods added will be available for all controllers.
3
3
4 class ApplicationController < ActionController::Base
4 class ApplicationController < ActionController::Base
5 # Pick a unique cookie name to distinguish our session data from others'
5 # Pick a unique cookie name to distinguish our session data from others'
6 session :session_key => '_grader_session_id'
6 session :session_key => '_grader_session_id'
7
7
8 + SINGLE_USER_MODE_CONF_KEY = 'system.single_user_mode'
9 +
10 + def authorization_by_roles(allowed_roles)
11 + return false unless authenticate
12 + user = User.find(session[:user_id])
13 + unless user.roles.detect { |role| allowed_roles.member?(role.name) }
14 + flash[:notice] = 'You are not authorized to view the page you requested'
15 + redirect_to :controller => 'main', :action => 'login'
16 + return false
17 + end
18 + end
19 +
8 protected
20 protected
9 def authenticate
21 def authenticate
10 unless session[:user_id]
22 unless session[:user_id]
11 redirect_to :controller => 'main', :action => 'login'
23 redirect_to :controller => 'main', :action => 'login'
12 return false
24 return false
13 end
25 end
14
26
15 # check if run in single user mode
27 # check if run in single user mode
16 - if defined?(SINGLE_USER_MODE) and (SINGLE_USER_MODE)
28 + if (Configuration[SINGLE_USER_MODE_CONF_KEY])
17 user = User.find(session[:user_id])
29 user = User.find(session[:user_id])
18 if user==nil or user.login != 'root'
30 if user==nil or user.login != 'root'
19 redirect_to :controller => 'main', :action => 'login'
31 redirect_to :controller => 'main', :action => 'login'
20 return false
32 return false
21 end
33 end
22 end
34 end
23
35
24 return true
36 return true
25 end
37 end
26
38
27 def authorization
39 def authorization
28 return false unless authenticate
40 return false unless authenticate
29 user = User.find(session[:user_id])
41 user = User.find(session[:user_id])
30 unless user.roles.detect { |role|
42 unless user.roles.detect { |role|
31 role.rights.detect{ |right|
43 role.rights.detect{ |right|
32 right.controller == self.class.controller_name and
44 right.controller == self.class.controller_name and
33 - (right.action == 'all' or right.action == action_name)
45 + (right.action == 'all' or right.action == action_name)
34 }
46 }
35 }
47 }
36 flash[:notice] = 'You are not authorized to view the page you requested'
48 flash[:notice] = 'You are not authorized to view the page you requested'
37 #request.env['HTTP_REFERER'] ? (redirect_to :back) : (redirect_to :controller => 'login')
49 #request.env['HTTP_REFERER'] ? (redirect_to :back) : (redirect_to :controller => 'login')
38 redirect_to :controller => 'main', :action => 'login'
50 redirect_to :controller => 'main', :action => 'login'
39 return false
51 return false
40 end
52 end
41 end
53 end
42
54
43 end
55 end
44
56
@@ -2,25 +2,31
2
2
3 before_filter :authenticate, :except => [:index, :login]
3 before_filter :authenticate, :except => [:index, :login]
4
4
5 verify :method => :post, :only => [:submit],
5 verify :method => :post, :only => [:submit],
6 :redirect_to => { :action => :index }
6 :redirect_to => { :action => :index }
7
7
8
8
9 def index
9 def index
10 redirect_to :action => 'login'
10 redirect_to :action => 'login'
11 end
11 end
12
12
13 def login
13 def login
14 + saved_notice = flash[:notice]
14 reset_session
15 reset_session
16 + flash[:notice] = saved_notice
17 +
18 + @title = Configuration['ui.front.title']
19 + @welcome = Configuration['ui.front.welcome_message']
20 +
15 render :action => 'login', :layout => 'empty'
21 render :action => 'login', :layout => 'empty'
16 end
22 end
17
23
18 def list
24 def list
19 prepare_list_information
25 prepare_list_information
20 end
26 end
21
27
22 def submit
28 def submit
23 @submission = Submission.new(params[:submission])
29 @submission = Submission.new(params[:submission])
24 @submission.user_id = session[:user_id]
30 @submission.user_id = session[:user_id]
25 @submission.language_id = 0
31 @submission.language_id = 0
26 @submission.source = params['file'].read if params['file']!=''
32 @submission.source = params['file'].read if params['file']!=''
@@ -10,24 +10,29
10 append_to menu_items, '[Submissions]', 'main', 'submission'
10 append_to menu_items, '[Submissions]', 'main', 'submission'
11 append_to menu_items, '[Test]', 'test', 'index'
11 append_to menu_items, '[Test]', 'test', 'index'
12
12
13 # admin menu
13 # admin menu
14 if (user!=nil) and (user.admin?)
14 if (user!=nil) and (user.admin?)
15 append_to menu_items, '[Problem admin]', 'problems', 'index'
15 append_to menu_items, '[Problem admin]', 'problems', 'index'
16 append_to menu_items, '[User admin]', 'user_admin', 'index'
16 append_to menu_items, '[User admin]', 'user_admin', 'index'
17 append_to menu_items, '[User stat]', 'user_admin', 'user_stat'
17 append_to menu_items, '[User stat]', 'user_admin', 'user_stat'
18 end
18 end
19
19
20 # general options
20 # general options
21 append_to menu_items, '[Settings]', 'users', 'index'
21 append_to menu_items, '[Settings]', 'users', 'index'
22 +
23 + if (user!=nil) and (user.admin?)
24 + append_to menu_items, '[Site config]', 'configurations', 'index'
25 + end
26 +
22 append_to menu_items, '[Log out]', 'main', 'login'
27 append_to menu_items, '[Log out]', 'main', 'login'
23
28
24 menu_items
29 menu_items
25 end
30 end
26
31
27 def append_to(option,label, controller, action)
32 def append_to(option,label, controller, action)
28 option << ' ' if option!=''
33 option << ' ' if option!=''
29 option << link_to_unless_current(label,
34 option << link_to_unless_current(label,
30 :controller => controller,
35 :controller => controller,
31 :action => action)
36 :action => action)
32 end
37 end
33
38
@@ -1,15 +1,15
1 - <h1>Grader</h1>
1 + <h1><%= @title %></h1>
2
2
3 - <b>Welcome back!</b><br/>
3 + <b><%= @welcome %></b><br/>
4 Please login to see the problem list.<br/><br/>
4 Please login to see the problem list.<br/><br/>
5
5
6 <% if flash[:notice] %>
6 <% if flash[:notice] %>
7 <hr>
7 <hr>
8 <b><%= flash[:notice] %></b>
8 <b><%= flash[:notice] %></b>
9 <hr>
9 <hr>
10 <% end %>
10 <% end %>
11
11
12 <div style="border: solid 1px gray; padding: 2px; background: #f0f0f0;">
12 <div style="border: solid 1px gray; padding: 2px; background: #f0f0f0;">
13 <% form_tag :controller => 'login', :action => 'login' do %>
13 <% form_tag :controller => 'login', :action => 'login' do %>
14 <table>
14 <table>
15 <tr>
15 <tr>
@@ -53,15 +53,12
53 # inflect.uncountable %w( fish sheep )
53 # inflect.uncountable %w( fish sheep )
54 # end
54 # end
55
55
56 # Add new mime types for use in respond_to blocks:
56 # Add new mime types for use in respond_to blocks:
57 # Mime::Type.register "text/richtext", :rtf
57 # Mime::Type.register "text/richtext", :rtf
58 # Mime::Type.register "application/x-mobile", :mobile
58 # Mime::Type.register "application/x-mobile", :mobile
59
59
60 # Include your application configuration below
60 # Include your application configuration below
61
61
62 # These are where inputs and outputs of test requests are stored
62 # These are where inputs and outputs of test requests are stored
63 TEST_REQUEST_INPUT_FILE_DIR = RAILS_ROOT + '/data/test_request/input'
63 TEST_REQUEST_INPUT_FILE_DIR = RAILS_ROOT + '/data/test_request/input'
64 TEST_REQUEST_OUTPUT_FILE_DIR = RAILS_ROOT + '/data/test_request/output'
64 TEST_REQUEST_OUTPUT_FILE_DIR = RAILS_ROOT + '/data/test_request/output'
65 -
66 - # Uncomment this for single user mode (only root is allowed to log in)
67 - # SINGLE_USER_MODE = true
@@ -1,24 +1,32
1 # This file is auto-generated from the current state of the database. Instead of editing this file,
1 # This file is auto-generated from the current state of the database. Instead of editing this file,
2 # please use the migrations feature of ActiveRecord to incrementally modify your database, and
2 # please use the migrations feature of ActiveRecord to incrementally modify your database, and
3 # then regenerate this schema definition.
3 # then regenerate this schema definition.
4 #
4 #
5 # Note that this schema.rb definition is the authoritative source for your database schema. If you need
5 # Note that this schema.rb definition is the authoritative source for your database schema. If you need
6 # to create the application database on another system, you should be using db:schema:load, not running
6 # to create the application database on another system, you should be using db:schema:load, not running
7 # all the migrations from scratch. The latter is a flawed and unsustainable approach (the more migrations
7 # all the migrations from scratch. The latter is a flawed and unsustainable approach (the more migrations
8 # you'll amass, the slower it'll run and the greater likelihood for issues).
8 # you'll amass, the slower it'll run and the greater likelihood for issues).
9 #
9 #
10 # It's strongly recommended to check this file into your version control system.
10 # It's strongly recommended to check this file into your version control system.
11
11
12 - ActiveRecord::Schema.define(:version => 21) do
12 + ActiveRecord::Schema.define(:version => 22) do
13 +
14 + create_table "configurations", :force => true do |t|
15 + t.string "key"
16 + t.string "value_type"
17 + t.string "value"
18 + t.datetime "created_at"
19 + t.datetime "updated_at"
20 + end
13
21
14 create_table "grader_processes", :force => true do |t|
22 create_table "grader_processes", :force => true do |t|
15 t.string "host", :limit => 20
23 t.string "host", :limit => 20
16 t.integer "pid"
24 t.integer "pid"
17 t.string "mode"
25 t.string "mode"
18 t.boolean "active"
26 t.boolean "active"
19 t.datetime "created_at"
27 t.datetime "created_at"
20 t.datetime "updated_at"
28 t.datetime "updated_at"
21 t.integer "task_id"
29 t.integer "task_id"
22 end
30 end
23
31
24 add_index "grader_processes", ["host", "pid"], :name => "index_grader_processes_on_ip_and_pid"
32 add_index "grader_processes", ["host", "pid"], :name => "index_grader_processes_on_ip_and_pid"
@@ -5,38 +5,38
5
5
6 before(:each) do
6 before(:each) do
7 @problem = mock(Problem, :name => 'test')
7 @problem = mock(Problem, :name => 'test')
8 @language = mock(Language, :name => 'cpp', :ext => 'cpp')
8 @language = mock(Language, :name => 'cpp', :ext => 'cpp')
9 @submission = mock(Submission,
9 @submission = mock(Submission,
10 :id => 1,
10 :id => 1,
11 :user_id => 1,
11 :user_id => 1,
12 :problem => @problem,
12 :problem => @problem,
13 :language => @language,
13 :language => @language,
14 :source => 'sample source',
14 :source => 'sample source',
15 :compiler_message => 'none')
15 :compiler_message => 'none')
16 @user = mock(User, :id => 1, :login => 'john')
16 @user = mock(User, :id => 1, :login => 'john')
17 - Submission.should_receive(:find).with(@user.id.to_s).and_return(@submission)
17 + Submission.should_receive(:find).with(@submission.id.to_s).and_return(@submission)
18 end
18 end
19
19
20 it "should let user sees her own source" do
20 it "should let user sees her own source" do
21 - get 'source', {:id => 1}, {:user_id => 1}
21 + get 'source', {:id => @submission.id}, {:user_id => 1}
22 response.should be_success
22 response.should be_success
23 end
23 end
24
24
25 it "should let user sees her own compiler message" do
25 it "should let user sees her own compiler message" do
26 - get 'compiler_msg', {:id => 1}, {:user_id => 1}
26 + get 'compiler_msg', {:id => @submission.id}, {:user_id => 1}
27 response.should be_success
27 response.should be_success
28 end
28 end
29
29
30 it "should not let user sees other user's source" do
30 it "should not let user sees other user's source" do
31 - get 'source', {:id => 1}, {:user_id => 2}
31 + get 'source', {:id => @submission.id}, {:user_id => 2}
32 flash[:notice].should =~ /[Ee]rror/
32 flash[:notice].should =~ /[Ee]rror/
33 response.should redirect_to(:action => 'list')
33 response.should redirect_to(:action => 'list')
34 end
34 end
35
35
36 it "should not let user sees other user's compiler message" do
36 it "should not let user sees other user's compiler message" do
37 - get 'compiler_msg', {:id => 1}, {:user_id => 2}
37 + get 'compiler_msg', {:id => @submission.id}, {:user_id => 2}
38 flash[:notice].should =~ /[Ee]rror/
38 flash[:notice].should =~ /[Ee]rror/
39 response.should redirect_to(:action => 'list')
39 response.should redirect_to(:action => 'list')
40 end
40 end
41
41
42 end
42 end
You need to be logged in to leave comments. Login now