0.9.3.4: Fix what I did yesterday
All checks were successful
File-uploader-crystal CI / build (push) Successful in 1m49s
All checks were successful
File-uploader-crystal CI / build (push) Successful in 1m49s
This commit is contained in:
parent
cb75b97520
commit
bb9ecee67b
4 changed files with 64 additions and 81 deletions
|
@ -37,7 +37,7 @@ module Handling::Admin
|
||||||
failed_files << file
|
failed_files << file
|
||||||
rescue ex
|
rescue ex
|
||||||
LOGGER.error "Unknown error: #{ex.message}"
|
LOGGER.error "Unknown error: #{ex.message}"
|
||||||
error500 "Unknown error: #{ex.message}"
|
http_error 500,"Unknown error: #{ex.message}"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
json = JSON.build do |j|
|
json = JSON.build do |j|
|
||||||
|
@ -69,7 +69,7 @@ module Handling::Admin
|
||||||
failed << item
|
failed << item
|
||||||
rescue ex
|
rescue ex
|
||||||
LOGGER.error "Unknown error: #{ex.message}"
|
LOGGER.error "Unknown error: #{ex.message}"
|
||||||
error500 "Unknown error: #{ex.message}"
|
http_error 500, "Unknown error: #{ex.message}"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
json = JSON.build do |j|
|
json = JSON.build do |j|
|
||||||
|
@ -107,7 +107,7 @@ module Handling::Admin
|
||||||
failed << item
|
failed << item
|
||||||
rescue ex
|
rescue ex
|
||||||
LOGGER.error "Unknown error: #{ex.message}"
|
LOGGER.error "Unknown error: #{ex.message}"
|
||||||
error500 "Unknown error: #{ex.message}"
|
http_error 500,"Unknown error: #{ex.message}"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
json = JSON.build do |j|
|
json = JSON.build do |j|
|
||||||
|
|
|
@ -18,7 +18,7 @@ module Handling
|
||||||
# which is inspecting the file directly (If I'm not wrong).
|
# which is inspecting the file directly (If I'm not wrong).
|
||||||
if CONFIG.size_limit > 0
|
if CONFIG.size_limit > 0
|
||||||
if env.request.headers["Content-Length"].to_i > 1048576*CONFIG.size_limit
|
if env.request.headers["Content-Length"].to_i > 1048576*CONFIG.size_limit
|
||||||
return error413("File is too big. The maximum size allowed is #{CONFIG.size_limit}MiB")
|
return http_error 413, "File is too big. The maximum size allowed is #{CONFIG.size_limit}MiB"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
filename = ""
|
filename = ""
|
||||||
|
@ -33,13 +33,13 @@ module Handling
|
||||||
HTTP::FormData.parse(env.request) do |upload|
|
HTTP::FormData.parse(env.request) do |upload|
|
||||||
if upload.filename.nil? || upload.filename.to_s.empty?
|
if upload.filename.nil? || upload.filename.to_s.empty?
|
||||||
LOGGER.debug "No file provided by the user"
|
LOGGER.debug "No file provided by the user"
|
||||||
return error403("No file provided")
|
return http_error 403, "No file provided"
|
||||||
end
|
end
|
||||||
# TODO: upload.body is emptied when is copied or read
|
# TODO: upload.body is emptied when is copied or read
|
||||||
# Utils.check_duplicate(upload.dup)
|
# Utils.check_duplicate(upload.dup)
|
||||||
extension = File.extname("#{upload.filename}")
|
extension = File.extname("#{upload.filename}")
|
||||||
if CONFIG.blockedExtensions.includes?(extension.split(".")[1])
|
if CONFIG.blockedExtensions.includes?(extension.split(".")[1])
|
||||||
return error401("Extension '#{extension}' is not allowed")
|
return http_error 401, "Extension '#{extension}' is not allowed"
|
||||||
end
|
end
|
||||||
filename = Utils.generate_filename
|
filename = Utils.generate_filename
|
||||||
file_path = "#{CONFIG.files}/#{filename}#{extension}"
|
file_path = "#{CONFIG.files}/#{filename}#{extension}"
|
||||||
|
@ -70,7 +70,7 @@ module Handling
|
||||||
SQL.exec "UPDATE ips SET count = count + 1 WHERE ip = ('#{ip_address}')"
|
SQL.exec "UPDATE ips SET count = count + 1 WHERE ip = ('#{ip_address}')"
|
||||||
rescue ex
|
rescue ex
|
||||||
LOGGER.error "An error ocurred when trying to insert the data into the DB: #{ex.message}"
|
LOGGER.error "An error ocurred when trying to insert the data into the DB: #{ex.message}"
|
||||||
return error500("An error ocurred when trying to insert the data into the DB")
|
return http_error 500, "An error ocurred when trying to insert the data into the DB"
|
||||||
end
|
end
|
||||||
json = JSON.build do |j|
|
json = JSON.build do |j|
|
||||||
j.object do
|
j.object do
|
||||||
|
@ -99,10 +99,10 @@ module Handling
|
||||||
files = env.params.json["files"].as((Array(JSON::Any)))
|
files = env.params.json["files"].as((Array(JSON::Any)))
|
||||||
rescue ex : JSON::ParseException
|
rescue ex : JSON::ParseException
|
||||||
LOGGER.error "Body malformed: #{ex.message}"
|
LOGGER.error "Body malformed: #{ex.message}"
|
||||||
return error400 "Body malformed: #{ex.message}"
|
return http_error 400, "Body malformed: #{ex.message}"
|
||||||
rescue ex
|
rescue ex
|
||||||
LOGGER.error "Unknown error: #{ex.message}"
|
LOGGER.error "Unknown error: #{ex.message}"
|
||||||
return error500 "Unknown error"
|
return http_error 500, "Unknown error"
|
||||||
end
|
end
|
||||||
successfull_files = [] of NamedTuple(filename: String, extension: String, original_filename: String, checksum: String, delete_key: String | Nil)
|
successfull_files = [] of NamedTuple(filename: String, extension: String, original_filename: String, checksum: String, delete_key: String | Nil)
|
||||||
failed_files = [] of String
|
failed_files = [] of String
|
||||||
|
@ -127,7 +127,7 @@ module Handling
|
||||||
end
|
end
|
||||||
rescue ex
|
rescue ex
|
||||||
LOGGER.debug "Failed to download file '#{url}': #{ex.message}"
|
LOGGER.debug "Failed to download file '#{url}': #{ex.message}"
|
||||||
return error403("Failed to download file '#{url}'")
|
return http_error 403, "Failed to download file '#{url}'"
|
||||||
failed_files << url
|
failed_files << url
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -158,7 +158,7 @@ module Handling
|
||||||
checksum: checksum}
|
checksum: checksum}
|
||||||
rescue ex
|
rescue ex
|
||||||
LOGGER.error "An error ocurred when trying to insert the data into the DB: #{ex.message}"
|
LOGGER.error "An error ocurred when trying to insert the data into the DB: #{ex.message}"
|
||||||
return error500("An error ocurred when trying to insert the data into the DB")
|
return http_error 500, "An error ocurred when trying to insert the data into the DB"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
json = JSON.build do |j|
|
json = JSON.build do |j|
|
||||||
|
@ -212,7 +212,7 @@ module Handling
|
||||||
end
|
end
|
||||||
rescue ex
|
rescue ex
|
||||||
LOGGER.debug "Failed to download file '#{url}': #{ex.message}"
|
LOGGER.debug "Failed to download file '#{url}': #{ex.message}"
|
||||||
return error403("Failed to download file '#{url}': #{ex.message}")
|
return http_error 403, "Failed to download file '#{url}': #{ex.message}"
|
||||||
failed_files << url
|
failed_files << url
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -241,7 +241,7 @@ module Handling
|
||||||
checksum: checksum}
|
checksum: checksum}
|
||||||
rescue ex
|
rescue ex
|
||||||
LOGGER.error "An error ocurred when trying to insert the data into the DB: #{ex.message}"
|
LOGGER.error "An error ocurred when trying to insert the data into the DB: #{ex.message}"
|
||||||
return error500("An error ocurred when trying to insert the data into the DB")
|
return http_error 500, "An error ocurred when trying to insert the data into the DB"
|
||||||
end
|
end
|
||||||
json = JSON.build do |j|
|
json = JSON.build do |j|
|
||||||
j.array do
|
j.array do
|
||||||
|
@ -266,25 +266,30 @@ module Handling
|
||||||
end
|
end
|
||||||
|
|
||||||
def retrieve_file(env)
|
def retrieve_file(env)
|
||||||
|
protocol = Utils.protocol(env)
|
||||||
|
host = Utils.host(env)
|
||||||
begin
|
begin
|
||||||
protocol = Utils.protocol(env)
|
|
||||||
host = Utils.host(env)
|
|
||||||
fileinfo = SQL.query_one?("SELECT filename, original_filename, uploaded_at, extension, checksum, thumbnail
|
fileinfo = SQL.query_one?("SELECT filename, original_filename, uploaded_at, extension, checksum, thumbnail
|
||||||
FROM files
|
FROM files
|
||||||
WHERE filename = ?",
|
WHERE filename = ?",
|
||||||
env.params.url["filename"].split(".").first,
|
env.params.url["filename"].split(".").first,
|
||||||
as: {filename: String, ofilename: String, up_at: String, ext: String, checksum: String, thumbnail: String | Nil})
|
as: {filename: String, ofilename: String, up_at: String, ext: String, checksum: String, thumbnail: String | Nil})
|
||||||
if fileinfo.nil?
|
if fileinfo.nil?
|
||||||
return error404("File '#{env.params.url["filename"]}' does not exist")
|
# TODO: Switch this to 404, if I use 404, it will use the kemal error page (ANOYING!)
|
||||||
|
return http_error 418, "File '#{env.params.url["filename"]}' does not exist"
|
||||||
end
|
end
|
||||||
env.response.headers["Content-Disposition"] = "inline; filename*=UTF-8''#{fileinfo[:ofilename]}"
|
rescue ex
|
||||||
# env.response.headers["Last-Modified"] = "#{fileinfo[:up_at]}"
|
LOGGER.debug "Error when retrieving file '#{env.params.url["filename"]}': #{ex.message}"
|
||||||
env.response.headers["ETag"] = "#{fileinfo[:checksum]}"
|
return http_error 500, "Error when retrieving file '#{env.params.url["filename"]}'"
|
||||||
|
end
|
||||||
|
env.response.headers["Content-Disposition"] = "inline; filename*=UTF-8''#{fileinfo[:ofilename]}"
|
||||||
|
# env.response.headers["Last-Modified"] = "#{fileinfo[:up_at]}"
|
||||||
|
env.response.headers["ETag"] = "#{fileinfo[:checksum]}"
|
||||||
|
|
||||||
CONFIG.opengraphUseragents.each do |useragent|
|
CONFIG.opengraphUseragents.each do |useragent|
|
||||||
if env.request.headers.try &.["User-Agent"].includes?(useragent)
|
if env.request.headers.try &.["User-Agent"].includes?(useragent)
|
||||||
env.response.content_type = "text/html"
|
env.response.content_type = "text/html"
|
||||||
return %(
|
return %(
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
|
@ -297,13 +302,9 @@ module Handling
|
||||||
</head>
|
</head>
|
||||||
</html>
|
</html>
|
||||||
)
|
)
|
||||||
end
|
|
||||||
end
|
end
|
||||||
send_file env, "#{CONFIG.files}/#{fileinfo[:filename]}#{fileinfo[:ext]}"
|
|
||||||
rescue ex
|
|
||||||
LOGGER.debug "Error when retrieving file '#{env.params.url["filename"]}': #{ex.message}"
|
|
||||||
return error500("Error when retrieving file '#{env.params.url["filename"]}'")
|
|
||||||
end
|
end
|
||||||
|
send_file env, "#{CONFIG.files}/#{fileinfo[:filename]}#{fileinfo[:ext]}"
|
||||||
end
|
end
|
||||||
|
|
||||||
def retrieve_thumbnail(env)
|
def retrieve_thumbnail(env)
|
||||||
|
@ -311,7 +312,7 @@ module Handling
|
||||||
send_file env, "#{CONFIG.thumbnails}/#{env.params.url["thumbnail"]}"
|
send_file env, "#{CONFIG.thumbnails}/#{env.params.url["thumbnail"]}"
|
||||||
rescue ex
|
rescue ex
|
||||||
LOGGER.debug "Thumbnail '#{env.params.url["thumbnail"]}' does not exist: #{ex.message}"
|
LOGGER.debug "Thumbnail '#{env.params.url["thumbnail"]}' does not exist: #{ex.message}"
|
||||||
return error403("Thumbnail '#{env.params.url["thumbnail"]}' does not exist")
|
return http_error 403, "Thumbnail '#{env.params.url["thumbnail"]}' does not exist"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -333,7 +334,7 @@ module Handling
|
||||||
end
|
end
|
||||||
rescue ex
|
rescue ex
|
||||||
LOGGER.error "Unknown error: #{ex.message}"
|
LOGGER.error "Unknown error: #{ex.message}"
|
||||||
return error500("Unknown error")
|
return http_error 500, "Unknown error"
|
||||||
end
|
end
|
||||||
json_data
|
json_data
|
||||||
end
|
end
|
||||||
|
@ -359,11 +360,11 @@ module Handling
|
||||||
return msg("File '#{fileinfo[:filename]}' deleted successfully")
|
return msg("File '#{fileinfo[:filename]}' deleted successfully")
|
||||||
rescue ex
|
rescue ex
|
||||||
LOGGER.error("Unknown error: #{ex.message}")
|
LOGGER.error("Unknown error: #{ex.message}")
|
||||||
return error500("Unknown error")
|
return http_error 500, "Unknown error"
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
LOGGER.debug "Key '#{env.params.query["key"]}' does not exist"
|
LOGGER.debug "Key '#{env.params.query["key"]}' does not exist"
|
||||||
return error401("Delete key '#{env.params.query["key"]}' does not exist. No files were deleted")
|
return http_error 401, "Delete key '#{env.params.query["key"]}' does not exist. No files were deleted"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -1,34 +1,10 @@
|
||||||
macro http_error(status_code, message)
|
macro http_error(status_code, message)
|
||||||
env.response.content_type = "application/json"
|
env.response.content_type = "application/json"
|
||||||
env.response.status_code = {{status_code}}
|
env.response.status_code = {{status_code}}
|
||||||
error_message = {"error" => {{message}}}.to_json
|
error_message = {"error" => {{message}}}.to_json
|
||||||
error_message
|
error_message
|
||||||
end
|
end
|
||||||
|
|
||||||
macro error400(message)
|
|
||||||
http_error(400, {{message}})
|
|
||||||
end
|
|
||||||
|
|
||||||
macro error401(message)
|
|
||||||
http_error(401, {{message}})
|
|
||||||
end
|
|
||||||
|
|
||||||
macro error403(message)
|
|
||||||
http_error(403, {{message}})
|
|
||||||
end
|
|
||||||
|
|
||||||
macro error404(message)
|
|
||||||
http_error(404, {{message}})
|
|
||||||
end
|
|
||||||
|
|
||||||
macro error413(message)
|
|
||||||
http_error(413, {{message}})
|
|
||||||
end
|
|
||||||
|
|
||||||
macro error500(message)
|
|
||||||
http_error(500, {{message}})
|
|
||||||
end
|
|
||||||
|
|
||||||
macro msg(message)
|
macro msg(message)
|
||||||
env.response.content_type = "application/json"
|
env.response.content_type = "application/json"
|
||||||
msg = {"message" => {{message}}}.to_json
|
msg = {"message" => {{message}}}.to_json
|
||||||
|
|
|
@ -12,7 +12,31 @@ module Routing
|
||||||
|
|
||||||
before_post "/api/admin/*" do |env|
|
before_post "/api/admin/*" do |env|
|
||||||
if env.request.headers.try &.["X-Api-Key"]? != CONFIG.adminApiKey || nil
|
if env.request.headers.try &.["X-Api-Key"]? != CONFIG.adminApiKey || nil
|
||||||
halt env, status_code: 401, response: error401("Wrong API Key")
|
halt env, status_code: 401, response: http_error 401, "Wrong API Key"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
before_post "/upload" do |env|
|
||||||
|
begin
|
||||||
|
ip_info = SQL.query_one?("SELECT ip, count, date FROM ips WHERE ip = ?", Utils.ip_address(env), as: {ip: String, count: Int32, date: Int32})
|
||||||
|
rescue ex
|
||||||
|
LOGGER.error "Error when trying to enforce rate limits: #{ex.message}"
|
||||||
|
next
|
||||||
|
end
|
||||||
|
|
||||||
|
if ip_info.nil?
|
||||||
|
next
|
||||||
|
end
|
||||||
|
|
||||||
|
time_since_first_upload = Time.utc.to_unix - ip_info[:date]
|
||||||
|
time_until_unban = ip_info[:date] - Time.utc.to_unix + CONFIG.rateLimitPeriod
|
||||||
|
if time_since_first_upload > CONFIG.rateLimitPeriod
|
||||||
|
SQL.exec "DELETE FROM ips WHERE ip = ?", ip_info[:ip]
|
||||||
|
end
|
||||||
|
if CONFIG.filesPerIP > 0
|
||||||
|
if ip_info[:count] >= CONFIG.filesPerIP && time_since_first_upload < CONFIG.rateLimitPeriod
|
||||||
|
halt env, status_code: 401, response: http_error 401, "Rate limited! Try again in #{time_until_unban} seconds"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -22,7 +46,7 @@ module Routing
|
||||||
next
|
next
|
||||||
end
|
end
|
||||||
if CONFIG.blockTorAddresses && @@exit_nodes.includes?(Utils.ip_address(env))
|
if CONFIG.blockTorAddresses && @@exit_nodes.includes?(Utils.ip_address(env))
|
||||||
halt env, status_code: 401, response: error401(CONFIG.torMessage)
|
halt env, status_code: 401, response: http_error 401, CONFIG.torMessage
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -40,28 +64,6 @@ module Routing
|
||||||
end
|
end
|
||||||
|
|
||||||
post "/upload" do |env|
|
post "/upload" do |env|
|
||||||
begin
|
|
||||||
ip_info = SQL.query_one?("SELECT ip, count, date FROM ips WHERE ip = ?", Utils.ip_address(env), as: {ip: String, count: Int32, date: Int32})
|
|
||||||
rescue ex
|
|
||||||
LOGGER.error "Error when trying to enforce rate limits: #{ex.message}"
|
|
||||||
next
|
|
||||||
end
|
|
||||||
|
|
||||||
if ip_info.nil?
|
|
||||||
next
|
|
||||||
end
|
|
||||||
|
|
||||||
time_since_first_upload = Time.utc.to_unix - ip_info[:date]
|
|
||||||
time_until_unban = ip_info[:date] - Time.utc.to_unix + CONFIG.rateLimitPeriod
|
|
||||||
if time_since_first_upload > CONFIG.rateLimitPeriod
|
|
||||||
SQL.exec "DELETE FROM ips WHERE ip = ?", ip_info[:ip]
|
|
||||||
end
|
|
||||||
if CONFIG.filesPerIP > 0
|
|
||||||
if ip_info[:count] >= CONFIG.filesPerIP && time_since_first_upload < CONFIG.rateLimitPeriod
|
|
||||||
halt env, status_code: 401, response: error401("Rate limited! Try again in #{time_until_unban} seconds")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
Handling.upload(env)
|
Handling.upload(env)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -122,4 +124,8 @@ module Routing
|
||||||
get "/api/admin/torexitnodes" do |env|
|
get "/api/admin/torexitnodes" do |env|
|
||||||
Handling::Admin.retrieve_tor_exit_nodes(env, @@exit_nodes)
|
Handling::Admin.retrieve_tor_exit_nodes(env, @@exit_nodes)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
error 404 do
|
||||||
|
"File not found"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue