- implement login and load images from zip

This commit is contained in:
Alex Ling 2020-02-12 03:47:10 +00:00
parent a3203dccba
commit cc031c9aef
5 changed files with 148 additions and 14 deletions

View File

@ -1,15 +1,25 @@
require "kemal"
require "./storage"
class AuthHandler < Kemal::Handler
exclude ["/login"]
exclude ["/login"], "POST"
property storage : Storage
def initialize(@storage)
end
def call(env)
return call_next(env) if exclude_match?(env)
my_cookie = HTTP::Cookie.new(
name: "Example",
value: "KemalCR"
)
env.response.cookies << my_cookie
pp env.request.cookies
env.request.cookies.each do |c|
next if c.name != "token"
if @storage.verify_token c.value
return call_next env
end
end
env.redirect "/login"
end
end

View File

@ -1,4 +1,14 @@
require "zip"
require "mime"
class Image
property data : Bytes
property mime : String
property filename : String
property size : Int32
def initialize(@data, @mime, @filename, @size)
end
end
class Entry
property zip_path : String
@ -10,6 +20,29 @@ class Entry
@title = File.basename path, ".zip"
@size = (File.size path).humanize_bytes
end
def read_page(page_num)
Zip::File.open @zip_path do |file|
page = file.entries
.select { |e|
["image/jpeg", "image/png"].includes? \
MIME.from_filename? e.filename
}
.sort { |a, b| a.filename <=> b.filename }
.[page_num]
page.open do |io|
slice = Bytes.new page.uncompressed_size
bytes_read = io.read_fully? slice
unless bytes_read
return nil
end
return Image.new slice, MIME.from_filename(page.filename),\
page.filename, bytes_read
end
end
end
def get_cover()
read_page 0
end
end
class Title
@ -25,6 +58,9 @@ class Title
.map { |path| Entry.new File.join dir, path }
.sort { |a, b| a.title <=> b.title }
end
def get_cover()
@entries[0].get_cover
end
end
class Library

View File

@ -5,21 +5,47 @@ require "./storage"
require "./auth_handler"
config = Config.load
library = Library.new config.library_path
storage = Storage.new config.db_path
get "/" do
"Hello World!"
macro layout(name)
render "src/views/#{{{name}}}.ecr", "src/views/layout.ecr"
end
# APIs
get "/api/test" do |env|
"Hello!"
macro send_img(env, img)
send_file env, image.data, image.mime
end
add_handler AuthHandler.new
get "/" do |env|
image = library.titles[0].get_cover
unless image
"Failed to load image"
next
end
send_img env, image
end
get "/login" do |env|
render "src/views/login.ecr"
end
post "/login" do |env|
username = env.params.body["username"]
password = env.params.body["password"]
token = storage.verify_user username, password
if token.nil?
env.redirect "/login"
next
end
cookie = HTTP::Cookie.new "token", token
env.response.cookies << cookie
env.redirect "/"
end
add_handler AuthHandler.new storage
Kemal.config.port = config.port
Kemal.run

24
src/views/layout.ecr Normal file
View File

@ -0,0 +1,24 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="X-UA-Compatible" content="IE=edge">
<title>Mango</title>
<meta name="description" content="Mango Manga Server">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/uikit@3.3.1/dist/css/uikit.min.css" />
</head>
<body>
<div class="uk-section uk-section-primary uk-section-small">
<p class="uk-align-right uk-margin-right">Hello !</p>
</div>
<div class="uk-section uk-section-default uk-section-small">
<%= content %>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/uikit@3.3.1/dist/js/uikit.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/uikit@3.3.1/dist/js/uikit-icons.min.js"></script>
</body>
</html>

38
src/views/login.ecr Normal file
View File

@ -0,0 +1,38 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="X-UA-Compatible" content="IE=edge">
<title>Mango</title>
<meta name="description" content="Mango Manga Server">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/uikit@3.3.1/dist/css/uikit.min.css" />
</head>
<body>
<div class="uk-section uk-section-muted uk-flex uk-flex-middle uk-animation-fade" uk-height-viewport="">
<div class="uk-width-1-1">
<div class="uk-container">
<div class="uk-grid-margin uk-grid uk-grid-stack" uk-grid="">
<div class="uk-width-1-1@m">
<div class="uk-margin uk-width-large uk-margin-auto uk-card uk-card-default uk-card-body uk-box-shadow-large">
<h3 class="uk-card-title uk-text-center">Log In</h3>
<form action="/login" method="post">
<div class="uk-margin">
<div class="uk-inline uk-width-1-1"><span class="uk-form-icon" uk-icon="icon:user"></span><input class="uk-input uk-form-large" type="text" name="username"></div>
</div>
<div class="uk-margin">
<div class="uk-inline uk-width-1-1"><span class="uk-form-icon" uk-icon="icon:lock"></span><input class="uk-input uk-form-large" type="password" name="password"></div>
</div>
<div class="uk-margin"><button class="uk-button uk-button-primary uk-button-large uk-width-1-1">Login</button></div>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/uikit@3.3.1/dist/js/uikit.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/uikit@3.3.1/dist/js/uikit-icons.min.js"></script>
</body>
</html>