Description:
[web] added mode + access control, when sites started/finished git-svn-id: http://theory.cpe.ku.ac.th/grader/web/trunk@250 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

r122:dfa0387efb1e - - 9 files changed: 188 inserted, 84 deleted

@@ -0,0 +1,17
1 + class AddModeToConfigurations < ActiveRecord::Migration
2 + def self.up
3 +
4 + # Configuration['system.mode']:
5 + # * 'standard' mode
6 + # * 'contest' mode (check site start time/stop time)
7 + # * 'analysis' mode (show results, no new submissions)
8 +
9 + Configuration.create(:key => 'system.mode',
10 + :value_type => 'string',
11 + :value => 'standard')
12 + end
13 +
14 + def self.down
15 + Configuration.find_by_key('system.mode').destroy
16 + end
17 + end
@@ -1,129 +1,141
1 1 class MainController < ApplicationController
2 2
3 + SYSTEM_MODE_CONF_KEY = 'system.mode'
4 +
3 5 before_filter :authenticate, :except => [:index, :login]
6 + before_filter :check_viewability
4 7
5 8 #
6 9 # COMMENT OUT: filter in each action instead
7 10 #
8 11 # before_filter :verify_time_limit, :only => [:submit]
9 12
10 13 verify :method => :post, :only => [:submit],
11 14 :redirect_to => { :action => :index }
12 15
13 16
14 17 def index
15 18 redirect_to :action => 'login'
16 19 end
17 20
18 21 def login
19 22 saved_notice = flash[:notice]
20 23 reset_session
21 24 flash[:notice] = saved_notice
22 25
23 26 render :action => 'login', :layout => 'empty'
24 27 end
25 28
26 29 def list
27 30 prepare_list_information
28 31 end
29 32
30 33 def help
31 34 @user = User.find(session[:user_id])
32 35 end
33 36
34 37 def submit
35 38 user = User.find(session[:user_id])
36 39
37 40 @submission = Submission.new(params[:submission])
38 41 @submission.user = user
39 42 @submission.language_id = 0
40 43 if params['file']!=''
41 44 @submission.source = params['file'].read
42 45 @submission.source_filename = params['file'].original_filename
43 46 end
44 47 @submission.submitted_at = Time.new.gmtime
45 48
46 - if user.site!=nil and user.site.finished?
49 + if Configuration[SYSTEM_MODE_CONF_KEY]=='contest' and
50 + user.site!=nil and user.site.finished?
47 51 @submission.errors.add_to_base "The contest is over."
48 52 prepare_list_information
49 53 render :action => 'list' and return
50 54 end
51 55
52 56 if @submission.valid?
53 57 if @submission.save == false
54 58 flash[:notice] = 'Error saving your submission'
55 59 elsif Task.create(:submission_id => @submission.id,
56 60 :status => Task::STATUS_INQUEUE) == false
57 61 flash[:notice] = 'Error adding your submission to task queue'
58 62 end
59 63 else
60 64 prepare_list_information
61 65 render :action => 'list' and return
62 66 end
63 67 redirect_to :action => 'list'
64 68 end
65 69
66 70 def source
67 71 submission = Submission.find(params[:id])
68 72 if submission.user_id == session[:user_id]
69 73 if submission.problem.output_only
70 74 fname = submission.source_filename
71 75 else
72 76 fname = submission.problem.name + '.' + submission.language.ext
73 77 end
74 78 send_data(submission.source,
75 79 {:filename => fname,
76 80 :type => 'text/plain'})
77 81 else
78 82 flash[:notice] = 'Error viewing source'
79 83 redirect_to :action => 'list'
80 84 end
81 85 end
82 86
83 87 def compiler_msg
84 88 @submission = Submission.find(params[:id])
85 89 if @submission.user_id == session[:user_id]
86 90 render :action => 'compiler_msg', :layout => 'empty'
87 91 else
88 92 flash[:notice] = 'Error viewing source'
89 93 redirect_to :action => 'list'
90 94 end
91 95 end
92 96
93 97 def submission
94 98 @user = User.find(session[:user_id])
95 99 @problems = Problem.find_available_problems
96 100 if params[:id]==nil
97 101 @problem = nil
98 102 @submissions = nil
99 103 else
100 104 @problem = Problem.find_by_name(params[:id])
101 105 @submissions = Submission.find_all_by_user_problem(@user.id, @problem.id)
102 106 end
103 107 end
104 108
105 109 def error
106 110 @user = User.find(session[:user_id])
107 111 end
108 112
109 113 protected
110 114 def prepare_list_information
111 115 @problems = Problem.find_available_problems
112 116 @prob_submissions = Array.new
113 117 @user = User.find(session[:user_id])
114 118 @problems.each do |p|
115 119 sub = Submission.find_last_by_user_and_problem(@user.id,p.id)
116 120 if sub!=nil
117 121 @prob_submissions << { :count => sub.number, :submission => sub }
118 122 else
119 123 @prob_submissions << { :count => 0, :submission => nil }
120 124 end
121 125 end
122 126
123 127 @announcements = Announcement.find(:all,
124 128 :conditions => "published = 1",
125 129 :order => "created_at DESC")
126 130 end
127 131
132 + def check_viewability
133 + user = User.find(session[:user_id])
134 + if (!Configuration.show_tasks_to?(user)) and
135 + ((action_name=='submission') or (action_name=='submit'))
136 + redirect_to :action => 'list' and return
137 + end
138 + end
139 +
128 140 end
129 141
@@ -1,15 +1,24
1 1 class TasksController < ApplicationController
2 2
3 - before_filter :authenticate
4 -
3 + before_filter :authenticate, :check_viewability
5 4
6 5 def index
7 6 redirect_to :action => 'list'
8 7 end
9 8
10 9 def list
11 10 @problems = Problem.find_available_problems
12 11 @user = User.find(session[:user_id])
13 12 end
14 13
14 + protected
15 +
16 + def check_viewability
17 + user = User.find(session[:user_id])
18 + if user==nil or !Configuration.show_tasks_to?(user)
19 + redirect_to :controller => 'main', :action => 'list'
20 + return false
21 + end
22 + end
23 +
15 24 end
@@ -1,95 +1,108
1 1 class TestController < ApplicationController
2 2
3 - before_filter :authenticate
3 + SYSTEM_MODE_CONF_KEY = 'system.mode'
4 +
5 + before_filter :authenticate, :check_viewability
4 6
5 7 #
6 8 # COMMENT OUT: filter in each action instead
7 9 #
8 10 # before_filter :verify_time_limit, :only => [:submit]
9 11
10 12 verify :method => :post, :only => [:submit],
11 13 :redirect_to => { :action => :index }
12 14
13 15 def index
14 16 prepare_index_information
15 17 end
16 18
17 19 def submit
18 20 @user = User.find(session[:user_id])
19 21
20 22 @submitted_test_request = TestRequest.new_from_form_params(@user,params[:test_request])
21 23
22 24 if @submitted_test_request.errors.length != 0
23 25 prepare_index_information
24 26 render :action => 'index' and return
25 27 end
26 28
27 - if @user.site!=nil and @user.site.finished?
29 + if Configuration[SYSTEM_MODE_CONF_KEY]=='contest' and
30 + @user.site!=nil and @user.site.finished?
28 31 @submitted_test_request.errors.add_to_base('Contest is over.')
29 32 prepare_index_information
30 33 render :action => 'index' and return
31 34 end
32 35
33 36 if @submitted_test_request.save
34 37 redirect_to :action => 'index'
35 38 else
36 39 prepare_index_information
37 40 render :action => 'index'
38 41 end
39 42 end
40 43
41 44 def read
42 45 user = User.find(session[:user_id])
43 46 begin
44 47 test_request = TestRequest.find(params[:id])
45 48 rescue
46 49 test_request = nil
47 50 end
48 51 if test_request==nil or test_request.user_id != user.id
49 52 flash[:notice] = 'Invalid output'
50 53 redirect_to :action => 'index'
51 54 return
52 55 end
53 56 if test_request.output_file_name!=nil
54 57 data = File.open(test_request.output_file_name).read(2048)
55 58 if data==nil
56 59 data=""
57 60 end
58 61 send_data(data,
59 62 {:filename => 'output.txt',
60 63 :type => 'text/plain'})
61 64 return
62 65 end
63 66 redirect_to :action => 'index'
64 67 end
65 68
66 69 def result
67 70 @user = User.find(session[:user_id])
68 71 begin
69 72 @test_request = TestRequest.find(params[:id])
70 73 rescue
71 74 @test_request = nil
72 75 end
73 76 if @test_request==nil or @test_request.user_id != @user.id
74 77 flash[:notice] = 'Invalid request'
75 78 redirect_to :action => 'index'
76 79 return
77 80 end
78 81 end
79 82
80 83 protected
81 84
82 85 def prepare_index_information
83 86 @user = User.find(session[:user_id])
84 87 @submissions = Submission.find_last_for_all_available_problems(@user.id)
85 88 all_problems = @submissions.collect { |submission| submission.problem }
86 89 @problems = []
87 90 all_problems.each do |problem|
88 91 if problem.test_allowed
89 92 @problems << problem
90 93 end
91 94 end
92 95 @test_requests = @user.test_requests
93 96 end
94 97
98 + def check_viewability
99 + user = User.find(session[:user_id])
100 + if !Configuration.show_tasks_to?(user)
101 + redirect_to :controller => 'main', :action => 'list'
102 + end
103 + if (!Configuration.show_submitbox_to?(user)) and (action_name=='submit')
104 + redirect_to :controller => 'test', :action => 'index'
105 + end
106 + end
107 +
95 108 end
@@ -1,84 +1,106
1 1 # Methods added to this helper will be available to all templates in the application.
2 2 module ApplicationHelper
3 3
4 + SYSTEM_MODE_CONF_KEY = 'system.mode'
5 +
4 6 def user_header
5 7 menu_items = ''
6 8 user = User.find(session[:user_id])
7 9
8 10 if (user!=nil) and (session[:admin])
9 11 # admin menu
10 12 menu_items << "<b>Administrative task:</b> "
11 13 append_to menu_items, '[Announcements]', 'announcements', 'index'
12 14 append_to menu_items, '[Msg console]', 'messages', 'console'
13 15 append_to menu_items, '[Problem admin]', 'problems', 'index'
14 16 append_to menu_items, '[User admin]', 'user_admin', 'index'
15 17 append_to menu_items, '[User stat]', 'user_admin', 'user_stat'
16 18 append_to menu_items, '[Graders]', 'graders', 'list'
17 19 append_to menu_items, '[Site config]', 'configurations', 'index'
18 20 menu_items << "<br/>"
19 21 end
20 22
21 23 # main page
22 24 append_to menu_items, '[Main]', 'main', 'list'
23 25 append_to menu_items, '[Messages]', 'messages', 'list'
24 - append_to menu_items, '[Tasks]', 'tasks', 'list'
25 - append_to menu_items, '[Submissions]', 'main', 'submission'
26 - append_to menu_items, '[Test]', 'test', 'index'
26 +
27 + if (user!=nil) and (Configuration.show_tasks_to?(user))
28 + append_to menu_items, '[Tasks]', 'tasks', 'list'
29 + append_to menu_items, '[Submissions]', 'main', 'submission'
30 + append_to menu_items, '[Test]', 'test', 'index'
31 + end
27 32 append_to menu_items, '[Help]', 'main', 'help'
28 33 #append_to menu_items, '[Settings]', 'users', 'index'
29 34 append_to menu_items, '[Log out]', 'main', 'login'
30 35
31 36 menu_items
32 37 end
33 38
34 39 def append_to(option,label, controller, action)
35 40 option << ' ' if option!=''
36 41 option << link_to_unless_current(label,
37 42 :controller => controller,
38 43 :action => action)
39 44 end
40 45
41 46 def format_short_time(time)
42 47 now = Time.now.gmtime
43 48 st = ''
44 49 if (time.yday != now.yday) or
45 50 (time.year != now.year)
46 51 st = time.strftime("%x ")
47 52 end
48 53 st + time.strftime("%X")
49 54 end
50 55
56 + def read_textfile(fname,max_size=2048)
57 + begin
58 + File.open(fname).read(max_size)
59 + rescue
60 + nil
61 + end
62 + end
51 63
52 64 def user_title_bar(user)
53 - if user.site!=nil and user.site.finished?
54 - contest_over_string = <<CONTEST_OVER
65 + header = ''
66 +
67 + #
68 + # if the contest is over
69 + if Configuration[SYSTEM_MODE_CONF_KEY]=='contest' and
70 + user.site!=nil and user.site.finished?
71 + header = <<CONTEST_OVER
55 72 <tr><td colspan="2" align="center">
56 73 <span class="contest-over-msg">THE CONTEST IS OVER</span>
57 74 </td></tr>
58 75 CONTEST_OVER
59 76 end
77 +
78 + #
79 + # if the contest is in the anaysis mode
80 + if Configuration[SYSTEM_MODE_CONF_KEY]=='analysis'
81 + header = <<ANALYSISMODE
82 + <tr><td colspan="2" align="center">
83 + <span class="contest-over-msg">ANALYSIS MODE</span>
84 + </td></tr>
85 + ANALYSISMODE
86 + end
87 +
88 + #
89 + # build real title bar
60 90 <<TITLEBAR
61 91 <div class="title">
62 92 <table>
63 - #{contest_over_string}
93 + #{header}
64 94 <tr>
65 95 <td class="left-col">
66 96 #{user.full_name}<br/>
67 97 Current time is #{format_short_time(Time.new.gmtime)} UTC<br/>
68 98 </td>
69 99 <td class="right-col">APIO'08</td>
70 100 </tr>
71 101 </table>
72 102 </div>
73 103 TITLEBAR
74 104 end
75 105
76 - def read_textfile(fname,max_size=2048)
77 - begin
78 - File.open(fname).read(max_size)
79 - rescue
80 - nil
81 - end
82 - end
83 -
84 106 end
@@ -1,43 +1,70
1 + #
2 + # This class also contains various login of the system.
3 + #
1 4 class Configuration < ActiveRecord::Base
2 5
6 + SYSTEM_MODE_CONF_KEY = 'system.mode'
7 +
3 8 @@configurations = nil
4 9
5 10 def self.get(key)
6 11 if @@configurations == nil
7 12 self.read_config
8 13 end
9 14 return @@configurations[key]
10 15 end
11 16
12 17 def self.[](key)
13 18 self.get(key)
14 19 end
15 20
16 21 def self.reload
17 22 self.read_config
18 23 end
19 24
20 25 def self.clear
21 26 @@configurations = nil
22 27 end
23 28
29 + #
30 + # View decision
31 + #
32 + def self.show_submitbox_to?(user)
33 + mode = get(SYSTEM_MODE_CONF_KEY)
34 + return false if mode=='analysis'
35 + if (mode=='contest')
36 + return false if (user.site!=nil) and
37 + ((user.site.started==false) or (user.site.finished?))
38 + end
39 + return true
40 + end
41 +
42 + def self.show_tasks_to?(user)
43 + mode = get(SYSTEM_MODE_CONF_KEY)
44 + if (mode=='contest')
45 + return false if (user.site!=nil) and (user.site.started==false)
46 + end
47 + return true
48 + end
49 +
50 +
24 51 protected
25 52 def self.read_config
26 53 @@configurations = {}
27 54 Configuration.find(:all).each do |conf|
28 55 key = conf.key
29 56 val = conf.value
30 57 case conf.value_type
31 58 when 'string'
32 59 @@configurations[key] = val
33 60
34 61 when 'integer'
35 62 @@configurations[key] = val.to_i
36 63
37 64 when 'boolean'
38 65 @@configurations[key] = (val=='true')
39 66 end
40 67 end
41 68 end
42 69
43 70 end
@@ -1,30 +1,32
1 1 = user_title_bar(@user)
2 2
3 3 - if @announcements.length!=0
4 4 .announcementbox
5 5 %span{:class => 'title'}
6 6 Announcements
7 7 = render :partial => 'announcement', :collection => @announcements
8 8
9 - .submitbox
10 - = error_messages_for 'submission'
11 - = render :partial => 'submission_box'
9 + - if Configuration.show_submitbox_to?(@user)
10 + .submitbox
11 + = error_messages_for 'submission'
12 + = render :partial => 'submission_box'
12 13
13 14
14 15 %hr/
15 16
16 - %table.info
17 - %tr.info-head
18 - %th
19 - %th Tasks
20 - %th # of sub(s)
21 - %th Results
22 - = render :partial => 'problem', :collection => @problems
17 + - if Configuration.show_tasks_to?(@user)
18 + %table.info
19 + %tr.info-head
20 + %th
21 + %th Tasks
22 + %th # of sub(s)
23 + %th Results
24 + = render :partial => 'problem', :collection => @problems
23 25
24 26 %hr/
25 27
26 28 %p
27 29 %b Note:
28 30 We currently have problems synchronizing
29 31 the time stamps between grading machines.
30 32 You will see weird time stamps during the practice session.
@@ -1,105 +1,107
1 1 <%= user_title_bar(@user) %>
2 2
3 3 <h2>Test Interface</h2>
4 4
5 5 <% if @problems.length==0 %>
6 6 There is no submission
7 7 <% else %>
8 8
9 9 <script type="text/javascript">
10 10 var submissionCount = new Array();
11 11 <% @submissions.each do |submission| %>
12 12 submissionCount[<%= submission.problem_id %>]=<%= submission.number %>;
13 13 <% end %>
14 14
15 15 function updateSubmissionList() {
16 16 currentProb = document.getElementById("test_request_problem_id").value;
17 17 count = submissionCount[currentProb];
18 18 submissionSelect = document.getElementById("test_request_submission_number");
19 19 old_len = submissionSelect.length;
20 20 // clear the box
21 21 for(i=0; i<old_len; i++)
22 22 submissionSelect.remove(0);
23 23 for(i=count; i>=1; i--) {
24 24 try {
25 25 submissionSelect.add(new Option(""+i,""+i,false,false),null);
26 26 } catch(ex) {
27 27 submissionSelect.add(new Option(""+i,""+i,false,false));
28 28 }
29 29 }
30 30 }
31 31 </script>
32 32
33 - <div class="submitbox">
34 - <%= error_messages_for 'submitted_test_request' %>
35 - <% form_for :test_request, nil,
36 - :url => { :action => 'submit'},
37 - :html => { :multipart => true } do |f| %>
38 - <table>
39 - <tr>
40 - <td>Task:</td>
41 - <td>
42 - <%= select(:test_request,
43 - :problem_id,
44 - @problems.collect {|p| [p.name, p.id]}, {},
45 - { :onclick => "updateSubmissionList();" }) %>
46 - </td>
47 - </tr>
48 - <tr>
49 - <td>Submission:</td>
50 - <td>
51 - <%= select(:test_request,
52 - :submission_number,
53 - ((1..@submissions[0].number).collect {|n| [n,n]}).reverse) %>
54 - </td>
55 - </tr>
56 - <tr>
57 - <td>Input data:</td>
58 - <td>
59 - <%= f.file_field :input_file %>
60 - </td>
61 - <td>
62 - (combined size should not exceed 2MB)
63 - </td>
64 - </tr>
65 - <tr>
66 - <td>
67 - Additional file<sup><span style="color:red">*</span></sup>:
68 - </td>
69 - <td>
70 - <%= f.file_field :additional_file %>
71 - </td>
72 - <td>
73 - <small>
74 - * This option works <u>only</u> for task max.
75 - You can use this to submit <tt>questions.txt</tt>.<br/>
76 - The file shall be copied to the execution directory before your program runs.
77 - </small>
78 - </td>
79 - </tr>
80 - <tr>
81 - <td colspan="2">
82 - <%= submit_tag 'submit' %>
83 - </td>
84 - </tr>
85 - </table>
33 + <% if Configuration.show_submitbox_to?(@user) %>
34 + <div class="submitbox">
35 + <%= error_messages_for 'submitted_test_request' %>
36 + <% form_for :test_request, nil,
37 + :url => { :action => 'submit'},
38 + :html => { :multipart => true } do |f| %>
39 + <table>
40 + <tr>
41 + <td>Task:</td>
42 + <td>
43 + <%= select(:test_request,
44 + :problem_id,
45 + @problems.collect {|p| [p.name, p.id]}, {},
46 + { :onclick => "updateSubmissionList();" }) %>
47 + </td>
48 + </tr>
49 + <tr>
50 + <td>Submission:</td>
51 + <td>
52 + <%= select(:test_request,
53 + :submission_number,
54 + ((1..@submissions[0].number).collect {|n| [n,n]}).reverse) %>
55 + </td>
56 + </tr>
57 + <tr>
58 + <td>Input data:</td>
59 + <td>
60 + <%= f.file_field :input_file %>
61 + </td>
62 + <td>
63 + (combined size should not exceed 2MB)
64 + </td>
65 + </tr>
66 + <tr>
67 + <td>
68 + Additional file<sup><span style="color:red">*</span></sup>:
69 + </td>
70 + <td>
71 + <%= f.file_field :additional_file %>
72 + </td>
73 + <td>
74 + <small>
75 + * This option works <u>only</u> for task max.
76 + You can use this to submit <tt>questions.txt</tt>.<br/>
77 + The file shall be copied to the execution directory before your program runs.
78 + </small>
79 + </td>
80 + </tr>
81 + <tr>
82 + <td colspan="2">
83 + <%= submit_tag 'submit' %>
84 + </td>
85 + </tr>
86 + </table>
87 + <% end %>
88 + </div>
86 89 <% end %>
87 - </div>
88 90
89 91 <h3>Previous requests</h3>
90 92
91 93 <table class="info">
92 94 <tr class="info-head">
93 95 <th>at</th>
94 96 <th>problem</th>
95 97 <th>sub #</th>
96 98 <th>status</th>
97 99 <th>output (first 2kb)</th>
98 100 <th>compiler message</th>
99 101 <th>detail</th>
100 102 </tr>
101 103 <%= render :partial => 'test_request', :collection => @test_requests %>
102 104 </table>
103 105
104 106 <% end %>
105 107
@@ -1,108 +1,108
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 => 35) do
12 + ActiveRecord::Schema.define(:version => 36) do
13 13
14 14 create_table "announcements", :force => true do |t|
15 15 t.string "author"
16 16 t.text "body"
17 17 t.boolean "published"
18 18 t.datetime "created_at"
19 19 t.datetime "updated_at"
20 20 end
21 21
22 22 create_table "configurations", :force => true do |t|
23 23 t.string "key"
24 24 t.string "value_type"
25 25 t.string "value"
26 26 t.datetime "created_at"
27 27 t.datetime "updated_at"
28 28 end
29 29
30 30 create_table "countries", :force => true do |t|
31 31 t.string "name"
32 32 t.datetime "created_at"
33 33 t.datetime "updated_at"
34 34 end
35 35
36 36 create_table "descriptions", :force => true do |t|
37 37 t.text "body"
38 38 t.boolean "markdowned"
39 39 t.datetime "created_at"
40 40 t.datetime "updated_at"
41 41 end
42 42
43 43 create_table "grader_processes", :force => true do |t|
44 44 t.string "host", :limit => 20
45 45 t.integer "pid"
46 46 t.string "mode"
47 47 t.boolean "active"
48 48 t.datetime "created_at"
49 49 t.datetime "updated_at"
50 50 t.integer "task_id"
51 51 t.string "task_type"
52 52 end
53 53
54 54 add_index "grader_processes", ["host", "pid"], :name => "index_grader_processes_on_ip_and_pid"
55 55
56 56 create_table "languages", :force => true do |t|
57 57 t.string "name", :limit => 10
58 58 t.string "pretty_name"
59 59 t.string "ext", :limit => 10
60 60 end
61 61
62 62 create_table "messages", :force => true do |t|
63 63 t.integer "sender_id"
64 64 t.integer "receiver_id"
65 65 t.integer "replying_message_id"
66 66 t.text "body"
67 67 t.boolean "replied"
68 68 t.datetime "created_at"
69 69 t.datetime "updated_at"
70 70 end
71 71
72 72 create_table "problems", :force => true do |t|
73 73 t.string "name", :limit => 30
74 74 t.string "full_name"
75 75 t.integer "full_score"
76 76 t.date "date_added"
77 77 t.boolean "available"
78 78 t.string "url"
79 79 t.integer "description_id"
80 80 t.boolean "test_allowed"
81 81 t.boolean "output_only"
82 82 end
83 83
84 84 create_table "rights", :force => true do |t|
85 85 t.string "name"
86 86 t.string "controller"
87 87 t.string "action"
88 88 end
89 89
90 90 create_table "rights_roles", :id => false, :force => true do |t|
91 91 t.integer "right_id"
92 92 t.integer "role_id"
93 93 end
94 94
95 95 add_index "rights_roles", ["role_id"], :name => "index_rights_roles_on_role_id"
96 96
97 97 create_table "roles", :force => true do |t|
98 98 t.string "name"
99 99 end
100 100
101 101 create_table "roles_users", :id => false, :force => true do |t|
102 102 t.integer "role_id"
103 103 t.integer "user_id"
104 104 end
105 105
106 106 add_index "roles_users", ["user_id"], :name => "index_roles_users_on_user_id"
107 107
108 108 create_table "sessions", :force => true do |t|
You need to be logged in to leave comments. Login now