require "sequel" require "sinatra" require 'newrelic_rpm' if production? require "slim" require "pry" unless production? require "envyable" require "hashids" require "set" Envyable.load("config/env.yaml", ENV['RACK_ENV']) if ENV['RACK_ENV'] != "test" DB = Sequel.connect(:adapter=>'postgres', :host=>ENV['SV_HOST'], :database=>ENV['SV_DB'], :user=>ENV['SV_USER'], :password=>ENV['SV_PASSWORD'], :sslmode => "require") end class Schueler < Sequel::Model(:schueler) one_to_many :sprecher_stimmen, :class => :Sprecher one_to_many :schuko_stimmen, :class => :Schuko end class Lehrer < Sequel::Model(:lehrer) one_to_many :lehrer_stimmen, :class => :Verbindungslehrer end class Info < Sequel::Model(:infos);end class Sprecher < Sequel::Model(:sprecher) many_to_one :schueler, :class => :Schueler end class Schuko < Sequel::Model(:schuko) many_to_one :schueler, :class => :Schueler end class Verbindungslehrer < Sequel::Model(:verbindungslehrer) many_to_one :lehrer, :key => :lehrer_id, :class => :Lehrer end class SV < Sinatra::Application configure do enable :sessions set :session_secret, (ENV['SV_SESSION_SECRET'] || 'your_secret') Slim::Engine.set_options pretty: true enable :static set :public_folder, File.dirname(__FILE__) + '/public' end configure :production do newrelic_ignore '/ping' end helpers do def vor_der_wahl? Time.now < time_for(ENV['SV_WAHL_BEGINN']) end def nach_der_wahl? Time.now > time_for(ENV['SV_WAHL_ENDE']) end def wahlzeit? zeit = Time.now (zeit > Time.parse(ENV["SV_WAHL_BEGINN"])) and (zeit < Time.parse(ENV["SV_WAHL_ENDE"])) end def protected! return if authorized? headers['WWW-Authenticate'] = 'Basic realm="Bitte anmelden"' halt 401, "Not authorized\n" end def authorized? @auth ||= Rack::Auth::Basic::Request.new(request.env) @auth.provided? and @auth.basic? and @auth.credentials and @auth.credentials == [ENV['SV_BASIC_AUTH_USER'], ENV['SV_BASIC_AUTH_PASSWORD']] end def hashids hashids = Hashids.new(ENV['SV_SESSION_SECRET'], 5, "ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnpqrstuvwxyz23456789") end end error do 'Es ist ein Fehler aufgetreten. Sollte das nochmal passieren, schreiben Sie mir doch bitte eine eMail: bk@hmt.im' end before do if session[:flash] && session[:flash][0] == 0 logger.info session[:flash][1] end end get '/' do if nach_der_wahl? redirect to("/ergebnis") end infos = Info.all slim :home, :locals => {:infos => infos} end get '/ping' do [200] end post "/wahl" do if wahlzeit? session[:flash] = [0, "Sie können sich nicht mehr aufstellen lassen, die Wahl hat bereits begonnen"] redirect back end schueler = Schueler.where(:hashid => params[:hashid]).first if schueler.update_fields params, [:info, :email, :schuko, :sprecher, :nachname] session[:flash] = [1, "Ihre Eingabe wurde gespeichert"] else session[:flash] = [0, "Es gab einen Fehler beim Speichern"] end redirect back end post '/info' do protected! if DB[:infos].insert(:text => params[:text], :timestamp => params[:timestamp]) session[:flash] = [1, "Die Info wurde gespeichert"] else session[:flash] = [0, "Es gab einen Fehler beim Speichern der Info"] end redirect to("/") end get '/info_loeschen/:id' do |id| protected! Info.where(:id => id).first.delete redirect back end get '/info' do protected! infos = Info.all slim :info, :locals => {:infos => infos} end get '/ergebnis' do protected! unless nach_der_wahl? sprecher, schuko, lehrer, waehler = [], [], [], 0 DB.transaction do sprecher = Schueler.where(:sprecher => true).all schuko = Schueler.where(:schuko => true).all lehrer = Lehrer.all waehler = Schueler.where(:gewaehlt => true).count end slim :ergebnis, :locals => {:sprecher => sprecher, :schuko => schuko, :lehrer => lehrer, :waehler => waehler} end post "/hashcheck" do redirect back if params[:stimm_hash].nil? arrays = params[:stimm_hash].split("l").map{|a| hashids.decode a} sprecher = Sprecher.where(:id => arrays[0]) schuko = Schuko.where(:id => arrays[1]) lehrer = Verbindungslehrer.where(:id => arrays[2]) slim :hashcheck, :locals => {:sprecher => sprecher, :schuko => schuko, :lehrer => lehrer} end post "/hashid" do redirect to("/#{params[:hashid]}") end get "/:hashid" do schueler = Schueler.where(:hashid => params[:hashid]).first if schueler.nil? halt 404, "Adresse richtig abgetippt? Eventuell geht es mit dem QR-Code am Telefon leichter?" end lehrer = Lehrer.all slim :hashid, :locals => {:schueler => schueler, :lehrer => lehrer} end post "/:hashid" do if nach_der_wahl? session[:flash] = [0, "Der Wahlzeitraum ist bereits abgelaufen."] redirect back elsif vor_der_wahl? session[:flash] = [0, "Der Wahlzeitraum hat noch nicht begonnen."] redirect back end schueler = Schueler.where(:hashid => params[:hashid]).first if schueler.nil? halt 404, "Hier stimmt etwas nicht mit Ihrem persönlichen Code" end if schueler.gewaehlt session[:flash] = [0, "Sie haben schon gewählt"] redirect back end sprecher, schuko, lehrer = params[:sprecher], params[:schuko], params[:lehrer] if sprecher && sprecher.count > 2 session[:flash] = [0, "Zu viele Sprecher gewählt (max. 2)"] redirect back elsif schuko && schuko.count > 8 session[:flash] = [0, "Zu viele Vertreter für die Schulkonferenz gewählt (max. 8)"] redirect back elsif lehrer && lehrer.count > 2 session[:flash] = [0, "Zu viele Vertrauenslehrer gewählt (max. 2)"] redirect back end stimm_ids = [] sprecher_ids, schuko_ids, lehrer_ids =[], [], [] stimmabgabe = DB.transaction do sprecher && sprecher.to_set.each do |s| if Schueler[s].sprecher sprecher_ids << DB[:sprecher].insert(:schueler_id => s) else raise Sequel::Rollback session[:flash] = [0, "Es wurde ein nichtaufgestellter Sprecher gewählt"] redirect back end end schuko && schuko.to_set.each do |s| if Schueler[s].schuko schuko_ids << DB[:schuko].insert(:schueler_id => s) else raise Sequel::Rollback session[:flash] = [0, "Es wurde ein nichtaufgestellter Vertreter zur Schulkonferenz gewählt"] redirect back end end lehrer && lehrer.to_set.each do |l| lehrer_ids << DB[:verbindungslehrer].insert(:lehrer_id => l) end schueler.update(:gewaehlt => true) end stimm_ids << sprecher_ids << schuko_ids << lehrer_ids stimm_hash = stimm_ids.map do |s_id| return "" if s_id.nil? hashids.encode s_id end if stimmabgabe session[:flash] = [1, "Ihre Wahl wurde gespeichert"] session[:stimm_hash] = stimm_hash.join("l") else session[:flash] = [0, "Es gab einen Fehler bei der Speicherung der Wahlergebnisse"] end redirect back end end