sv.rb 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. require "sequel"
  2. require "sinatra"
  3. require 'newrelic_rpm'
  4. require "slim"
  5. require "pry"
  6. require "envyable"
  7. require "hashids"
  8. require "set"
  9. Envyable.load("config/env.yaml", ENV['RACK_ENV'])
  10. if ENV['RACK_ENV'] != "test"
  11. DB = Sequel.connect(:adapter=>'postgres', :host=>ENV['SV_HOST'], :database=>ENV['SV_DB'], :user=>ENV['SV_USER'], :password=>ENV['SV_PASSWORD'], :sslmode => "require")
  12. end
  13. class Schueler < Sequel::Model(:schueler)
  14. one_to_many :sprecher_stimmen, :key => :sprecher_id, :class => :Sprecher
  15. one_to_many :schuko_stimmen, :key => :schuko_id, :class => :Schuko
  16. end
  17. class Lehrer < Sequel::Model(:lehrer)
  18. one_to_many :lehrer_stimmen, :key => :lehrer_id, :class => :Verbindungslehrer
  19. end
  20. class Info < Sequel::Model(:infos);end
  21. class Sprecher < Sequel::Model(:sprecher);end
  22. class Schuko < Sequel::Model(:schuko);end
  23. class Verbindungslehrer < Sequel::Model(:verbindungslehrer);end
  24. class SV < Sinatra::Application
  25. configure do
  26. enable :sessions
  27. set :session_secret, (ENV['SV_SESSION_SECRET'] || 'your_secret')
  28. Slim::Engine.set_options pretty: true
  29. enable :static
  30. set :public_folder, File.dirname(__FILE__) + '/public'
  31. end
  32. configure :production do
  33. newrelic_ignore '/ping'
  34. end
  35. helpers do
  36. def protected!
  37. return if authorized?
  38. headers['WWW-Authenticate'] = 'Basic realm="Bitte anmelden"'
  39. halt 401, "Not authorized\n"
  40. end
  41. def authorized?
  42. @auth ||= Rack::Auth::Basic::Request.new(request.env)
  43. @auth.provided? and @auth.basic? and @auth.credentials and @auth.credentials == [ENV['SV_BASIC_AUTH_USER'], ENV['SV_BASIC_AUTH_PASSWORD']]
  44. end
  45. def hashids
  46. hashids = Hashids.new(ENV['SV_SESSION_SECRET'], 5, "ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnpqrstuvwxyz23456789")
  47. end
  48. end
  49. error do
  50. 'Es ist ein Fehler aufgetreten. Sollte das nochmal passieren, schreiben Sie mir doch bitte eine eMail: bk@hmt.im'
  51. end
  52. before do
  53. if session[:flash] && session[:flash][0] == 0
  54. logger.info session[:flash][1]
  55. end
  56. end
  57. get '/' do
  58. infos = Info.all
  59. slim :home, :locals => {:infos => infos}
  60. end
  61. get '/ping' do
  62. [200]
  63. end
  64. post "/wahl" do
  65. if Time.now > time_for('Sep 30, 2016, 18:00')
  66. session[:flash] = [0, "Sie können sich nicht mehr aufstellen lassen, die Wahl hat bereits begonnen"]
  67. redirect back
  68. end
  69. schueler = Schueler.where(:hashid => params[:hashid]).first
  70. if schueler.update_fields params, [:info, :email, :schuko, :sprecher, :nachname]
  71. session[:flash] = [1, "Ihre Eingabe wurde gespeichert"]
  72. else
  73. session[:flash] = [0, "Es gab einen Fehler beim Speichern"]
  74. end
  75. redirect back
  76. end
  77. post '/info' do
  78. protected!
  79. if DB[:infos].insert(params)
  80. session[:flash] = [1, "Die Info wurde gespeichert"]
  81. else
  82. session[:flash] = [0, "Es gab einen Fehler beim Speichern der Info"]
  83. end
  84. redirect to("/")
  85. end
  86. get '/info_loeschen/:id' do |id|
  87. protected!
  88. Info.where(:id => id).first.delete
  89. redirect back
  90. end
  91. get '/info' do
  92. protected!
  93. infos = Info.all
  94. slim :info, :locals => {:infos => infos}
  95. end
  96. get '/ergebnis' do
  97. protected!
  98. sprecher, schuko, lehrer, waehler = [], [], [], 0
  99. DB.transaction do
  100. sprecher = Schueler.where(:sprecher => true).all
  101. schuko = Schueler.where(:schuko => true).all
  102. lehrer = Lehrer.all
  103. waehler = Schueler.where(:gewaehlt => true).count
  104. end
  105. slim :ergebnis, :locals => {:sprecher => sprecher, :schuko => schuko, :lehrer => lehrer, :waehler => waehler}
  106. end
  107. post "/hashid" do
  108. redirect to("/#{params[:hashid]}")
  109. end
  110. get "/:hashid" do
  111. schueler = Schueler.where(:hashid => params[:hashid]).first
  112. if schueler.nil?
  113. halt 404, "Adresse richtig abgetippt? Eventuell geht es mit dem QR-Code am Telefon leichter?"
  114. end
  115. lehrer = Lehrer.all
  116. slim :hashid, :locals => {:schueler => schueler, :lehrer => lehrer}
  117. end
  118. post "/:hashid" do
  119. if Time.now > time_for('Oct 3, 2016, 18:00')
  120. session[:flash] = [0, "Der Wahlzeitraum ist seit 3. Oktober 18:00 Uhr abgelaufen."]
  121. redirect back
  122. elsif Time.now < time_for('Sep 30, 2016, 18:00')
  123. session[:flash] = [0, "Der Wahlzeitraum beginnt erst am 30. September um 18:00 Uhr."]
  124. redirect back
  125. end
  126. schueler = Schueler.where(:hashid => params[:hashid]).first
  127. if schueler.nil?
  128. halt 404, "Hier stimmt etwas nicht mit Ihrem persönlichen Code"
  129. end
  130. if schueler.gewaehlt
  131. session[:flash] = [0, "Sie haben schon gewählt"]
  132. redirect back
  133. end
  134. sprecher, schuko, lehrer = params[:sprecher], params[:schuko], params[:lehrer]
  135. if sprecher && sprecher.count > 2
  136. session[:flash] = [0, "Zu viele Sprecher gewählt (max. 2)"]
  137. redirect back
  138. elsif schuko && schuko.count > 8
  139. session[:flash] = [0, "Zu viele Vertreter für die Schulkonferenz gewählt (max. 8)"]
  140. redirect back
  141. elsif lehrer && lehrer.count > 2
  142. session[:flash] = [0, "Zu viele Vertrauenslehrer gewählt (max. 2)"]
  143. redirect back
  144. end
  145. stimm_ids = []
  146. sprecher_ids, schuko_ids, lehrer_ids =[], [], []
  147. stimmabgabe = DB.transaction do
  148. sprecher && sprecher.to_set.each do |s|
  149. if Schueler[s].sprecher
  150. sprecher_ids << DB[:sprecher].insert(:sprecher_id => s)
  151. else
  152. raise Sequel::Rollback
  153. session[:flash] = [0, "Es wurde ein nichtaufgestellter Sprecher gewählt"]
  154. redirect back
  155. end
  156. end
  157. schuko && schuko.to_set.each do |s|
  158. if Schueler[s].schuko
  159. schuko_ids << DB[:schuko].insert(:schuko_id => s)
  160. else
  161. raise Sequel::Rollback
  162. session[:flash] = [0, "Es wurde ein nichtaufgestellter Vertreter zur Schulkonferenz gewählt"]
  163. redirect back
  164. end
  165. end
  166. lehrer && lehrer.to_set.each do |l|
  167. lehrer_ids << DB[:verbindungslehrer].insert(:lehrer_id => l)
  168. end
  169. schueler.update(:gewaehlt => true)
  170. end
  171. stimm_ids << sprecher_ids << schuko_ids << lehrer_ids
  172. stimm_hash = stimm_ids.map do |s_id|
  173. return "" if s_id.nil?
  174. hashids.encode s_id
  175. end
  176. if stimmabgabe
  177. session[:flash] = [1, "Ihre Wahl wurde gespeichert"]
  178. session[:stimm_hash] = stimm_hash.join("l")
  179. else
  180. session[:flash] = [0, "Es gab einen Fehler bei der Speicherung der Wahlergebnisse"]
  181. end
  182. redirect back
  183. end
  184. end