veto

Simple Sinatra voting website.
git clone git://git.knutsen.co/veto
Log | Files | Refs | README | LICENSE

commit 3a477f8b0f58503d00ab3cb5890e9b423fc6a622
parent 6ef7c0a082c03f65ebfa7c329c5e845029349625
Author: Fredrik <moi@knutsen.co>
Date:   Mon, 29 Oct 2018 17:33:30 +0000

Merge pull request #6 from Demonstrandum/devel

Update to using MongoDB
Diffstat:
A.gitignore | 41+++++++++++++++++++++++++++++++++++++++++
MGemfile | 1+
MGemfile.lock | 6++++--
Mnow.json | 5++++-
Mpublic/styles.css | 8++++++--
Mserver.rb | 93+++++++++++++++++++++++++------------------------------------------------------
Cserver.rb -> server.rb.old | 0
Mviews/index.erb | 12++++++++++--
8 files changed, 95 insertions(+), 71 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -0,0 +1,41 @@ +# gem +*.gem + +# Shh, web stuff +tmp/ +log/ + +## System and release files ## +# OS files +.DS_Store +.DS_Store? +._* +.Spotlight-V100 +.Trashes +ehthumbs.db +Thumbs.db +*.swp +*.ini + +# Compiled files +*.com +*.class +*.dll +*.exe +*.o +*.so + +# Packages +*.7z +*.dmg +*.gz +*.iso +*.jar +*.rar +*.tar +*.zip + +# Debug logs and databases +*.log +*.sql +*.sqlite diff --git a/Gemfile b/Gemfile @@ -5,3 +5,4 @@ gem 'rack', '~> 2.0', '>= 2.0.5' gem 'rack-ssl', '~> 1.4' gem 'sinatra', '~> 2.0', '>= 2.0.1' gem 'json' +gem 'mongo' diff --git a/Gemfile.lock b/Gemfile.lock @@ -1,9 +1,12 @@ GEM remote: https://rubygems.org/ specs: + bson (4.3.0) daemons (1.2.6) eventmachine (1.2.7) json (2.1.0) + mongo (2.6.2) + bson (>= 4.3.0, < 5.0.0) mustermann (1.0.3) rack (2.0.5) rack-protection (2.0.4) @@ -15,7 +18,6 @@ GEM rack (~> 2.0) rack-protection (= 2.0.4) tilt (~> 2.0) - symbolized (0.0.1) thin (1.7.2) daemons (~> 1.0, >= 1.0.9) eventmachine (~> 1.0, >= 1.0.4) @@ -27,10 +29,10 @@ PLATFORMS DEPENDENCIES json + mongo rack (~> 2.0, >= 2.0.5) rack-ssl (~> 1.4) sinatra (~> 2.0, >= 2.0.1) - symbolized thin BUNDLED WITH diff --git a/now.json b/now.json @@ -1,5 +1,8 @@ { "name": "Veto", "alias": "veto.vote", - "type": "docker" + "type": "docker", + "env": { + "MONGO_DB": "@mongo_url_secret" + } } diff --git a/public/styles.css b/public/styles.css @@ -217,6 +217,10 @@ h3 { border-bottom: 2px solid; } +.issues h3 { + color: inherit; +} + .issues .show { max-height: 300px; opacity: 1; @@ -225,7 +229,7 @@ h3 { .issues .error { background: #ffc8b3; border-color: #ff5436; - color: #800; + color: #800 !important; } .issues .error p { @@ -236,7 +240,7 @@ h3 { .issues .warning { background: #ffeab3; border-color: #ffc136; - color: #885a00; + color: #885a00 !important; } .issues .warning p { diff --git a/server.rb b/server.rb @@ -1,4 +1,4 @@ -require 'net/http' +require 'mongo' require 'json' require 'sinatra' @@ -11,57 +11,24 @@ enable :sessions before { request.path_info.sub! %r{/$}, "" } -$INDIFFERENT = proc do |h, k| - case k - when String then sym = k.to_sym; h[sym] if h.key?(sym) - when Symbol then str = k.to_s; h[str] if h.key?(str) - end -end - -$polls = { - :'this-is-a-poll-name' => { - :name => 'This is a poll name', - :votes => {}, - :alt => true, - :voters => [] - } -} # Example. - -$JSON_ID = '1arifg' -$JSON_BASE = 'https://api.myjson.com' +# ENV['MONGO_DB'] variable with Now secrets, or just in your shell if local. +CLIENT = Mongo::Client.new "#{ENV['MONGO_DB']}/Veto" +POLLS = CLIENT[:polls] -String.class_eval { def to_uri; URI(self); end } -$polls.default_proc = $INDIFFERENT - -def request_json - puts "[!!] Requesting JSON, ID: #{$JSON_ID}" - response = Net::HTTP.get "#{$JSON_BASE}/bins/#{$JSON_ID}".to_uri - $polls = JSON.parse response, {:symbolize_names => true} - $polls.default_proc = $INDIFFERENT - pp $polls -end - -def save_json - puts "[!!] Saving JSON, ID: #{$JSON_ID}" - uri = "#{$JSON_BASE}/bins/#{$JSON_ID}".to_uri - puts "[!!]\tURI: #{uri}" - req = Net::HTTP::Put.new uri - req.set_content_type 'application/json' - req.body = $polls.to_json - res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request req } - puts "[!!]\tResponse: #{res.inspect}" +def poll_exist? code + POLLS.find({:code => code}).to_a.size > 0 end -request_json # Initial JSON retrieval - def make_poll code, name, alt - $polls[code] = { + alt = alt.to_s == 'true' + poll = { + :code => code, :name => name, :votes => {}, :alt => alt, :voters => [] } - save_json + POLLS.insert_one poll end $HEAD_TAGS = <<-HTML @@ -97,7 +64,7 @@ get '/share/:code' do end post '/new' do - return nil if $polls.keys.include? params[:code] + return nil if poll_exist? params[:code] make_poll( params[:code], @@ -105,47 +72,45 @@ post '/new' do params[:alt]) params[:primary].each do |option| - $polls[params[:code]][:votes][option] = { - :number => 0, - :primary => true - } + POLLS.update_one({:code => params[:code]}, { + :"$set" => { + :"votes.#{option}" => { + :number => 0, + :primary => true + } + } + }) end - save_json end get '/poll/:poll' do - unless $polls.keys.map(&:to_s).include? params[:poll] + unless poll_exist? params[:poll] return "This poll has not been created/does not exist!" end local = {:code => params[:poll], :head_tags => $HEAD_TAGS} - local.merge! $polls[params[:poll]] + local.merge! Hash.from_bson POLLS.find({:code => params[:poll]}).first.to_bson erb :poll, :locals => local end post '/poll/:poll/cast' do - return nil if $polls[params[:poll]][:voters].include? request.ip - $polls[params[:poll]][:voters].push request.ip + return nil if POLLS.find(:"$and" => [{:code => params[:poll]}, {:voters => request.ip}]).to_a.size > 0 + POLLS.update_one({:code => params[:poll]}, {:"$push" => {:voters => request.ip}}) - if $polls[params[:poll]][:votes].keys.include? params[:vote] - $polls[params[:poll]][:votes][params[:vote]][:number] += 1 + if POLLS.find({ :"votes.#{params[:vote]}" => {"$exists": true} }) + POLLS.update_one({:code => params[:poll]}, { :"$inc" => { :"votes.#{params[:vote]}.number" => 1 } }) else - $polls[params[:poll]][:votes][params[:vote]] = { + POLLS.update_one({:code => params[:poll]}, {:"$set" => {:"vote.#{params[:vote]}" => { :number => 1, :primary => false - } + }}}) end - save_json end get '/poll/:poll/votes.json' do - $polls[params[:poll]][:votes].to_json + (Hash.from_bson POLLS.find({:code => params[:poll]}).to_a.first.to_bson)[:votes].to_json end get '/polls.json' do - $polls.keys.map(&:to_s).to_json -end - -get '/exported.json' do - $polls.to_json + POLLS.find.to_a.map { |doc| doc[:code] }.to_json end diff --git a/server.rb b/server.rb.old diff --git a/views/index.erb b/views/index.erb @@ -139,12 +139,20 @@ } }); + $(document).on('keypress', '.editor', key => { + if (key.which === 13 || key.which === 10) { + key.preventDefault(); + save(); + editing = NaN; + } + }); + $("#addition").on('keypress', key => { let value = $("#addition").val().trim(); let values = Array(...$('#options li span').map((i, e) => e.innerHTML)); - if (key.which === 13) { - save(); + if (key.which === 13 || key.which === 10) { key.preventDefault(); + save(); if (value.length === 0) { return $('#addition').attention(); }