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 1 # Filters added to this controller apply to all controllers in the application.
2 2 # Likewise, all the methods added will be available for all controllers.
3 3
4 4 class ApplicationController < ActionController::Base
5 5 # Pick a unique cookie name to distinguish our session data from others'
6 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 20 protected
9 21 def authenticate
10 22 unless session[:user_id]
11 23 redirect_to :controller => 'main', :action => 'login'
12 24 return false
13 25 end
14 26
15 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 29 user = User.find(session[:user_id])
18 30 if user==nil or user.login != 'root'
19 31 redirect_to :controller => 'main', :action => 'login'
20 32 return false
21 33 end
22 34 end
23 35
24 36 return true
25 37 end
26 38
27 39 def authorization
28 40 return false unless authenticate
29 41 user = User.find(session[:user_id])
30 42 unless user.roles.detect { |role|
31 43 role.rights.detect{ |right|
32 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 48 flash[:notice] = 'You are not authorized to view the page you requested'
37 49 #request.env['HTTP_REFERER'] ? (redirect_to :back) : (redirect_to :controller => 'login')
38 50 redirect_to :controller => 'main', :action => 'login'
39 51 return false
40 52 end
41 53 end
42 54
43 55 end
44 56
@@ -2,25 +2,31
2 2
3 3 before_filter :authenticate, :except => [:index, :login]
4 4
5 5 verify :method => :post, :only => [:submit],
6 6 :redirect_to => { :action => :index }
7 7
8 8
9 9 def index
10 10 redirect_to :action => 'login'
11 11 end
12 12
13 13 def login
14 + saved_notice = flash[:notice]
14 15 reset_session
16 + flash[:notice] = saved_notice
17 +
18 + @title = Configuration['ui.front.title']
19 + @welcome = Configuration['ui.front.welcome_message']
20 +
15 21 render :action => 'login', :layout => 'empty'
16 22 end
17 23
18 24 def list
19 25 prepare_list_information
20 26 end
21 27
22 28 def submit
23 29 @submission = Submission.new(params[:submission])
24 30 @submission.user_id = session[:user_id]
25 31 @submission.language_id = 0
26 32 @submission.source = params['file'].read if params['file']!=''
@@ -10,24 +10,29
10 10 append_to menu_items, '[Submissions]', 'main', 'submission'
11 11 append_to menu_items, '[Test]', 'test', 'index'
12 12
13 13 # admin menu
14 14 if (user!=nil) and (user.admin?)
15 15 append_to menu_items, '[Problem admin]', 'problems', 'index'
16 16 append_to menu_items, '[User admin]', 'user_admin', 'index'
17 17 append_to menu_items, '[User stat]', 'user_admin', 'user_stat'
18 18 end
19 19
20 20 # general options
21 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 27 append_to menu_items, '[Log out]', 'main', 'login'
23 28
24 29 menu_items
25 30 end
26 31
27 32 def append_to(option,label, controller, action)
28 33 option << ' ' if option!=''
29 34 option << link_to_unless_current(label,
30 35 :controller => controller,
31 36 :action => action)
32 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 4 Please login to see the problem list.<br/><br/>
5 5
6 6 <% if flash[:notice] %>
7 7 <hr>
8 8 <b><%= flash[:notice] %></b>
9 9 <hr>
10 10 <% end %>
11 11
12 12 <div style="border: solid 1px gray; padding: 2px; background: #f0f0f0;">
13 13 <% form_tag :controller => 'login', :action => 'login' do %>
14 14 <table>
15 15 <tr>
@@ -53,15 +53,12
53 53 # inflect.uncountable %w( fish sheep )
54 54 # end
55 55
56 56 # Add new mime types for use in respond_to blocks:
57 57 # Mime::Type.register "text/richtext", :rtf
58 58 # Mime::Type.register "application/x-mobile", :mobile
59 59
60 60 # Include your application configuration below
61 61
62 62 # These are where inputs and outputs of test requests are stored
63 63 TEST_REQUEST_INPUT_FILE_DIR = RAILS_ROOT + '/data/test_request/input'
64 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 1 # This file is auto-generated from the current state of the database. Instead of editing this file,
2 2 # please use the migrations feature of ActiveRecord to incrementally modify your database, and
3 3 # then regenerate this schema definition.
4 4 #
5 5 # Note that this schema.rb definition is the authoritative source for your database schema. If you need
6 6 # to create the application database on another system, you should be using db:schema:load, not running
7 7 # all the migrations from scratch. The latter is a flawed and unsustainable approach (the more migrations
8 8 # you'll amass, the slower it'll run and the greater likelihood for issues).
9 9 #
10 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 22 create_table "grader_processes", :force => true do |t|
15 23 t.string "host", :limit => 20
16 24 t.integer "pid"
17 25 t.string "mode"
18 26 t.boolean "active"
19 27 t.datetime "created_at"
20 28 t.datetime "updated_at"
21 29 t.integer "task_id"
22 30 end
23 31
24 32 add_index "grader_processes", ["host", "pid"], :name => "index_grader_processes_on_ip_and_pid"
@@ -5,38 +5,38
5 5
6 6 before(:each) do
7 7 @problem = mock(Problem, :name => 'test')
8 8 @language = mock(Language, :name => 'cpp', :ext => 'cpp')
9 9 @submission = mock(Submission,
10 10 :id => 1,
11 11 :user_id => 1,
12 12 :problem => @problem,
13 13 :language => @language,
14 14 :source => 'sample source',
15 15 :compiler_message => 'none')
16 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 18 end
19 19
20 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 22 response.should be_success
23 23 end
24 24
25 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 27 response.should be_success
28 28 end
29 29
30 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 32 flash[:notice].should =~ /[Ee]rror/
33 33 response.should redirect_to(:action => 'list')
34 34 end
35 35
36 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 38 flash[:notice].should =~ /[Ee]rror/
39 39 response.should redirect_to(:action => 'list')
40 40 end
41 41
42 42 end
You need to be logged in to leave comments. Login now