require "http/server" require "ecr/macros" require "json" require "yaml" require "secure_random" require "sqlite3" module Guff # TODO: think about versioning a bit (semantic, datestamp, etc) VERSION = "20160715" end require "./guff/**" module Guff module CLI module Actions abstract class Action def self.run(config : Config) new(config).run end def initialize(@config : Config) end abstract def run end class InitAction < Action class Data YAML.mapping({ init_sql: Array(String), add_user: String, test_posts: Array(String), }) def self.load(system_dir : String) : Data self.from_yaml(File.read(File.join(system_dir, "init.yaml"))) end end def initialize(config : Config) super(config) # read init data @data = Data.load(@config.system_dir) end def run STDERR.puts "Initializing data directory" Dir.mkdir(@config.data_dir) unless Dir.exists?(@config.data_dir) Guff::Database.new(@config.db_path) do |db| @data.init_sql.each do |sql| db.query(sql) end # gen random password and add admin user # TODO: move these to init.yaml password = Password.random_password add_user(db, "Admin", "admin@admin", password) add_user(db, "Test", "test@test", "test") add_test_posts(db) STDERR.puts "admin user: admin@admin, password: #{password}" end end private def add_user( db : Database, name : String, email : String, password : String ) : Int64 db.query(@data.add_user, [ name, email, Password.create(password), "admin", ]) db.last_insert_row_id.to_i64 end private def add_test_posts(db) # STDERR.puts "DEBUG: adding test data" @data.test_posts.each do |sql| db.query(sql) end end end class RunAction < Action def run STDERR.puts "Running web server" check_dirs # create context context = Context.new(@config) STDERR.puts "listening on %s:%s" % [@config.host, @config.port] # run server HTTP::Server.new( @config.host, @config.port.to_i, Handlers.get(context) ).listen end private def check_dirs { system: @config.system_dir, data: @config.data_dir, }.each do |name, dir| unless Dir.exists?(dir) raise "missing #{name} directory: \"#{dir}\"" end end end end end def self.run(app : String, args : Array(String)) begin begin # parse command-line arguments config = Config.parse(app, args) rescue err raise "#{err}. Use --help for usage" end case config.mode when "init" Actions::InitAction.run(config) when "run" Actions::RunAction.run(config) when "help" # do nothing else # never reached raise "unknown mode: #{config.mode}" end rescue err STDERR.puts "ERROR: #{err}." exit -1 end end end end Guff::CLI.run($0, ARGV)