require 'ipaddr' require "securerandom" class ApplicationController < ActionController::Base protect_from_forgery before_action :current_user before_action :nav_announcement before_action :unique_visitor_id SINGLE_USER_MODE_CONF_KEY = 'system.single_user_mode' MULTIPLE_IP_LOGIN_CONF_KEY = 'right.multiple_ip_login' WHITELIST_IGNORE_CONF_KEY = 'right.whitelist_ignore' WHITELIST_IP_CONF_KEY = 'right.whitelist_ip' #report and redirect for unauthorized activities def unauthorized_redirect(notice = 'You are not authorized to view the page you requested') flash[:notice] = notice redirect_to login_main_path end # Returns the current logged-in user (if any). def current_user return nil unless session[:user_id] @current_user ||= User.find(session[:user_id]) end def nav_announcement @nav_announcement = Announcement.where(on_nav_bar: true) end def admin_authorization return false unless check_valid_login user = User.includes(:roles).find(session[:user_id]) unless user.admin? unauthorized_redirect return false end return true end #admin always count as every roles def role_authorization(roles) return false unless check_valid_login user = User.find(session[:user_id]) return true if user.admin? roles.each do |r| return true if user.has_role?(r) end unauthorized_redirect end def authorization_by_roles(allowed_roles) return false unless check_valid_login unless @current_user.roles.detect { |role| allowed_roles.member?(role.name) } unauthorized_redirect return false end end def testcase_authorization #admin always has privileged if @current_user.admin? return true end unauthorized_redirect unless GraderConfiguration["right.view_testcase"] end def unique_visitor_id unless cookies.encrypted[:uuid] value = SecureRandom.uuid cookies.encrypted[:uuid] = { value: value, expires: 20.year } end end protected #redirect to root (and also force logout) #if the user is not logged_in or the system is in "ADMIN ONLY" mode def check_valid_login #check if logged in unless session[:user_id] if GraderConfiguration[SINGLE_USER_MODE_CONF_KEY] unauthorized_redirect('You need to login but you cannot log in at this time') else unauthorized_redirect('You need to login') end return false end # check if run in single user mode if GraderConfiguration[SINGLE_USER_MODE_CONF_KEY] if @current_user==nil || (!@current_user.admin?) unauthorized_redirect('You cannot log in at this time') return false end end # check if the user is enabled unless @current_user.enabled? || @current_user.admin? unauthorized_redirect 'Your account is disabled' return false end # check if user ip is allowed unless @current_user.admin? || GraderConfiguration[WHITELIST_IGNORE_CONF_KEY] unless is_request_ip_allowed? unauthorized_redirect 'Your IP is not allowed to login at this time.' return false end end if GraderConfiguration.multicontests? return true if @current_user.admin? begin if @current_user.contest_stat(true).forced_logout flash[:notice] = 'You have been automatically logged out.' redirect_to :controller => 'main', :action => 'index' end rescue end end return true end #redirect to root (and also force logout) #if the user use different ip from the previous connection # only applicable when MULTIPLE_IP_LOGIN options is false only def authenticate_by_ip_address #this assume that we have already authenticate normally unless GraderConfiguration[MULTIPLE_IP_LOGIN_CONF_KEY] user = User.find(session[:user_id]) if (!user.admin? && user.last_ip && user.last_ip != request.remote_ip) flash[:notice] = "You cannot use the system from #{request.remote_ip}. Your last ip is #{user.last_ip}" redirect_to :controller => 'main', :action => 'login' return false end unless user.last_ip user.last_ip = request.remote_ip user.save end end return true end def authorization return false unless check_valid_login user = User.find(session[:user_id]) unless user.roles.detect { |role| role.rights.detect{ |right| right.controller == self.class.controller_name and (right.action == 'all' || right.action == action_name) } } flash[:notice] = 'You are not authorized to view the page you requested' #request.env['HTTP_REFERER'] ? (redirect_to :back) : (redirect_to :controller => 'login') redirect_to :controller => 'main', :action => 'login' return false end end def verify_time_limit return true if session[:user_id]==nil user = User.find(session[:user_id], :include => :site) return true if user==nil || user.site == nil if user.contest_finished? flash[:notice] = 'Error: the contest you are participating is over.' redirect_to :back return false end return true end def is_request_ip_allowed? unless GraderConfiguration[WHITELIST_IGNORE_CONF_KEY] user_ip = IPAddr.new(request.remote_ip) allowed = GraderConfiguration[WHITELIST_IP_CONF_KEY] || '' allowed.delete(' ').split(',').each do |ips| allow_ips = IPAddr.new(ips) if allow_ips.include?(user_ip) return true end end return false end return true end #function for datatable ajax query #return record,total_count,filter_count def process_query_record(record, total_count: nil, select: '', global_search: [], no_search: false, force_order: '', date_filter: '', date_param_since: 'date_since',date_param_until: 'date_until', hard_limit: nil) arel_table = record.model.arel_table if !no_search && params['search'] global_value = record.model.sanitize_sql(params['search']['value'].strip.downcase) if !global_value.blank? global_value.split.each do |value| global_where = global_search.map{|f| "LOWER(#{f}) like '%#{value}%'"}.join(' OR ') record = record.where(global_where) end end params['columns'].each do |i, col| if !col['search']['value'].blank? record = record.where(arel_table[col['name']].lower.matches("%#{col['search']['value'].strip.downcase}%")) end end end if !date_filter.blank? param_since = params[date_param_since] param_until = params[date_param_until] date_since = Time.zone.parse( param_since ) || Time.new(1,1,1) rescue Time.new(1,1,1) date_until = Time.zone.parse( param_until ) || Time.zone.now() rescue Time.zone.now() date_range = date_since..(date_until.end_of_day) record = record.where(date_filter.to_sym => date_range) end if force_order.blank? if params['order'] params['order'].each do |i, o| colName = params['columns'][o['column']]['name'] colName = "#{record.model.table_name}.#{colName}" if colName.upcase == 'ID' record = record.order("#{colName} #{o['dir'].casecmp('desc') != 0 ? 'ASC' : 'DESC'}") unless colName.blank? end end else record = record.order(force_order) end filterCount = record.count(record.model.primary_key) # if .group() is used, filterCount might be like {id_1: count_1, id_2: count_2, ...} # so we should count the result again.. if filterCount.is_a? Hash filterCount = filterCount.count end record = record.offset(params['start'] || 0) record = record.limit(hard_limit) if (params['length']) limit = params['length'].to_i limit == hard_limit if (hard_limit && hard_limit < limit) record = record.limit(limit) end if (!select.blank?) record = record.select(select) end return record, total_count || record.model.count, filterCount end end