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
@@ -5,6 +5,18
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]
@@ -13,7 +25,7
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'
@@ -30,7 +42,7
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'
@@ -11,7 +11,13
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
@@ -19,6 +19,11
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
@@ -1,6 +1,6
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] %>
@@ -62,6 +62,3
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
@@ -9,7 +9,15
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
@@ -14,27 +14,27
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
You need to be logged in to leave comments. Login now