Compare commits

...

2 Commits
v1.2 ... master

Author SHA1 Message Date
byte-chan™ deeba9420f Fix /delete not deleting answers 2018-03-13 09:54:19 +01:00
byte-chan™ ae40be448e Code cleanup (#1) 2018-03-13 09:52:19 +01:00
2 changed files with 82 additions and 87 deletions

167
server.rb
View File

@ -7,8 +7,6 @@ require "sinatra"
require "json" require "json"
require_relative "sql" require_relative "sql"
set :bind, '0.0.0.0'
class String class String
def escape def escape
self.gsub("&", "&amp;").gsub("<", "&lt;").gsub("\"", "&quot;") self.gsub("&", "&amp;").gsub("<", "&lt;").gsub("\"", "&quot;")
@ -18,34 +16,7 @@ end
get "/" do get "/" do
@title = PROJECT_DISPLAYNAME @title = PROJECT_DISPLAYNAME
@description = "Ask questions, copy link, get answers. Powered by Ruby, Sinatra and SQLite." @description = "Ask questions, copy link, get answers. Powered by Ruby, Sinatra and SQLite."
erb <<~BODY erb :home
<form id="f_question" action="/q" method="post"><div class="formdiv">
<input type="text" name="q_text" style="width: 100%; margin-bottom: 1em;" placeholder="Question"/>
<textarea name="q_options" style="width: 100%; height: 200px;" placeholder="Add answers here, one per line"></textarea>
<input type="submit" class="submit-main" value="Submit"/>
</div></form>
<h1>simplePoll</h1>
<p>simplePoll is a simple poll service powered by Ruby, Sinatra and SQLite. Static files are loaded into memory to improve performance. Using advanced IP address technology, users can only submit one answer for polls.</p>
<p>simplePoll also offers a simple API for poll information in JSON format:</p>
<pre>
/api/&lt;question_id&gt; =&gt; {
"id": question_id,
"text": "Question text",
"answers": [
{
"id": answer_id,
"text": "Answer 1",
"count": 3
},
{
"id": answer_id,
"text": "Answer 2"
"count": 37547821
}
]
}
</pre>
BODY
end end
get "/style.css" do get "/style.css" do
@ -53,14 +24,6 @@ get "/style.css" do
erb :style, layout: false erb :style, layout: false
end end
get "/error" do
raise Exception.new("OH NOES")
end
get "/secret" do
403
end
post "/q" do post "/q" do
text = params[:q_text] text = params[:q_text]
options_raw = params[:q_options] options_raw = params[:q_options]
@ -68,27 +31,15 @@ post "/q" do
if not text or not options_raw then if not text or not options_raw then
status 400 status 400
@title = "Invalid input" @title = "Invalid input"
erb <<~BODY erb :question_invalid
<h1>Invalid input</h1>
<p>Missing POST data</p>
<a onclick="history.back();" class="button">&lt;&lt; Try again</a>
BODY
elsif text.size < 10 then elsif text.size < 10 then
status 400 status 400
@title = "Invalid input" @title = "Invalid input"
erb <<~BODY erb :question_short
<h1>Invalid input</h1>
<p>Question too short</p>
<a onclick="history.back();" class="button">&lt;&lt; Try again</a>
BODY
elsif options.size < 2 then elsif options.size < 2 then
status 400 status 400
@title = "Invalid input" @title = "Invalid input"
erb <<~BODY erb :question_noanswers
<h1>Invalid input</h1>
<p>At least 2 answers required</p>
<a onclick="history.back();" class="button">&lt;&lt; Try again</a>
BODY
else else
q = new_question(text, options) q = new_question(text, options)
puts("Question #{q.id} created by #{request.ip.inspect}") puts("Question #{q.id} created by #{request.ip.inspect}")
@ -145,7 +96,19 @@ get %r{/q/([0-9]+)/delete} do |id|
end end
end end
get %r{/q/([0-9]+)$} do |id| get %r{/q/([0-9]+)/answer} do |id|
if question_exists? id.to_i then
if params["answer"] then
puts("Trying to submit answer for #{request.ip.inspect}")
Question.new(id.to_i).add_answer(request.ip, params["answer"])
end
redirect to "/q/#{id}"
else
404
end
end
get %r{/q/([0-9]+)} do |id|
if question_exists? id.to_i then if question_exists? id.to_i then
@q = Question.new(id.to_i) @q = Question.new(id.to_i)
@qdata = @q.summary @qdata = @q.summary
@ -161,36 +124,7 @@ get %r{/q/([0-9]+)$} do |id|
else else
@delete_code = "" @delete_code = ""
end end
erb <<~BODY erb :answer_form
<form id="f_answer" action="/q/<%=@qdata[:id]%>/answer"><div class="formdiv">
<strong><%=@qdata[:text].escape%></strong>
<ul id="q_options"><% for opt in @qdata[:options] do %>
<li class="q_option">
<input type="radio" required id="radio<%= opt[:id] %>" name="answer" value="<%= opt[:id] %>"/><label for="radio<%= opt[:id] %>"><%= opt[:text].escape %></label><span style="float: right;"><%= opt[:count] %></span><br/>
<div class="q_answer_bar">
<div style="width: <%= @answer_count > 0 ? (opt[:count] / @answer_count.to_f)*100 : 0 %>%;"></div>
</div>
</li>
<% end %></ul>
<input type="submit" class="submit-main" value="Submit answer"/>
</div></form>
<form id="f_delete" action="/q/<%=@qdata[:id]%>/delete"><div class="formdiv">
<input type="text" size="32" name="code" placeholder="Code" value="#{@delete_code}"/>
<input type="submit" class="submit-delete" value="Delete"/>
</div></form>
BODY
else
404
end
end
get %r{/q/([0-9]+)/answer} do |id|
if question_exists? id.to_i then
if params["answer"] then
puts("Trying to submit answer for #{request.ip.inspect}")
Question.new(id.to_i).add_answer(request.ip, params["answer"])
end
redirect to "/q/#{id}"
else else
404 404
end end
@ -399,7 +333,7 @@ a.button:hover {
@@ e403 @@ e403
<h1>403 Forbidden</h1> <h1>403 Forbidden</h1>
<p>You're doing this to yourself. Stop.</p> <p>You do not have access to the requested location.</p>
@@ notfound @@ notfound
<h1>404 Not Found</h1> <h1>404 Not Found</h1>
@ -407,6 +341,67 @@ a.button:hover {
@@ e500 @@ e500
<h1>500 Internal Server Error</h1> <h1>500 Internal Server Error</h1>
<p>This shouldn't've happened.</p> <p>The server has encountered an error while processing your request.</p>
<p style="font-size: 50%;"><%= env["sinatra.error"].message %></p> <p style="font-size: 50%;"><%= env["sinatra.error"].message %></p>
@@ question_invalid
<h1>Invalid input</h1>
<p>Missing POST data</p>
<a onclick="history.back();" class="button">&lt;&lt; Try again</a>
@@ question_short
<h1>Invalid input</h1>
<p>Question too short</p>
<a onclick="history.back();" class="button">&lt;&lt; Try again</a>
@@ question_noanswers
<h1>Invalid input</h1>
<p>At least 2 answers required</p>
<a onclick="history.back();" class="button">&lt;&lt; Try again</a>
@@ home
<form id="f_question" action="/q" method="post"><div class="formdiv">
<input type="text" name="q_text" style="width: 100%; margin-bottom: 1em;" placeholder="Question"/>
<textarea name="q_options" style="width: 100%; height: 200px;" placeholder="Add answers here, one per line"></textarea>
<input type="submit" class="submit-main" value="Submit"/>
</div></form>
<h1>simplePoll</h1>
<p>simplePoll is a simple poll service powered by Ruby, Sinatra and SQLite. Static files are loaded into memory to improve performance. Using advanced IP address technology, users can only submit one answer for polls.</p>
<p>simplePoll also offers a simple API for poll information in JSON format:</p>
<pre>
/api/&lt;question_id&gt; =&gt; {
"success": true,
"id": question_id,
"text": "Question text",
"answers": [
{
"id": answer_id,
"text": "Answer 1",
"count": 3
},
{
"id": answer_id,
"text": "Answer 2"
"count": 37547821
}
]
}
</pre>
@@ answer_form
<form id="f_answer" action="/q/<%=@qdata[:id]%>/answer"><div class="formdiv">
<strong><%=@qdata[:text].escape%></strong>
<ul id="q_options"><% for opt in @qdata[:options] do %>
<li class="q_option">
<input type="radio" required id="radio<%= opt[:id] %>" name="answer" value="<%= opt[:id] %>"/><label for="radio<%= opt[:id] %>"><%= opt[:text].escape %></label><span style="float: right;"><%= opt[:count] %></span><br/>
<div class="q_answer_bar">
<div style="width: <%= @answer_count > 0 ? (opt[:count] / @answer_count.to_f)*100 : 0 %>%;"></div>
</div>
</li>
<% end %></ul>
<input type="submit" class="submit-main" value="Submit answer"/>
</div></form>
<form id="f_delete" action="/q/<%=@qdata[:id]%>/delete"><div class="formdiv">
<input type="text" size="32" name="code" placeholder="Code" value="<%= @delete_code %>"/>
<input type="submit" class="submit-delete" value="Delete"/>
</div></form>

2
sql.rb
View File

@ -101,7 +101,7 @@ end
def delete_question(id) def delete_question(id)
sql(<<~SQL, [id]) sql(<<~SQL, [id])
DELETE FROM q_answers WHERE q_answers.o_id IN ( DELETE FROM q_answers WHERE q_answers.id IN (
SELECT q_answers.id FROM q_options WHERE q_answers.o_id = q_options.id AND q_options.q_id = ?1 SELECT q_answers.id FROM q_options WHERE q_answers.o_id = q_options.id AND q_options.q_id = ?1
); );
SQL SQL