diff --git a/src/handlers/auth_handler.cr b/src/handlers/auth_handler.cr index 3f094eb..42d9cf6 100644 --- a/src/handlers/auth_handler.cr +++ b/src/handlers/auth_handler.cr @@ -11,9 +11,6 @@ class AuthHandler < Kemal::Handler "You have to login with proper credentials" HEADER_LOGIN_REQUIRED = "Basic realm=\"Login Required\"" - def initialize(@storage : Storage) - end - def require_basic_auth(env) env.response.status_code = 401 env.response.headers["WWW-Authenticate"] = HEADER_LOGIN_REQUIRED @@ -23,12 +20,12 @@ class AuthHandler < Kemal::Handler def validate_token(env) token = env.session.string? "token" - !token.nil? && @storage.verify_token token + !token.nil? && Storage.default.verify_token token end def validate_token_admin(env) token = env.session.string? "token" - !token.nil? && @storage.verify_admin token + !token.nil? && Storage.default.verify_admin token end def validate_auth_header(env) @@ -49,7 +46,7 @@ class AuthHandler < Kemal::Handler def verify_user(value) username, password = Base64.decode_string(value[BASIC.size + 1..-1]) .split(":") - @storage.verify_user username, password + Storage.default.verify_user username, password end def handle_opds_auth(env) diff --git a/src/mango.cr b/src/mango.cr index 1fbe6a6..bcce252 100644 --- a/src/mango.cr +++ b/src/mango.cr @@ -53,6 +53,11 @@ class CLI < Clim ARGV.clear Config.load(opts.config).set_current + + # Initialize main components + Storage.default + Queue.default + Library.default MangaDex::Downloader.default Plugin::Downloader.default diff --git a/src/routes/admin.cr b/src/routes/admin.cr index c2f8fa9..4445b0e 100644 --- a/src/routes/admin.cr +++ b/src/routes/admin.cr @@ -1,13 +1,11 @@ -require "./router" - -class AdminRouter < Router +struct AdminRouter def initialize get "/admin" do |env| layout "admin" end get "/admin/user" do |env| - users = @context.storage.list_users + users = Storage.default.list_users username = get_username env layout "user" end @@ -32,11 +30,11 @@ class AdminRouter < Router # would not contain `admin` admin = !env.params.body["admin"]?.nil? - @context.storage.new_user username, password, admin + Storage.default.new_user username, password, admin redirect env, "/admin/user" rescue e - @context.error e + Logger.error e redirect_url = URI.new \ path: "/admin/user/edit", query: hash_to_query({"error" => e.message}) @@ -51,12 +49,12 @@ class AdminRouter < Router admin = !env.params.body["admin"]?.nil? original_username = env.params.url["original_username"] - @context.storage.update_user \ + Storage.default.update_user \ original_username, username, password, admin redirect env, "/admin/user" rescue e - @context.error e + Logger.error e redirect_url = URI.new \ path: "/admin/user/edit", query: hash_to_query({"username" => original_username, \ diff --git a/src/routes/api.cr b/src/routes/api.cr index 4ec7407..f48451e 100644 --- a/src/routes/api.cr +++ b/src/routes/api.cr @@ -1,9 +1,8 @@ -require "./router" require "../mangadex/*" require "../upload" require "koa" -class APIRouter < Router +struct APIRouter @@api_json : String? API_VERSION = "0.1.0" @@ -178,7 +177,7 @@ class APIRouter < Router eid = env.params.url["eid"] page = env.params.url["page"].to_i - title = @context.library.get_title tid + title = Library.default.get_title tid raise "Title ID `#{tid}` not found" if title.nil? entry = title.get_entry eid raise "Entry ID `#{eid}` of `#{title.title}` not found" if entry.nil? @@ -188,7 +187,7 @@ class APIRouter < Router send_img env, img rescue e - @context.error e + Logger.error e env.response.status_code = 500 e.message end @@ -204,7 +203,7 @@ class APIRouter < Router tid = env.params.url["tid"] eid = env.params.url["eid"] - title = @context.library.get_title tid + title = Library.default.get_title tid raise "Title ID `#{tid}` not found" if title.nil? entry = title.get_entry eid raise "Entry ID `#{eid}` of `#{title.title}` not found" if entry.nil? @@ -215,7 +214,7 @@ class APIRouter < Router send_img env, img rescue e - @context.error e + Logger.error e env.response.status_code = 500 e.message end @@ -228,12 +227,12 @@ class APIRouter < Router get "/api/book/:tid" do |env| begin tid = env.params.url["tid"] - title = @context.library.get_title tid + title = Library.default.get_title tid raise "Title ID `#{tid}` not found" if title.nil? send_json env, title.to_json rescue e - @context.error e + Logger.error e env.response.status_code = 404 e.message end @@ -242,7 +241,7 @@ class APIRouter < Router Koa.describe "Returns the entire library with all titles and entries" Koa.response 200, ref: "$library" get "/api/library" do |env| - send_json env, @context.library.to_json + send_json env, Library.default.to_json end Koa.describe "Triggers a library scan" @@ -250,11 +249,11 @@ class APIRouter < Router Koa.response 200, ref: "$scanResult" post "/api/admin/scan" do |env| start = Time.utc - @context.library.scan + Library.default.scan ms = (Time.utc - start).total_milliseconds send_json env, { "milliseconds" => ms, - "titles" => @context.library.titles.size, + "titles" => Library.default.titles.size, }.to_json end @@ -281,9 +280,9 @@ class APIRouter < Router delete "/api/admin/user/delete/:username" do |env| begin username = env.params.url["username"] - @context.storage.delete_user username + Storage.default.delete_user username rescue e - @context.error e + Logger.error e send_json env, { "success" => false, "error" => e.message, @@ -308,7 +307,7 @@ class APIRouter < Router put "/api/progress/:tid/:page" do |env| begin username = get_username env - title = (@context.library.get_title env.params.url["tid"]).not_nil! + title = (Library.default.get_title env.params.url["tid"]).not_nil! page = env.params.url["page"].to_i entry_id = env.params.query["eid"]? @@ -322,7 +321,7 @@ class APIRouter < Router title.read_all username end rescue e - @context.error e + Logger.error e send_json env, { "success" => false, "error" => e.message, @@ -340,7 +339,7 @@ class APIRouter < Router put "/api/bulk_progress/:action/:tid" do |env| begin username = get_username env - title = (@context.library.get_title env.params.url["tid"]).not_nil! + title = (Library.default.get_title env.params.url["tid"]).not_nil! action = env.params.url["action"] ids = env.params.json["ids"].as(Array).map &.as_s @@ -349,7 +348,7 @@ class APIRouter < Router end title.bulk_progress action, ids, username rescue e - @context.error e + Logger.error e send_json env, { "success" => false, "error" => e.message, @@ -369,7 +368,7 @@ class APIRouter < Router Koa.response 200, ref: "$result" put "/api/admin/display_name/:tid/:name" do |env| begin - title = (@context.library.get_title env.params.url["tid"]) + title = (Library.default.get_title env.params.url["tid"]) .not_nil! name = env.params.url["name"] entry = env.params.query["eid"]? @@ -380,7 +379,7 @@ class APIRouter < Router title.set_display_name eobj.not_nil!.title, name end rescue e - @context.error e + Logger.error e send_json env, { "success" => false, "error" => e.message, @@ -403,7 +402,7 @@ class APIRouter < Router manga = api.get_manga id send_json env, manga.to_info_json rescue e - @context.error e + Logger.error e send_json env, {"error" => e.message}.to_json end end @@ -427,13 +426,13 @@ class APIRouter < Router Time.unix chapter["time"].as_s.to_i ) } - inserted_count = @context.queue.push jobs + inserted_count = Queue.default.push jobs send_json env, { "success": inserted_count, "fail": jobs.size - inserted_count, }.to_json rescue e - @context.error e + Logger.error e send_json env, {"error" => e.message}.to_json end end @@ -443,8 +442,8 @@ class APIRouter < Router interval = (interval_raw.to_i? if interval_raw) || 5 loop do socket.send({ - "jobs" => @context.queue.get_all, - "paused" => @context.queue.paused?, + "jobs" => Queue.default.get_all, + "paused" => Queue.default.paused?, }.to_json) sleep interval.seconds end @@ -457,10 +456,10 @@ class APIRouter < Router Koa.response 200, ref: "$jobs" get "/api/admin/mangadex/queue" do |env| begin - jobs = @context.queue.get_all + jobs = Queue.default.get_all send_json env, { "jobs" => jobs, - "paused" => @context.queue.paused?, + "paused" => Queue.default.paused?, "success" => true, }.to_json rescue e @@ -491,20 +490,20 @@ class APIRouter < Router case action when "delete" if id.nil? - @context.queue.delete_status Queue::JobStatus::Completed + Queue.default.delete_status Queue::JobStatus::Completed else - @context.queue.delete id + Queue.default.delete id end when "retry" if id.nil? - @context.queue.reset + Queue.default.reset else - @context.queue.reset id + Queue.default.reset id end when "pause" - @context.queue.pause + Queue.default.pause when "resume" - @context.queue.resume + Queue.default.resume else raise "Unknown queue action #{action}" end @@ -550,7 +549,7 @@ class APIRouter < Router when "cover" title_id = env.params.query["tid"] entry_id = env.params.query["eid"]? - title = @context.library.get_title(title_id).not_nil! + title = Library.default.get_title(title_id).not_nil! unless SUPPORTED_IMG_TYPES.includes? \ MIME.from_filename? filename @@ -634,7 +633,7 @@ class APIRouter < Router Time.utc ) } - inserted_count = @context.queue.push jobs + inserted_count = Queue.default.push jobs send_json env, { "success": inserted_count, "fail": jobs.size - inserted_count, @@ -656,7 +655,7 @@ class APIRouter < Router tid = env.params.url["tid"] eid = env.params.url["eid"] - title = @context.library.get_title tid + title = Library.default.get_title tid raise "Title ID `#{tid}` not found" if title.nil? entry = title.get_entry eid raise "Entry ID `#{eid}` of `#{title.title}` not found" if entry.nil? @@ -681,12 +680,12 @@ class APIRouter < Router Koa.response 404, "Entry not found" get "/api/download/:tid/:eid" do |env| begin - title = (@context.library.get_title env.params.url["tid"]).not_nil! + title = (Library.default.get_title env.params.url["tid"]).not_nil! entry = (title.get_entry env.params.url["eid"]).not_nil! send_attachment env, entry.zip_path rescue e - @context.error e + Logger.error e env.response.status_code = 404 end end @@ -696,7 +695,7 @@ class APIRouter < Router Koa.response 200, ref: "$tagsResult" get "/api/tags/:tid" do |env| begin - title = (@context.library.get_title env.params.url["tid"]).not_nil! + title = (Library.default.get_title env.params.url["tid"]).not_nil! tags = title.tags send_json env, { @@ -704,7 +703,7 @@ class APIRouter < Router "tags" => tags, }.to_json rescue e - @context.error e + Logger.error e send_json env, { "success" => false, "error" => e.message, @@ -718,7 +717,7 @@ class APIRouter < Router Koa.tag "admin" put "/api/admin/tags/:tid/:tag" do |env| begin - title = (@context.library.get_title env.params.url["tid"]).not_nil! + title = (Library.default.get_title env.params.url["tid"]).not_nil! tag = env.params.url["tag"] title.add_tag tag @@ -727,7 +726,7 @@ class APIRouter < Router "error" => nil, }.to_json rescue e - @context.error e + Logger.error e send_json env, { "success" => false, "error" => e.message, @@ -741,7 +740,7 @@ class APIRouter < Router Koa.tag "admin" delete "/api/admin/tags/:tid/:tag" do |env| begin - title = (@context.library.get_title env.params.url["tid"]).not_nil! + title = (Library.default.get_title env.params.url["tid"]).not_nil! tag = env.params.url["tag"] title.delete_tag tag @@ -750,7 +749,7 @@ class APIRouter < Router "error" => nil, }.to_json rescue e - @context.error e + Logger.error e send_json env, { "success" => false, "error" => e.message, diff --git a/src/routes/main.cr b/src/routes/main.cr index 67bbd31..9218933 100644 --- a/src/routes/main.cr +++ b/src/routes/main.cr @@ -1,6 +1,4 @@ -require "./router" - -class MainRouter < Router +struct MainRouter def initialize get "/login" do |env| base_url = Config.current.base_url @@ -11,7 +9,7 @@ class MainRouter < Router begin env.session.delete_string "token" rescue e - @context.error "Error when attempting to log out: #{e}" + Logger.error "Error when attempting to log out: #{e}" ensure redirect env, "/login" end @@ -21,7 +19,7 @@ class MainRouter < Router begin username = env.params.body["username"] password = env.params.body["password"] - token = @context.storage.verify_user(username, password).not_nil! + token = Storage.default.verify_user(username, password).not_nil! env.session.string "token", token @@ -41,22 +39,22 @@ class MainRouter < Router begin username = get_username env - sort_opt = SortOptions.from_info_json @context.library.dir, username + sort_opt = SortOptions.from_info_json Library.default.dir, username get_sort_opt - titles = @context.library.sorted_titles username, sort_opt + titles = Library.default.sorted_titles username, sort_opt percentage = titles.map &.load_percentage username layout "library" rescue e - @context.error e + Logger.error e env.response.status_code = 500 end end get "/book/:title" do |env| begin - title = (@context.library.get_title env.params.url["title"]).not_nil! + title = (Library.default.get_title env.params.url["title"]).not_nil! username = get_username env sort_opt = SortOptions.from_info_json title.dir, username @@ -68,7 +66,7 @@ class MainRouter < Router title_percentage = title.titles.map &.load_percentage username layout "title" rescue e - @context.error e + Logger.error e env.response.status_code = 500 end end @@ -92,7 +90,7 @@ class MainRouter < Router layout "plugin-download" rescue e - @context.error e + Logger.error e env.response.status_code = 500 end end @@ -100,16 +98,16 @@ class MainRouter < Router get "/" do |env| begin username = get_username env - continue_reading = @context - .library.get_continue_reading_entries username - recently_added = @context.library.get_recently_added_entries username - start_reading = @context.library.get_start_reading_titles username - titles = @context.library.titles + continue_reading = Library.default + .get_continue_reading_entries username + recently_added = Library.default.get_recently_added_entries username + start_reading = Library.default.get_start_reading_titles username + titles = Library.default.titles new_user = !titles.any? { |t| t.load_percentage(username) > 0 } empty_library = titles.size == 0 layout "home" rescue e - @context.error e + Logger.error e env.response.status_code = 500 end end @@ -126,7 +124,7 @@ class MainRouter < Router raise "Tag #{tag} not found" if title_ids.empty? - titles = title_ids.map { |id| @context.library.get_title id } + titles = title_ids.map { |id| Library.default.get_title id } .select Title titles = sort_titles titles, sort_opt, username @@ -134,7 +132,7 @@ class MainRouter < Router layout "tag" rescue e - @context.error e + Logger.error e env.response.status_code = 404 end end diff --git a/src/routes/opds.cr b/src/routes/opds.cr index eafbcb9..e810b25 100644 --- a/src/routes/opds.cr +++ b/src/routes/opds.cr @@ -1,18 +1,16 @@ -require "./router" - -class OPDSRouter < Router +struct OPDSRouter def initialize get "/opds" do |env| - titles = @context.library.titles + titles = Library.default.titles render_xml "src/views/opds/index.xml.ecr" end get "/opds/book/:title_id" do |env| begin - title = @context.library.get_title(env.params.url["title_id"]).not_nil! + title = Library.default.get_title(env.params.url["title_id"]).not_nil! render_xml "src/views/opds/title.xml.ecr" rescue e - @context.error e + Logger.error e env.response.status_code = 404 end end diff --git a/src/routes/reader.cr b/src/routes/reader.cr index fb81d3e..9685f5b 100644 --- a/src/routes/reader.cr +++ b/src/routes/reader.cr @@ -1,12 +1,10 @@ -require "./router" - -class ReaderRouter < Router +struct ReaderRouter def initialize get "/reader/:title/:entry" do |env| begin username = get_username env - title = (@context.library.get_title env.params.url["title"]).not_nil! + title = (Library.default.get_title env.params.url["title"]).not_nil! entry = (title.get_entry env.params.url["entry"]).not_nil! next layout "reader-error" if entry.err_msg @@ -19,7 +17,7 @@ class ReaderRouter < Router redirect env, "/reader/#{title.id}/#{entry.id}/#{page}" rescue e - @context.error e + Logger.error e env.response.status_code = 404 end end @@ -30,7 +28,7 @@ class ReaderRouter < Router username = get_username env - title = (@context.library.get_title env.params.url["title"]).not_nil! + title = (Library.default.get_title env.params.url["title"]).not_nil! entry = (title.get_entry env.params.url["entry"]).not_nil! page = env.params.url["page"].to_i raise "" if page > entry.pages || page <= 0 @@ -45,7 +43,7 @@ class ReaderRouter < Router render "src/views/reader.html.ecr" rescue e - @context.error e + Logger.error e env.response.status_code = 404 end end diff --git a/src/routes/router.cr b/src/routes/router.cr deleted file mode 100644 index a6d7ace..0000000 --- a/src/routes/router.cr +++ /dev/null @@ -1,3 +0,0 @@ -class Router - @context : Context = Context.default -end diff --git a/src/server.cr b/src/server.cr index 380f4b3..71973d4 100644 --- a/src/server.cr +++ b/src/server.cr @@ -5,29 +5,7 @@ require "./handlers/*" require "./util/*" require "./routes/*" -class Context - property library : Library - property storage : Storage - property queue : Queue - - use_default - - def initialize - @storage = Storage.default - @library = Library.default - @queue = Queue.default - end - - {% for lvl in Logger::LEVELS %} - def {{lvl.id}}(msg) - Logger.{{lvl.id}} msg - end - {% end %} -end - class Server - @context : Context = Context.default - def initialize error 403 do |env| message = "HTTP 403: You are not authorized to visit #{env.request.path}" @@ -53,11 +31,11 @@ class Server Kemal.config.logging = false add_handler LogHandler.new - add_handler AuthHandler.new @context.storage + add_handler AuthHandler.new add_handler UploadHandler.new Config.current.upload_path {% if flag?(:release) %} # when building for relase, embed the static files in binary - @context.debug "We are in release mode. Using embedded static files." + Logger.debug "We are in release mode. Using embedded static files." serve_static false add_handler StaticHandler.new {% end %} @@ -71,7 +49,7 @@ class Server end def start - @context.debug "Starting Kemal server" + Logger.debug "Starting Kemal server" {% if flag?(:release) %} Kemal.config.env = "production" {% end %} diff --git a/src/util/web.cr b/src/util/web.cr index 03af6a2..a6db2e1 100644 --- a/src/util/web.cr +++ b/src/util/web.cr @@ -8,17 +8,17 @@ macro layout(name) # this is why we check the default username first before checking the # token. if Config.current.disable_login - is_admin = @context.storage. + is_admin = Storage.default. username_is_admin Config.current.default_username end if token = env.session.string? "token" - is_admin = @context.storage.verify_admin token + is_admin = Storage.default.verify_admin token end page = {{name}} render "src/views/#{{{name}}}.html.ecr", "src/views/layout.html.ecr" rescue e message = e.to_s - @context.error message + Logger.error message render "src/views/message.html.ecr", "src/views/layout.html.ecr" end end @@ -30,7 +30,7 @@ end macro get_username(env) begin token = env.session.string "token" - (@context.storage.verify_token token).not_nil! + (Storage.default.verify_token token).not_nil! rescue e if Config.current.disable_login Config.current.default_username