- initial commit

This commit is contained in:
Alex Ling
2020-02-11 22:06:17 +00:00
commit 3c2b054ec8
15 changed files with 324 additions and 0 deletions

15
src/auth_handler.cr Normal file
View File

@@ -0,0 +1,15 @@
require "kemal"
class AuthHandler < Kemal::Handler
exclude ["/login"]
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
end
end

37
src/config.cr Normal file
View File

@@ -0,0 +1,37 @@
require "yaml"
require "uuid"
require "base64"
class Config
include YAML::Serializable
@[YAML::Field(key: "port")]
property port = 9000
@[YAML::Field(key: "library_path")]
property library_path = File.expand_path "~/mango-library", home: true
@[YAML::Field(key: "db_path")]
property db_path = File.expand_path "~/mango-library/mango.db", home: true
def self.load
cfg_path = File.expand_path "~/.config/mango/config.yml", home: true
if File.exists? cfg_path
return self.from_yaml File.read cfg_path
end
puts "The config file #{cfg_path} does not exist." \
"Do you want mango to dump the default config there? [Y/n]"
input = gets
if !input.nil? && input.downcase == "n"
abort "Aborting..."
end
default = self.allocate
cfg_dir = File.dirname cfg_path
unless Dir.exists? cfg_dir
Dir.mkdir_p cfg_dir
end
File.write cfg_path, default.to_yaml
puts "The config file has been created at #{cfg_path}."
default
end
end

44
src/library.cr Normal file
View File

@@ -0,0 +1,44 @@
require "zip"
class Entry
property zip_path : String
property title : String
property size : String
def initialize(path : String)
@zip_path = path
@title = File.basename path, ".zip"
@size = (File.size path).humanize_bytes
end
end
class Title
property dir : String
property entries : Array(Entry)
property title : String
def initialize(dir : String)
@dir = dir
@title = File.basename dir
@entries = (Dir.entries dir)
.select! { |path| (File.extname path) == ".zip" }
.map { |path| Entry.new File.join dir, path }
.sort { |a, b| a.title <=> b.title }
end
end
class Library
property dir : String
property titles : Array(Title)
def initialize(dir : String)
@dir = dir
unless Dir.exists? dir
abort "ERROR: The library directory #{dir} does not exist"
end
@titles = (Dir.entries dir)
.select! { |path| File.directory? File.join dir, path }
.map { |path| Title.new File.join dir, path }
.select! { |title| !title.entries.empty? }
end
end

25
src/mango.cr Normal file
View File

@@ -0,0 +1,25 @@
require "kemal"
require "./config"
require "./library"
require "./storage"
require "./auth_handler"
config = Config.load
library = Library.new config.library_path
storage = Storage.new config.db_path
get "/" do
"Hello World!"
end
# APIs
get "/api/test" do |env|
"Hello!"
end
add_handler AuthHandler.new
Kemal.config.port = config.port
Kemal.run

73
src/storage.cr Normal file
View File

@@ -0,0 +1,73 @@
require "sqlite3"
require "crypto/bcrypt"
require "uuid"
require "base64"
def hash_password(pw)
Crypto::Bcrypt::Password.create(pw).to_s
end
def verify_password(hash, pw)
(Crypto::Bcrypt::Password.new hash).verify pw
end
def random_str()
Base64.strict_encode UUID.random().to_s
end
class Storage
property path : String
def initialize(path)
@path = path
DB.open "sqlite3://#{path}" do |db|
begin
db.exec "create table users" \
"(username text, password text, token text, admin integer)"
rescue e : SQLite3::Exception | DB::Error
unless e.message == "table users already exists"
raise e
end
else
db.exec "create unique index username_idx on users (username)"
db.exec "create unique index token_idx on users (token)"
random_pw = random_str
hash = hash_password random_pw
db.exec "insert into users values (?, ?, ?, ?)",
"admin", hash, "", 1
puts "Initial user created. You can log in with " \
"#{{"username" => "admin", "password" => random_pw}}"
end
end
end
def verify_user(username, password)
DB.open "sqlite3://#{@path}" do |db|
begin
hash = db.query_one "select password from users where " \
"username = (?)", username, as: String
unless verify_password hash, password
return nil
end
token = random_str
db.exec "update users set token = (?) where username = (?)",
token, username
return token
rescue e : SQLite3::Exception | DB::Error
return nil
end
end
end
def verify_token(token)
DB.open "sqlite3://#{@path}" do |db|
begin
username = db.query_one "select username from users where " \
"token = (?)", token, as: String
return username
rescue e : SQLite3::Exception | DB::Error
return nil
end
end
end
end