Description:
merge
Commit status:
[Not Reviewed]
References:
merge algo
Comments:
0 Commit comments 0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
Add another comment

r840:b948bb241476 - - 9 files changed: 66 inserted, 2 deleted

@@ -0,0 +1,25
1 + = simple_form_for(@announcement) do |f|
2 + - if @announcement.errors.any?
3 + .form-row
4 + .col-sm-12
5 + #error_explanation.alert.alert-dismissable.alert-danger
6 + %button.close{type: "button", data: { dismiss: "alert"}, aria: {hidden: "true"}} ×
7 + %h3= "เกิดปัญหาในการบันทึกข้อมูลเนื่องจาก"
8 + %ul
9 + - @announcement.errors.full_messages.each do |message|
10 + %li= message
11 + .form-row
12 + .col-md-6.col-12
13 + -# = f.input :lock_version, as: :hidden
14 + = f.input :title
15 + = f.input :notes, label: 'Notes (shown internally, used to organize announcements)'
16 + = f.input :body
17 + = f.input :author
18 + = f.input :published
19 + = f.input :frontpage, label: 'Display in the front page only?'
20 + = f.input :on_nav_bar, label: 'Show on menu bar?', wrapper: :custom_boolean
21 + = f.input :contest_only, label: 'Display in contest only?'
22 + = f.submit "Create", class: 'btn btn-primary'
23 + -if content_for?(:form_buttons)
24 + = yield(:form_buttons)
25 + / = link_to 'Back', announcements_path, class: 'btn btn-default'
@@ -0,0 +1,5
1 + class AddOnNavBarToAnnouncement < ActiveRecord::Migration[5.2]
2 + def change
3 + add_column :announcements, :on_nav_bar, :boolean, default: false
4 + end
5 + end
@@ -1,116 +1,116
1 1 class AnnouncementsController < ApplicationController
2 2
3 3 before_action :admin_authorization
4 4
5 5 in_place_edit_for :announcement, :published
6 6
7 7 # GET /announcements
8 8 # GET /announcements.xml
9 9 def index
10 10 @announcements = Announcement.order(created_at: :desc)
11 11
12 12 respond_to do |format|
13 13 format.html # index.html.erb
14 14 format.xml { render :xml => @announcements }
15 15 end
16 16 end
17 17
18 18 # GET /announcements/1
19 19 # GET /announcements/1.xml
20 20 def show
21 21 @announcement = Announcement.find(params[:id])
22 22
23 23 respond_to do |format|
24 24 format.html # show.html.erb
25 25 format.xml { render :xml => @announcement }
26 26 end
27 27 end
28 28
29 29 # GET /announcements/new
30 30 # GET /announcements/new.xml
31 31 def new
32 32 @announcement = Announcement.new
33 33
34 34 respond_to do |format|
35 35 format.html # new.html.erb
36 36 format.xml { render :xml => @announcement }
37 37 end
38 38 end
39 39
40 40 # GET /announcements/1/edit
41 41 def edit
42 42 @announcement = Announcement.find(params[:id])
43 43 end
44 44
45 45 # POST /announcements
46 46 # POST /announcements.xml
47 47 def create
48 48 @announcement = Announcement.new(announcement_params)
49 49
50 50 respond_to do |format|
51 51 if @announcement.save
52 52 flash[:notice] = 'Announcement was successfully created.'
53 53 format.html { redirect_to(@announcement) }
54 54 format.xml { render :xml => @announcement, :status => :created, :location => @announcement }
55 55 else
56 56 format.html { render :action => "new" }
57 57 format.xml { render :xml => @announcement.errors, :status => :unprocessable_entity }
58 58 end
59 59 end
60 60 end
61 61
62 62 # PUT /announcements/1
63 63 # PUT /announcements/1.xml
64 64 def update
65 65 @announcement = Announcement.find(params[:id])
66 66
67 67 respond_to do |format|
68 68 if @announcement.update_attributes(announcement_params)
69 69 flash[:notice] = 'Announcement was successfully updated.'
70 70 format.html { redirect_to(@announcement) }
71 71 format.js {}
72 72 format.xml { head :ok }
73 73 else
74 74 format.html { render :action => "edit" }
75 75 format.js {}
76 76 format.xml { render :xml => @announcement.errors, :status => :unprocessable_entity }
77 77 end
78 78 end
79 79 end
80 80
81 81 def toggle
82 82 @announcement = Announcement.find(params[:id])
83 83 @announcement.update_attributes( published: !@announcement.published? )
84 84 respond_to do |format|
85 85 format.js { render partial: 'toggle_button',
86 86 locals: {button_id: "#announcement_toggle_#{@announcement.id}",button_on: @announcement.published? } }
87 87 end
88 88 end
89 89
90 90 def toggle_front
91 91 @announcement = Announcement.find(params[:id])
92 92 @announcement.update_attributes( frontpage: !@announcement.frontpage? )
93 93 respond_to do |format|
94 94 format.js { render partial: 'toggle_button',
95 95 locals: {button_id: "#announcement_toggle_front_#{@announcement.id}",button_on: @announcement.frontpage? } }
96 96 end
97 97 end
98 98
99 99 # DELETE /announcements/1
100 100 # DELETE /announcements/1.xml
101 101 def destroy
102 102 @announcement = Announcement.find(params[:id])
103 103 @announcement.destroy
104 104
105 105 respond_to do |format|
106 106 format.html { redirect_to(announcements_url) }
107 107 format.xml { head :ok }
108 108 end
109 109 end
110 110
111 111 private
112 112
113 113 def announcement_params
114 - params.require(:announcement).permit(:author, :body, :published, :frontpage, :contest_only, :title)
114 + params.require(:announcement).permit(:author, :body, :published, :frontpage, :contest_only, :title, :on_nav_bar)
115 115 end
116 116 end
@@ -1,216 +1,221
1 1 require 'ipaddr'
2 2
3 3 class ApplicationController < ActionController::Base
4 4 protect_from_forgery
5 5
6 6 before_action :current_user
7 + before_action :nav_announcement
7 8
8 9 SINGLE_USER_MODE_CONF_KEY = 'system.single_user_mode'
9 10 MULTIPLE_IP_LOGIN_CONF_KEY = 'right.multiple_ip_login'
10 11 WHITELIST_IGNORE_CONF_KEY = 'right.whitelist_ignore'
11 12 WHITELIST_IP_CONF_KEY = 'right.whitelist_ip'
12 13
13 14 #report and redirect for unauthorized activities
14 15 def unauthorized_redirect(notice = 'You are not authorized to view the page you requested')
15 16 flash[:notice] = notice
16 17 redirect_to login_main_path
17 18 end
18 19
19 20 # Returns the current logged-in user (if any).
20 21 def current_user
21 22 return nil unless session[:user_id]
22 23 @current_user ||= User.find(session[:user_id])
23 24 end
24 25
26 + def nav_announcement
27 + @nav_announcement = Announcement.where(on_nav_bar: true)
28 + end
29 +
25 30 def admin_authorization
26 31 return false unless check_valid_login
27 32 user = User.includes(:roles).find(session[:user_id])
28 33 unless user.admin?
29 34 unauthorized_redirect
30 35 return false
31 36 end
32 37 return true
33 38 end
34 39
35 40 def authorization_by_roles(allowed_roles)
36 41 return false unless check_valid_login
37 42 unless @current_user.roles.detect { |role| allowed_roles.member?(role.name) }
38 43 unauthorized_redirect
39 44 return false
40 45 end
41 46 end
42 47
43 48 def testcase_authorization
44 49 #admin always has privileged
45 50 if @current_user.admin?
46 51 return true
47 52 end
48 53
49 54 unauthorized_redirect unless GraderConfiguration["right.view_testcase"]
50 55 end
51 56
52 57
53 58 protected
54 59
55 60 #redirect to root (and also force logout)
56 61 #if the user is not logged_in or the system is in "ADMIN ONLY" mode
57 62 def check_valid_login
58 63 #check if logged in
59 64 unless session[:user_id]
60 65 if GraderConfiguration[SINGLE_USER_MODE_CONF_KEY]
61 66 unauthorized_redirect('You need to login but you cannot log in at this time')
62 67 else
63 68 unauthorized_redirect('You need to login')
64 69 end
65 70 return false
66 71 end
67 72
68 73 # check if run in single user mode
69 74 if GraderConfiguration[SINGLE_USER_MODE_CONF_KEY]
70 75 if @current_user==nil || (!@current_user.admin?)
71 76 unauthorized_redirect('You cannot log in at this time')
72 77 return false
73 78 end
74 79 end
75 80
76 81 # check if the user is enabled
77 82 unless @current_user.enabled? || @current_user.admin?
78 83 unauthorized_redirect 'Your account is disabled'
79 84 return false
80 85 end
81 86
82 87 # check if user ip is allowed
83 88 unless @current_user.admin? || GraderConfiguration[WHITELIST_IGNORE_CONF_KEY]
84 89 unless is_request_ip_allowed?
85 90 unauthorized_redirect 'Your IP is not allowed to login at this time.'
86 91 return false
87 92 end
88 93 end
89 94
90 95 if GraderConfiguration.multicontests?
91 96 return true if @current_user.admin?
92 97 begin
93 98 if @current_user.contest_stat(true).forced_logout
94 99 flash[:notice] = 'You have been automatically logged out.'
95 100 redirect_to :controller => 'main', :action => 'index'
96 101 end
97 102 rescue
98 103 end
99 104 end
100 105 return true
101 106 end
102 107
103 108 #redirect to root (and also force logout)
104 109 #if the user use different ip from the previous connection
105 110 # only applicable when MULTIPLE_IP_LOGIN options is false only
106 111 def authenticate_by_ip_address
107 112 #this assume that we have already authenticate normally
108 113 unless GraderConfiguration[MULTIPLE_IP_LOGIN_CONF_KEY]
109 114 user = User.find(session[:user_id])
110 115 if (!user.admin? && user.last_ip && user.last_ip != request.remote_ip)
111 116 flash[:notice] = "You cannot use the system from #{request.remote_ip}. Your last ip is #{user.last_ip}"
112 117 redirect_to :controller => 'main', :action => 'login'
113 118 return false
114 119 end
115 120 unless user.last_ip
116 121 user.last_ip = request.remote_ip
117 122 user.save
118 123 end
119 124 end
120 125 return true
121 126 end
122 127
123 128 def authorization
124 129 return false unless check_valid_login
125 130 user = User.find(session[:user_id])
126 131 unless user.roles.detect { |role|
127 132 role.rights.detect{ |right|
128 133 right.controller == self.class.controller_name and
129 134 (right.action == 'all' || right.action == action_name)
130 135 }
131 136 }
132 137 flash[:notice] = 'You are not authorized to view the page you requested'
133 138 #request.env['HTTP_REFERER'] ? (redirect_to :back) : (redirect_to :controller => 'login')
134 139 redirect_to :controller => 'main', :action => 'login'
135 140 return false
136 141 end
137 142 end
138 143
139 144 def verify_time_limit
140 145 return true if session[:user_id]==nil
141 146 user = User.find(session[:user_id], :include => :site)
142 147 return true if user==nil || user.site == nil
143 148 if user.contest_finished?
144 149 flash[:notice] = 'Error: the contest you are participating is over.'
145 150 redirect_to :back
146 151 return false
147 152 end
148 153 return true
149 154 end
150 155
151 156 def is_request_ip_allowed?
152 157 unless GraderConfiguration[WHITELIST_IGNORE_CONF_KEY]
153 158 user_ip = IPAddr.new(request.remote_ip)
154 159 allowed = GraderConfiguration[WHITELIST_IP_CONF_KEY] || ''
155 160
156 161 allowed.delete(' ').split(',').each do |ips|
157 162 allow_ips = IPAddr.new(ips)
158 163 if allow_ips.include?(user_ip)
159 164 return true
160 165 end
161 166 end
162 167 return false
163 168 end
164 169 return true
165 170 end
166 171
167 172 #function for datatable ajax query
168 173 #return record,total_count,filter_count
169 174 def process_query_record(record,
170 175 total_count: nil,
171 176 select: '',
172 177 global_search: [],
173 178 no_search: false,
174 179 force_order: '',
175 180 date_filter: '', date_param_since: 'date_since',date_param_until: 'date_until',
176 181 hard_limit: nil)
177 182 arel_table = record.model.arel_table
178 183
179 184 if !no_search && params['search']
180 185 global_value = record.model.sanitize_sql(params['search']['value'].strip.downcase)
181 186 if !global_value.blank?
182 187 global_value.split.each do |value|
183 188 global_where = global_search.map{|f| "LOWER(#{f}) like '%#{value}%'"}.join(' OR ')
184 189 record = record.where(global_where)
185 190 end
186 191 end
187 192
188 193 params['columns'].each do |i, col|
189 194 if !col['search']['value'].blank?
190 195 record = record.where(arel_table[col['name']].lower.matches("%#{col['search']['value'].strip.downcase}%"))
191 196 end
192 197 end
193 198 end
194 199
195 200 if !date_filter.blank?
196 201 param_since = params[date_param_since]
197 202 param_until = params[date_param_until]
198 203 date_since = Time.zone.parse( param_since ) || Time.new(1,1,1) rescue Time.new(1,1,1)
199 204 date_until = Time.zone.parse( param_until ) || Time.zone.now() rescue Time.zone.now()
200 205 date_range = date_since..(date_until.end_of_day)
201 206 record = record.where(date_filter.to_sym => date_range)
202 207 end
203 208
204 209 if force_order.blank?
205 210 if params['order']
206 211 params['order'].each do |i, o|
207 212 colName = params['columns'][o['column']]['name']
208 213 colName = "#{record.model.table_name}.#{colName}" if colName.upcase == 'ID'
209 214 record = record.order("#{colName} #{o['dir'].casecmp('desc') != 0 ? 'ASC' : 'DESC'}") unless colName.blank?
210 215 end
211 216 end
212 217 else
213 218 record = record.order(force_order)
214 219 end
215 220
216 221 filterCount = record.count(record.model.primary_key)
@@ -1,34 +1,45
1 + %h1 Edit Announcement
2 +
3 + -content_for(:form_buttons) do
4 + = link_to t(:back), announcements_path, class: 'card-link btn btn-secondary'
5 +
6 + = render 'form'
7 + -# old style
1 8 .container-fluid
2 9 %h1 Editing announcement
3 10 = error_messages_for :announcement
4 11 .row
5 12 .col-md-6
6 13 = form_for(@announcement) do |f|
7 14 .form-group
8 15 %label Title
9 16 = f.text_field :title, class: 'form-control'
10 17 .form-group
11 18 %label Notes
12 19 (shown internally, used to organize announcements)
13 20 = f.text_field :notes, class: 'form-control'
14 21 .form-group
15 22 %label Body
16 23 = f.text_area :body, class: 'form-control', style: 'height: 200px;'
17 24 .form-group
18 25 %label Author
19 26 = f.text_field :author, class: 'form-control'
20 27 .checkbox
21 28 %label
22 29 = f.check_box :published
23 30 Published
24 31 .checkbox
25 32 %label
26 33 = f.check_box :frontpage
27 34 Show on front page?
28 35 .checkbox
29 36 %label
37 + = f.check_box :on_nav_bar
38 + Show on top menu bar?
39 + .checkbox
40 + %label
30 41 = f.check_box :contest_only
31 42 Show only in contest?
32 43 = f.submit "Update", class: 'btn btn-primary'
33 44 = link_to 'Show', @announcement, class: 'btn btn-default'
34 45 = link_to 'Back', announcements_path, class: 'btn btn-default'
@@ -1,14 +1,22
1 1 %h1 New announcement
2 +
3 + -content_for(:form_buttons) do
4 + = link_to t(:back), announcements_path, class: 'card-link btn btn-secondary'
5 +
6 + = render 'form'
7 +
8 + -# old style
2 9 = error_messages_for :announcement
3 10 = simple_form_for(@announcement) do |f|
4 11 .row
5 12 .col-md-6
6 13 = f.input :title
7 14 = f.input :notes, label: 'Notes (shown internally, used to organize announcements)'
8 15 = f.input :body
9 16 = f.input :author
10 17 = f.input :published
11 18 = f.input :frontpage, label: 'Display in the front page only?'
12 19 = f.input :contest_only, label: 'Display in contest only?'
13 20 = f.button :submit, "Create", class: 'btn btn-primary'
14 21 = link_to 'Back', announcements_path, class: 'btn btn-default'
22 +
@@ -1,24 +1,27
1 1 %p
2 2 %b Author:
3 3 = h @announcement.author
4 4 %p
5 5 %b Title:
6 6 = h @announcement.title
7 7 %p
8 8 %b Notes:
9 9 = h @announcement.notes
10 10 %p
11 11 %b Body:
12 12 = h markdown(@announcement.body)
13 13 %p
14 14 %b Published:
15 15 = h @announcement.published
16 16 %p
17 17 %b Show on front page:
18 18 = h @announcement.frontpage
19 19 %p
20 + %b Show on top menu bar:
21 + = h @announcement.on_nav_bar
22 + %p
20 23 %b Show only in contest:
21 24 = h @announcement.contest_only
22 25 = link_to 'Edit', edit_announcement_path(@announcement)
23 26 |
24 27 = link_to 'Back', announcements_path
@@ -1,96 +1,102
1 1 %header.navbar.navbar-default.navbar-fixed-top
2 2 %nav
3 3 .container-fluid
4 4 .navbar-header
5 5 %button.navbar-toggle.collapsed{ data: {toggle: 'collapse', target: '#navbar-collapse'} }
6 6 %span.sr-only Togggle Navigation
7 7 %span.icon-bar
8 8 %span.icon-bar
9 9 %span.icon-bar
10 10 %a.navbar-brand{href: list_main_path}
11 11 %span.glyphicon.glyphicon-home
12 12 MAIN
13 13 .collapse.navbar-collapse#navbar-collapse
14 14 %ul.nav.navbar-nav
15 15 / submission
16 16 - if (@current_user!=nil) and (GraderConfiguration.show_tasks_to?(@current_user))
17 17 %li.dropdown
18 18 %a.dropdown-toggle{href: '#', data: {toggle:'dropdown'}, aria: {haspopup:"true", expanded:"false"}, role: "button"}
19 19 = "#{I18n.t 'menu.submissions'}"
20 20 %span.caret
21 21 %ul.dropdown-menu
22 22 = add_menu("View", 'submissions', 'index')
23 23 = add_menu("Self Test", 'test', 'index')
24 24 / hall of fame
25 25 - if GraderConfiguration['right.user_hall_of_fame']
26 26 = add_menu("#{I18n.t 'menu.hall_of_fame'}", 'report', 'problem_hof')
27 27 / display MODE button (with countdown in contest mode)
28 28 - if GraderConfiguration.analysis_mode?
29 29 %div.navbar-btn.btn.btn-success#countdown= "ANALYSIS MODE"
30 30 - elsif GraderConfiguration.time_limit_mode?
31 31 - if @current_user.contest_finished?
32 32 %div.navbar-btn.btn.btn-danger#countdown= "Contest is over"
33 33 - elsif !@current_user.contest_started?
34 34 %div.navbar-btn.btn.btn-primary#countdown= (t 'title_bar.contest_not_started')
35 35 - else
36 36 %div.navbar-btn.btn.btn-primary#countdown asdf
37 37 :javascript
38 38 $("#countdown").countdown({until: "+#{@current_user.contest_time_left.to_i}s", layout: 'Time left: {hnn}:{mnn}:{snn}'});
39 39 / admin section
40 40 - if (@current_user!=nil) and (session[:admin])
41 41 / management
42 42 %li.dropdown
43 43 %a.dropdown-toggle{href: '#', data: {toggle:'dropdown'}, aria: {haspopup:"true", expanded:"false"}, role: "button"}
44 44 Manage
45 45 %span.caret
46 46 %ul.dropdown-menu
47 47 = add_menu( 'Announcements', 'announcements', 'index')
48 48 = add_menu( 'Problems', 'problems', 'index')
49 49 = add_menu( 'Tags', 'tags', 'index')
50 50 = add_menu( 'Users', 'user_admin', 'index')
51 51 = add_menu( 'User Groups', 'groups', 'index')
52 52 = add_menu( 'Graders', 'graders', 'list')
53 53 = add_menu( 'Message ', 'messages', 'console')
54 54 %li.divider{role: 'separator'}
55 55 = add_menu( 'System config', 'configurations', 'index')
56 56 %li.divider{role: 'separator'}
57 57 = add_menu( 'Sites', 'sites', 'index')
58 58 = add_menu( 'Contests', 'contest_management', 'index')
59 59 / report
60 60 %li.dropdown
61 61 %a.dropdown-toggle{href: '#', data: {toggle:'dropdown'}, aria: {haspopup:"true", expanded:"false"}, role: "button"}
62 62 Report
63 63 %span.caret
64 64 %ul.dropdown-menu
65 65 = add_menu( 'Current Score', 'report', 'current_score')
66 66 = add_menu( 'Score Report', 'report', 'max_score')
67 67 = add_menu( 'Submission Report', 'report', 'submission')
68 68 = add_menu( 'Login Report', 'report', 'login')
69 69 - if (ungraded = Submission.where('graded_at is null').where('submitted_at < ?', 1.minutes.ago).count) > 0
70 70 =link_to "#{ungraded} backlogs!",
71 71 graders_list_path,
72 72 class: 'navbar-btn btn btn-default btn-warning', data: {toggle: 'tooltip'},title: 'Number of ungraded submission'
73 + / announcement
74 + - @nav_announcement.each do |ann|
75 + %p.navbar-text
76 + = ann.body.html_safe
77 +
78 +
73 79
74 80 %ul.nav.navbar-nav.navbar-right
75 81 = add_menu("#{content_tag(:span,'',class: 'glyphicon glyphicon-question-sign')}".html_safe, 'main', 'help')
76 82 = add_menu("#{content_tag(:span,'',class: 'glyphicon glyphicon-comment')}".html_safe, 'messages', 'index', {title: I18n.t('menu.messages'), data: {toggle: 'tooltip'}})
77 83 - if GraderConfiguration['system.user_setting_enabled']
78 84 = add_menu("#{content_tag(:span,'',class: 'glyphicon glyphicon-cog', id: 'user_profile')}".html_safe, 'users', 'profile', {title: I18n.t('menu.settings'), data: {toggle: 'tooltip'}})
79 85 = add_menu("#{content_tag(:span,'',class: 'glyphicon glyphicon-log-out')} #{@current_user.full_name}".html_safe, 'main', 'login', {title: I18n.t('menu.log_out'), data: {toggle: 'tooltip'}})
80 86
81 87 /
82 88 - if (@current_user!=nil) and (session[:admin])
83 89 %nav.navbar.navbar-fixed-top.navbar-inverse.secondnavbar
84 90 .container-fluid
85 91 .collapse.navbar-collapse
86 92 %ul.nav.navbar-nav
87 93 = add_menu( '[Announcements]', 'announcements', 'index')
88 94 = add_menu( '[Msg console]', 'messages', 'console')
89 95 = add_menu( '[Problems]', 'problems', 'index')
90 96 = add_menu( '[Users]', 'user_admin', 'index')
91 97 = add_menu( '[Results]', 'user_admin', 'user_stat')
92 98 = add_menu( '[Report]', 'report', 'multiple_login')
93 99 = add_menu( '[Graders]', 'graders', 'list')
94 100 = add_menu( '[Contests]', 'contest_management', 'index')
95 101 = add_menu( '[Sites]', 'sites', 'index')
96 102 = add_menu( '[System config]', 'configurations', 'index')
@@ -1,216 +1,217
1 1 # This file is auto-generated from the current state of the database. Instead
2 2 # of editing this file, please use the migrations feature of Active Record to
3 3 # incrementally modify your database, and then regenerate this schema definition.
4 4 #
5 5 # Note that this schema.rb definition is the authoritative source for your
6 6 # database schema. If you need to create the application database on another
7 7 # system, you should be using db:schema:load, not running all the migrations
8 8 # from scratch. The latter is a flawed and unsustainable approach (the more migrations
9 9 # you'll amass, the slower it'll run and the greater likelihood for issues).
10 10 #
11 11 # It's strongly recommended that you check this file into your version control system.
12 12
13 - ActiveRecord::Schema.define(version: 2020_08_13_083020) do
13 + ActiveRecord::Schema.define(version: 2021_01_24_101028) do
14 14
15 15 create_table "announcements", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
16 16 t.string "author"
17 17 t.text "body"
18 18 t.boolean "published"
19 19 t.datetime "created_at", null: false
20 20 t.datetime "updated_at", null: false
21 21 t.boolean "frontpage", default: false
22 22 t.boolean "contest_only", default: false
23 23 t.string "title"
24 24 t.string "notes"
25 + t.boolean "on_nav_bar", default: false
25 26 end
26 27
27 28 create_table "contests", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
28 29 t.string "title"
29 30 t.boolean "enabled"
30 31 t.datetime "created_at", null: false
31 32 t.datetime "updated_at", null: false
32 33 t.string "name"
33 34 end
34 35
35 36 create_table "contests_problems", id: false, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
36 37 t.integer "contest_id"
37 38 t.integer "problem_id"
38 39 end
39 40
40 41 create_table "contests_users", id: false, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
41 42 t.integer "contest_id"
42 43 t.integer "user_id"
43 44 end
44 45
45 46 create_table "countries", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
46 47 t.string "name"
47 48 t.datetime "created_at", null: false
48 49 t.datetime "updated_at", null: false
49 50 end
50 51
51 52 create_table "descriptions", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
52 53 t.text "body"
53 54 t.boolean "markdowned"
54 55 t.datetime "created_at", null: false
55 56 t.datetime "updated_at", null: false
56 57 end
57 58
58 59 create_table "grader_configurations", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
59 60 t.string "key"
60 61 t.string "value_type"
61 62 t.string "value"
62 63 t.datetime "created_at", null: false
63 64 t.datetime "updated_at", null: false
64 65 t.text "description"
65 66 end
66 67
67 68 create_table "grader_processes", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
68 69 t.string "host"
69 70 t.integer "pid"
70 71 t.string "mode"
71 72 t.boolean "active"
72 73 t.datetime "created_at", null: false
73 74 t.datetime "updated_at", null: false
74 75 t.integer "task_id"
75 76 t.string "task_type"
76 77 t.boolean "terminated"
77 78 t.index ["host", "pid"], name: "index_grader_processes_on_ip_and_pid"
78 79 end
79 80
80 81 create_table "groups", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
81 82 t.string "name"
82 83 t.string "description"
83 84 t.boolean "enabled", default: true
84 85 end
85 86
86 87 create_table "groups_problems", id: false, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
87 88 t.integer "problem_id", null: false
88 89 t.integer "group_id", null: false
89 90 t.index ["group_id", "problem_id"], name: "index_groups_problems_on_group_id_and_problem_id"
90 91 end
91 92
92 93 create_table "groups_users", options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
93 94 t.integer "group_id", null: false
94 95 t.integer "user_id", null: false
95 96 t.index ["user_id", "group_id"], name: "index_groups_users_on_user_id_and_group_id"
96 97 end
97 98
98 99 create_table "heart_beats", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
99 100 t.integer "user_id"
100 101 t.string "ip_address"
101 102 t.datetime "created_at", null: false
102 103 t.datetime "updated_at", null: false
103 104 t.string "status"
104 105 t.index ["updated_at"], name: "index_heart_beats_on_updated_at"
105 106 end
106 107
107 108 create_table "languages", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
108 109 t.string "name", limit: 10
109 110 t.string "pretty_name"
110 111 t.string "ext", limit: 10
111 112 t.string "common_ext"
112 113 end
113 114
114 115 create_table "logins", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
115 116 t.integer "user_id"
116 117 t.string "ip_address"
117 118 t.datetime "created_at", null: false
118 119 t.datetime "updated_at", null: false
119 120 t.index ["user_id"], name: "index_logins_on_user_id"
120 121 end
121 122
122 123 create_table "messages", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
123 124 t.integer "sender_id"
124 125 t.integer "receiver_id"
125 126 t.integer "replying_message_id"
126 127 t.text "body"
127 128 t.boolean "replied"
128 129 t.datetime "created_at", null: false
129 130 t.datetime "updated_at", null: false
130 131 end
131 132
132 133 create_table "problems", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
133 134 t.string "name", limit: 30
134 135 t.string "full_name"
135 136 t.integer "full_score"
136 137 t.date "date_added"
137 138 t.boolean "available"
138 139 t.string "url"
139 140 t.integer "description_id"
140 141 t.boolean "test_allowed"
141 142 t.boolean "output_only"
142 143 t.string "description_filename"
143 144 t.boolean "view_testcase"
144 145 end
145 146
146 147 create_table "problems_tags", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
147 148 t.integer "problem_id"
148 149 t.integer "tag_id"
149 150 t.index ["problem_id", "tag_id"], name: "index_problems_tags_on_problem_id_and_tag_id", unique: true
150 151 t.index ["problem_id"], name: "index_problems_tags_on_problem_id"
151 152 t.index ["tag_id"], name: "index_problems_tags_on_tag_id"
152 153 end
153 154
154 155 create_table "rights", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
155 156 t.string "name"
156 157 t.string "controller"
157 158 t.string "action"
158 159 end
159 160
160 161 create_table "rights_roles", id: false, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
161 162 t.integer "right_id"
162 163 t.integer "role_id"
163 164 t.index ["role_id"], name: "index_rights_roles_on_role_id"
164 165 end
165 166
166 167 create_table "roles", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
167 168 t.string "name"
168 169 end
169 170
170 171 create_table "roles_users", id: false, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
171 172 t.integer "role_id"
172 173 t.integer "user_id"
173 174 t.index ["user_id"], name: "index_roles_users_on_user_id"
174 175 end
175 176
176 177 create_table "sessions", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
177 178 t.string "session_id"
178 179 t.text "data"
179 180 t.datetime "updated_at"
180 181 t.index ["session_id"], name: "index_sessions_on_session_id"
181 182 t.index ["updated_at"], name: "index_sessions_on_updated_at"
182 183 end
183 184
184 185 create_table "sites", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
185 186 t.string "name"
186 187 t.boolean "started"
187 188 t.datetime "start_time"
188 189 t.datetime "created_at", null: false
189 190 t.datetime "updated_at", null: false
190 191 t.integer "country_id"
191 192 t.string "password"
192 193 end
193 194
194 195 create_table "submission_view_logs", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
195 196 t.integer "user_id"
196 197 t.integer "submission_id"
197 198 t.datetime "created_at", null: false
198 199 t.datetime "updated_at", null: false
199 200 end
200 201
201 202 create_table "submissions", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
202 203 t.integer "user_id"
203 204 t.integer "problem_id"
204 205 t.integer "language_id"
205 206 t.text "source", limit: 16777215
206 207 t.binary "binary"
207 208 t.datetime "submitted_at"
208 209 t.datetime "compiled_at"
209 210 t.text "compiler_message"
210 211 t.datetime "graded_at"
211 212 t.integer "points"
212 213 t.text "grader_comment"
213 214 t.integer "number"
214 215 t.string "source_filename"
215 216 t.float "max_runtime"
216 217 t.integer "peak_memory"
You need to be logged in to leave comments. Login now