summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpdp8 <pdp8@pdp8.info>2023-06-03 19:34:40 +0200
committerpdp8 <pdp8@pdp8.info>2023-06-03 19:34:40 +0200
commit23d72528a829e080ca6a508a217a700f04217d4a (patch)
tree2c3ad7a941fe7102a5edeca616f9c0937b225fe6
parent86c8118c9b908af2f0c2a74d2bc9f7af431e4e12 (diff)
sessions and login
-rw-r--r--activitypub.rb255
-rw-r--r--application.rb415
-rw-r--r--config.ru6
3 files changed, 101 insertions, 575 deletions
diff --git a/activitypub.rb b/activitypub.rb
index c019d6e..05ed6e0 100644
--- a/activitypub.rb
+++ b/activitypub.rb
@@ -20,7 +20,8 @@ ACCOUNT = "#{USER}@#{SOCIAL_DOMAIN}"
SOCIAL_URL = "https://#{SOCIAL_DOMAIN}"
ACTOR = File.join(SOCIAL_URL, USER)
-use Rack::Reloader
+enable :sessions
+set :session_secret, File.read(".secret").chomp
set :default_content_type, 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"'
set :port, 9292
@@ -33,24 +34,30 @@ end
post "/inbox" do # server-server
request.body.rewind # in case someone already read it
body = request.body.read
+ p body
action = JSON.parse body
case action["type"]
+
when "Create"
create action["object"]
+
when "Delete"
delete action["object"]
+
when "Update"
delete action["object"]
create action["object"]
+
when "Follow"
File.open(File.join("public", "followers", mention(action["actor"]) + ".json"), "w+") { |f| f.puts body }
accept = { "@context" => "https://www.w3.org/ns/activitystreams",
"id" => File.join(SOCIAL_URL + "#accepts", SecureRandom.uuid),
"type" => "Accept",
"actor" => ACTOR,
- "object" => object }
- send_signed accept, accept["object"]["actor"]
+ "object" => action["object"] }
+ send_signed accept, action["actor"]
+
when "Undo"
o = action["object"]
case o["type"]
@@ -59,12 +66,14 @@ post "/inbox" do # server-server
FileUtils.rm follower if JSON.parse(File.read(follower))["actor"] == o["actor"]
end
end
+
else
p body
end
end
post "/outbox" do # client-server
+ protected!
request.body.rewind # in case someone already read it
body = request.body.read
date = Time.now.strftime("%Y-%m-%dT%H:%M:%S")
@@ -107,54 +116,75 @@ post "/outbox" do # client-server
recipients.each { |r| send_signed create, r }
end
+post "/delete/*" do
+ protected!
+ FileUtils.rm params['splat'][0]
+ redirect to("/inbox")
+end
+
+post "/follow/*" do
+ protected!
+ mention = params['splat'][0]
+ actor = actor(mention)
+ p actor
+ following_path = File.join("public", "following", mention + ".json")
+ follow = { "@context" => "https://www.w3.org/ns/activitystreams",
+ "id" => File.join(SOCIAL_URL, following_path),
+ "type" => "Follow",
+ "actor" => ACTOR,
+ "object" => actor }
+ send_signed follow, actor
+ File.open(following_path, "w+") { |f| f.puts follow.to_json }
+ redirect to("/inbox")
+end
+
+post "/unfollow/*" do
+ protected!
+ mention = params['splat'][0]
+ actor = actor(mention)
+ following_path = File.join("public", "following", mention + ".json")
+ if File.exists?(following_path)
+ undo = { "@context" => "https://www.w3.org/ns/activitystreams",
+ "id" => File.join(SOCIAL_URL + "#undo", SecureRandom.uuid),
+ "type" => "Undo",
+ "actor" => ACTOR,
+ "object" => JSON.parse(File.read(following_path)) }
+ send_signed undo, actor
+ FileUtils.rm following_path
+ redirect to("/inbox")
+ end
+end
+
+post "/login" do
+ session["client"] = true if params["secret"] == File.read(".pwd").chomp
+ redirect to("/inbox")
+end
+
get "/.well-known/webfinger" do
if request["resource"] == "acct:#{ACCOUNT}"
send_file "./webfinger", :type => "application/jrd+json"
else
- 404
+ halt 404
end
end
get "/inbox", :provides => 'html' do
- erb "<!DOCTYPE html>
- <html lang='en'>
- <body>
- <% Dir['./inbox/*'].sort.each_with_index do |file,i| %>
- <% item = JSON.parse(File.read(file)) %>
- <%= i+1 %>&nbsp;<b><%= mention item['attributedTo'] %></b>&nbsp;<i><%= item['published'].sub('T', ' ') %></i>
- <p><%= item['content'] %>
- <% if item['attachment']
- item['attachment'].each do |att|
- case att['mediaType']
- when /audio/ %>
- <br><audio controls=''><source src='<%= att['url'] %>' type='<%= att['mediaType'] %>'></audio>
- <% when /image/ %>
- <br><a href='<%= att['url'] %>'><img src='<%= att['url'] %>'></a>
- <% when /video/ %>
- <br><video controls=''><source src='<%= att['url'] %>' type='<%= att['mediaType'] %>'></video>
- <% else %>
- <%= att %><br>
- <a href='<%= att['url'] %>'><%= att['url'] %></a>
- <% end %>
- <% end %>
- <% end %>
- <p>
- <form action='<%= File.join 'delete', file %>' method='post'>
- <button>Delete</button>
- </form>
- <form action='<%= File.join 'boost', file %>' method='post'>
- <button>Boost</button>
- </form>
- <form action='<%= File.join 'archive', file %>' method='post'>
- <button>Archive</button>
- </form>
- <form action='<%= File.join 'reply', file %>' method='post'>
- <button>Reply</button>
- </form>
- <hr>
- <% end %>
- </body>
- </html>"
+ protected!
+ @inbox = Dir['./inbox/*'].sort
+ p @inbox
+ erb :inbox
+end
+
+["/outbox","/following","/followers"].each do |path|
+ get path do
+ ordered_collection(path).to_json
+ end
+end
+
+helpers do
+ def protected!
+ redirect("/login.html") unless session['client']
+ end
end
def delete object
@@ -183,7 +213,7 @@ def get url, accept = 'application/ld+json; profile="https://www.w3.org/ns/activ
end
def ordered_collection dir
- posts = Dir[File.join(dir, "*.json")].collect { |f| JSON.parse(File.read f) }.sort_by { |o| o["published"] }
+ posts = Dir[File.join("public",dir, "*.json")].collect { |f| JSON.parse(File.read f) }.sort_by { |o| o["published"] }
{
"@context" => "https://www.w3.org/ns/activitystreams",
"summary" => "#{USER} #{dir}",
@@ -224,36 +254,43 @@ def send_signed object, url
end
def inbox uri
+ p "INBOX"
+ p uri
+ p get(uri)
URI(get(uri)["inbox"]).request_uri
end
def verify_signature env
# https://github.com/mastodon/mastodon/blob/main/app/controllers/concerns/signature_verification.rb
# TODO verify digest
- signature_params = {}
- env["HTTP_SIGNATURE"].split(',').each do |pair|
- k, v = pair.split('=')
- signature_params[k] = v.gsub('"', '')
- end
+ begin
+ signature_params = {}
+ env["HTTP_SIGNATURE"].split(',').each do |pair|
+ k, v = pair.split('=')
+ signature_params[k] = v.gsub('"', '')
+ end
- key_id = signature_params['keyId']
- headers = signature_params['headers']
- signature = Base64.decode64(signature_params['signature'])
+ key_id = signature_params['keyId']
+ headers = signature_params['headers']
+ signature = Base64.decode64(signature_params['signature'])
- actor = get key_id
- key = OpenSSL::PKey::RSA.new(actor['publicKey']['publicKeyPem'])
+ actor = get key_id
+ key = OpenSSL::PKey::RSA.new(actor['publicKey']['publicKeyPem'])
- comparison = headers.split(' ').map do |signed_params_name|
- if signed_params_name == '(request-target)'
- '(request-target): post /inbox'
- elsif signed_params_name == 'content-type'
- "#{signed_params_name}: #{env["CONTENT_TYPE"]}"
- else
- "#{signed_params_name}: #{env["HTTP_" + signed_params_name.upcase]}"
- end
- end.join("\n")
+ comparison = headers.split(' ').map do |signed_params_name|
+ if signed_params_name == '(request-target)'
+ '(request-target): post /inbox'
+ elsif signed_params_name == 'content-type'
+ "#{signed_params_name}: #{env["CONTENT_TYPE"]}"
+ else
+ "#{signed_params_name}: #{env["HTTP_" + signed_params_name.upcase]}"
+ end
+ end.join("\n")
- key.verify(OpenSSL::Digest.new('SHA256'), signature, comparison)
+ key.verify(OpenSSL::Digest.new('SHA256'), signature, comparison)
+ rescue
+ false
+ end
end
def actor mention
@@ -264,93 +301,3 @@ def actor mention
l["rel"] == "self"
}[0]["href"]
end
-
-=begin
-
-class Application
- def call(env)
- code = 404
- type = 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"'
- response = "Not found."
-
- case env['REQUEST_METHOD']
-
- when 'POST'
- input = env["rack.input"].read
- case env["REQUEST_PATH"]
-
- when %r{/delete} # receive from client
- if auth(env)
- FileUtils.rm env["REQUEST_URI"].sub("/delete/", "")
- return [302, { "Location" => "/inbox" }, []]
- end
-
- when "/outbox" # receive from client
- p "outbox"
- if auth(env)
- p "OK"
- else
- code = 403
- response = "You are not allowed to POST to #{env["REQUEST_URI"]}."
- end
-
- when "/follow" # receive from client
- if auth(env)
- input.split.each do |mention|
- actor = actor(mention)
- follow = { "@context" => "https://www.w3.org/ns/activitystreams",
- "id" => File.join(SOCIAL_URL, "following", SecureRandom.uuid + ".json"),
- "type" => "Follow",
- "actor" => ACTOR,
- "object" => actor }
- save follow
- puts(send follow, [actor])
- code = 200
- response = "OK"
- end
- else
- code = 403
- response = "You are not allowed to POST to #{env["REQUEST_URI"]}."
- end
-
- when "/unfollow" # receive from client
- if auth(env)
- input.split.each do |mention|
- actor = actor(mention)
- Dir["following/*.json"].each do |f|
- follow = JSON.parse(File.read(f))
- puts follow
- if follow["object"] == actor
- undo = { "@context" => "https://www.w3.org/ns/activitystreams",
- "id" => File.join(SOCIAL_URL + "#undo", SecureRandom.uuid),
- "type" => "Undo",
- "actor" => ACTOR,
- "object" => follow }
- send undo, [actor]
- FileUtils.rm f
- end
- end
- end
- end
- end
-
-
- def path object
- object["id"].sub(SOCIAL_URL, '').sub('/', '')
- end
-
- def save object
- path = path object
- FileUtils.mkdir_p File.dirname(path)
- File.open(path, "w+") { |f| f.puts object.to_json }
- end
-
- def auth env
- auth = Rack::Auth::Basic::Request.new(env)
- usr = File.read(".usr").chomp
- pwd = File.read(".pwd").chomp
- auth.provided? && auth.basic? && auth.credentials && auth.credentials == [usr, pwd]
- true
- end
-end
-=end
diff --git a/application.rb b/application.rb
deleted file mode 100644
index c8a657c..0000000
--- a/application.rb
+++ /dev/null
@@ -1,415 +0,0 @@
-# TODO
-# unwrap and save object from create
-# boost
-# archive
-# threads
-# federation
-# client post media
-# test with pleroma etc
-require 'json'
-require 'net/http'
-require 'uri'
-require 'base64'
-require 'securerandom'
-require 'fileutils'
-require 'digest/sha2'
-require 'nokogiri'
-
-USER = "pdp8"
-WWW_DOMAIN = "pdp8.info"
-WWW_URL = "https://#{WWW_DOMAIN}"
-SOCIAL_DOMAIN = "social.#{WWW_DOMAIN}"
-
-ACCOUNT = "#{USER}@#{SOCIAL_DOMAIN}"
-SOCIAL_URL = "https://#{SOCIAL_DOMAIN}"
-ACTOR = File.join(SOCIAL_URL, USER)
-
-class Application
- def call(env)
- code = 404
- type = 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"'
- response = "Not found."
-
- case env['REQUEST_METHOD']
-
- when 'POST'
- input = env["rack.input"].read
- case env["REQUEST_PATH"]
-
- when "/inbox" # receive from server
- if verify(env)
- begin
- object = JSON.parse(input)
- case object["type"]
- when "Create"
- File.open(File.join("inbox", SecureRandom.uuid + ".json"), "w+") { |f| f.puts input }
- # File.open(File.join("inbox", input["published"] + ".json"), "w+") { |f| f.puts input["object"] }
- when "Delete"
- puts input
- when "Follow"
- File.open(File.join("followers", SecureRandom.uuid + ".json"), "w+") { |f| f.puts input }
- accept = { "@context" => "https://www.w3.org/ns/activitystreams",
- "id" => File.join(SOCIAL_URL + "#accepts", SecureRandom.uuid),
- "type" => "Accept",
- "actor" => ACTOR,
- "object" => JSON.parse(input) }
- send accept, [accept["object"]["actor"]]
- when "Undo"
- o = object["object"]
- case o["type"]
- when "Follow"
- Dir["followers/*.json"].each do |follower|
- if JSON.parse(File.read(follower))["actor"] == o["actor"]
- FileUtils.rm follower
- end
- end
- else
- puts input
- end
- else
- puts input
- end
- code = 200
- response = "OK"
- rescue => e
- puts input, e.to_s
- response = "Request body contains invalid json."
- end
- else
- code = 403
- response = "Key verification failed for POST to #{env["REQUEST_URI"]}."
- end
-
- when %r{/delete} # receive from client
- if auth(env)
- FileUtils.rm env["REQUEST_URI"].sub("/delete/", "")
- return [302, { "Location" => "/inbox" }, []]
- end
-
- when "/outbox" # receive from client
- if auth(env)
- code, response = parse input
- else
- code = 403
- response = "You are not allowed to POST to #{env["REQUEST_URI"]}."
- end
-
- when "/follow" # receive from client
- if auth(env)
- input.split.each do |mention|
- actor = actor(mention)
- follow = { "@context" => "https://www.w3.org/ns/activitystreams",
- "id" => File.join(SOCIAL_URL, "following", SecureRandom.uuid + ".json"),
- "type" => "Follow",
- "actor" => ACTOR,
- "object" => actor }
- save follow
- puts(send follow, [actor])
- code = 200
- response = "OK"
- end
- else
- code = 403
- response = "You are not allowed to POST to #{env["REQUEST_URI"]}."
- end
-
- when "/unfollow" # receive from client
- if auth(env)
- input.split.each do |mention|
- actor = actor(mention)
- Dir["following/*.json"].each do |f|
- follow = JSON.parse(File.read(f))
- puts follow
- if follow["object"] == actor
- undo = { "@context" => "https://www.w3.org/ns/activitystreams",
- "id" => File.join(SOCIAL_URL + "#undo", SecureRandom.uuid),
- "type" => "Undo",
- "actor" => ACTOR,
- "object" => follow }
- send undo, [actor]
- FileUtils.rm f
- end
- end
- end
- end
- end
-
- when 'GET'
-
- case env["REQUEST_URI"] # REQUEST_PATH does not contain queries
-
- when "/.well-known/webfinger?resource=acct:#{ACCOUNT}"
- type = "application/jrd+json"
- response = File.read("webfinger")
- code = 200
-
- when "/#{USER}"
- # TODO serve html
- response = File.read(USER)
- code = 200
-
- when "/inbox"
- if auth(env)
- case env["HTTP_ACCEPT"]
- when /json/
- response = ordered_collection(env["REQUEST_PATH"]).to_json
- else
- type = "text/html"
- response = html env["REQUEST_PATH"]
- end
- code = 200
- else
- code = 403
- response = "You are not allowed to GET #{env["REQUEST_URI"]}."
- end
-
- when %r{/[outbox|following|followers|likes|shares]}
- response = ordered_collection(env["REQUEST_PATH"]).to_json
- code = 200
- end
-
- end
- [code, { "Content-Type" => type }, [response]]
- end
-
- def html path
- html = "<!DOCTYPE html>\n<html lang='en'>\n\t<body>"
- Dir[File.join(path.sub(/^\//, ''), "*")].sort_by { |f| File.stat(f).ctime }.each do |file|
- item = JSON.parse(File.read(file))
- html << "\n\t\t<b>#{mention item["actor"]}</b>&nbsp;<i>#{item["object"]["published"].sub("T",
- " ")}</i><p>#{item["object"]["content"]}"
- if item["object"]["attachment"]
- item["object"]["attachment"].each do |att|
- case att["mediaType"]
- when /audio/
- html << "\n<br><audio controls=''><source src='#{att["url"]}' type='#{att["mediaType"]}'></audio>"
- when /image/
- html << "\n<br><a href='#{att["url"]}'><img src='#{att["url"]}'></a>"
- when /video/
- html << "\n<br><video controls=''><source src='#{att["url"]}' type='#{att["mediaType"]}'></video>"
- else
- html << att + "<br>"
- html << "\n<a href='#{att["url"]}'>#{att["url"]}</a>"
- end
- end
- end
- html << "<p>
- <form action='#{File.join "delete", file}' method='post'>
- <button>Delete</button>
- </form>
- <form action='#{File.join "boost", file}' method='post'>
- <button>Boost</button>
- </form>
- <form action='#{File.join "archive", file}' method='post'>
- <button>Archive</button>
- </form>
- <form action='#{File.join "reply", file}' method='post'>
- <button>Reply</button>
- </form>
- <hr>"
- end
- html << "\n\t</body>\n</html>"
- end
-=begin
-=end
-
-=begin
- def html o
- html = "<!DOCTYPE html>
-<html lang='en'>
- <body>
- <b>#{mention o["actor"]}</b>&nbsp;<i>#{o["object"]["published"]}</i>
- <p>#{o["object"]["content"]}
- "
- if o["object"]["attachment"]
- o["object"]["attachment"].each do |att|
- case att["mediaType"]
- when /audio/
- html<< "\n<br><audio controls=''><source src='#{att["url"]}' type='#{att["mediaType"]}'></audio>"
- when /image/
- html << "\n<br><a href='#{att["url"]}'><img src='#{att["url"]}'></a>"
- when /video/
- html<< "\n<br><video controls=''><source src='#{att["url"]}' type='#{att["mediaType"]}'></video>"
- else
- html<< att + "<br>"
- html << "\n<a href='#{att["url"]}'>#{att["url"]}</a>"
- end
- end
- end
- end
- html << "\n\t</body>\n</html>"
- html
- end
-=end
-
- def parse input
- date = Time.now.strftime("%Y-%m-%dT%H:%M:%S")
- # TODO media attachments, hashtags
- note = {
- "@context" => "https://www.w3.org/ns/activitystreams",
- "id" => File.join(SOCIAL_URL, "note", SecureRandom.uuid + ".json"),
- "type" => "Note",
- "attributedTo" => ACTOR,
- "published" => date,
- "content" => "",
- "to" => ["https://www.w3.org/ns/activitystreams#Public"]
- }
- create = {
- "@context" => "https://www.w3.org/ns/activitystreams",
- "id" => File.join(SOCIAL_URL, "create", SecureRandom.uuid + ".json"),
- "type" => "Create",
- "actor" => ACTOR,
- "object" => note,
- "published" => date,
- "to" => ["https://www.w3.org/ns/activitystreams#Public"]
- }
- recipients = []
- if /^@/.match input
- mentions, input = input.split("\n", 2)
- mentions.split(/, */).each do |m|
- recipients << actor(m.chomp)
- end
- end
- note["content"] = input.lines.select { |l| !l.empty? }.join("<br>")
- recipients += Dir[File.join("followers", "*.json")].collect { |f| JSON.parse(File.read(f))["actor"] }
- recipients.delete ACTOR
- recipients.uniq!
- note["to"] += recipients
- create["to"] += recipients
-
- save create
- save note
- FileUtils.ln_s File.join('..', path(create)), "outbox"
-
- responses = send create, recipients
- if responses.collect { |r| r.code.to_i }.uniq.max < 400
- code = 200
- response = "OK"
- else
- code = 502
- response = responses.select { |r| r.code.to_i >= 400 }.collect { |r| r.body }.uniq
- end
- [code, response]
- end
-
- def actor mention
- mention = mention.sub(/^@/, '').chomp
- user, server = mention.split("@")
- get("https://#{server}/.well-known/webfinger?resource=acct:#{mention}",
- "application/jrd+json")["links"].select { |l|
- l["rel"] == "self"
- }[0]["href"]
- end
-
- def mention actor
- "#{get(actor)["preferredUsername"]}@#{URI(actor).host}"
- end
-
- def send object, urls
- # https://github.com/mastodon/mastodon/blob/main/app/lib/request.rb
- keypair = OpenSSL::PKey::RSA.new(File.read('private.pem'))
- responses = []
- urls.each do |url|
- date = Time.now.utc.httpdate
- uri = URI.parse(url)
-
- sha256 = OpenSSL::Digest::SHA256.new
- body = object.to_json
- digest = "SHA-256=" + sha256.base64digest(body)
-
- signed_string = "(request-target): post #{inbox uri}\nhost: #{uri.host}\ndate: #{date}\ndigest: #{digest}\ncontent-type: application/activity+json"
- signature = Base64.strict_encode64(keypair.sign(OpenSSL::Digest.new('SHA256'), signed_string))
- signed_header = 'keyId="' + ACTOR + '#main-key",algorithm="rsa-sha256",headers="(request-target) host date digest content-type",signature="' + signature + '"'
-
- uri = URI.parse(get(url)["inbox"])
- http = Net::HTTP.new(uri.host, uri.port)
- http.use_ssl = true
- header = {
- 'Content-Type' => 'application/activity+json',
- 'Host' => uri.host,
- 'Date' => date,
- 'Digest' => digest,
- 'Signature' => signed_header,
- }
- request = Net::HTTP::Post.new(uri.request_uri, header)
- request.body = body
-
- responses << http.request(request)
- end
- # puts responses
- responses
- end
-
- def ordered_collection dir
- collection = dir.sub(/^\//, "")
- posts = Dir[File.join(collection, "*.json")].collect { |f| JSON.parse(File.read f) }.sort_by { |o| o["published"] }
- {
- "@context" => "https://www.w3.org/ns/activitystreams",
- "summary" => "#{USER} #{collection}",
- "type" => "OrderedCollection",
- "totalItems" => posts.size,
- "orderedItems" => posts,
- }
- end
-
- def inbox uri
- URI(get(uri)["inbox"]).request_uri
- end
-
- def get url, accept = 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"'
- uri = URI(url)
- http = Net::HTTP.new(uri.host, uri.port)
- http.use_ssl = true
- header = { 'Accept' => accept }
- request = Net::HTTP::Get.new(uri.request_uri, header)
- response = http.request(request)
- JSON.parse(response.body)
- end
-
- def path object
- object["id"].sub(SOCIAL_URL, '').sub('/', '')
- end
-
- def save object
- path = path object
- FileUtils.mkdir_p File.dirname(path)
- File.open(path, "w+") { |f| f.puts object.to_json }
- end
-
- def verify env
- # https://github.com/mastodon/mastodon/blob/main/app/controllers/concerns/signature_verification.rb
- # TODO verify digest
- signature_params = {}
- env["HTTP_SIGNATURE"].split(',').each do |pair|
- k, v = pair.split('=')
- signature_params[k] = v.gsub('"', '')
- end
-
- key_id = signature_params['keyId']
- headers = signature_params['headers']
- signature = Base64.decode64(signature_params['signature'])
-
- actor = get key_id
- key = OpenSSL::PKey::RSA.new(actor['publicKey']['publicKeyPem'])
-
- comparison = headers.split(' ').map do |signed_params_name|
- if signed_params_name == '(request-target)'
- '(request-target): post /inbox'
- elsif signed_params_name == 'content-type'
- "#{signed_params_name}: #{env["CONTENT_TYPE"]}"
- else
- "#{signed_params_name}: #{env["HTTP_" + signed_params_name.upcase]}"
- end
- end.join("\n")
-
- key.verify(OpenSSL::Digest.new('SHA256'), signature, comparison)
- end
-
- def auth env
- auth = Rack::Auth::Basic::Request.new(env)
- usr = File.read(".usr").chomp
- pwd = File.read(".pwd").chomp
- auth.provided? && auth.basic? && auth.credentials && auth.credentials == [usr, pwd]
- true
- end
-end
diff --git a/config.ru b/config.ru
deleted file mode 100644
index fc37641..0000000
--- a/config.ru
+++ /dev/null
@@ -1,6 +0,0 @@
-require_relative './application.rb'
-require 'rack/protection'
-use Rack::Protection, :except => :session_hijacking
-use Rack::Reloader
-use Rack::Static, :urls => ["/create", "/outbox", "/following", "/followers", "/likes", "/shares"], :cascade => true
-run Application.new