require "thor" require "thor/util" require "fileutils" require_relative "hoboken/version" require_relative "hoboken/generate" require_relative "hoboken/actions" module Hoboken class Group < Thor::Group include Thor::Actions include Hoboken::Actions def self.source_root File.dirname(__FILE__) end end class Sequel < Thor::Group include Thor::Actions include Hoboken::Actions def self.source_root File.dirname(__FILE__) end def add_gems gem "sequel", "4.6.0" gem "sqlite3", "1.3.8", group: [:development, :test] end def setup_directories empty_directory("db/migrate") empty_directory("tasks") end def copy_rake_task copy_file("hoboken/templates/sequel.rake", "tasks/sequel.rake") end def setup_database_connection_in_rackup_file insert_into_file("config.ru", after: /require "bundler\/setup"/) do "\nrequire \"logger\"\nrequire \"sequel\"" end app_name = File.open("config.ru").grep(/run.+/).first.chomp.gsub("run ", "") gsub_file("config.ru", /run #{app_name}/) do <<CODE db = Sequel.connect(ENV["DATABASE_URL"], loggers: [Logger.new($stdout)]) Sequel.extension :migration Sequel::Migrator.check_current(db, "db/migrate") if Dir.glob("db/migrate/*.rb").size > 0 app = #{app_name} app.set :database, db run app CODE end end def add_database_test_helper_class insert_into_file("test/test_helper.rb", after: /require "test\/unit"/) do "\nrequire \"sequel\"" end append_file("test/test_helper.rb") do <<CODE module Test::Database class TestCase < Test::Unit::TestCase def run(*args, &block) result = nil database.transaction(rollback: :always) { result = super } result end private def database @database ||= Sequel.sqlite.tap do |db| Sequel.extension :migration Sequel::Migrator.run(db, 'db/migrate') if Dir.glob("db/migrate/*.rb").size > 0 end end end end CODE end end def reminders say "\nGemfile updated... don't forget to 'bundle install'" say <<TEXT Notes: * The sqlite3 gem has been installed for dev and test environments only. You will need to specify a gem to use for production. * You will need to specify an environment variable 'DATABASE_URL' (either add it to .env or export it) TEXT end end class OmniAuth < Thor::Group include Thor::Actions include Hoboken::Actions attr_reader :provider def self.source_root File.dirname(__FILE__) end def add_gem @provider = ask("Specify a provider (i.e. twitter, facebook. etc.): ").downcase provider_version = ask("Specify provider version: ") gem gem_name, provider_version end def setup_middleware insert_into_file("app.rb", after: /require "sinatra("|\/base")/) do "\nrequire \"#{gem_name}\"" end snippet = <<-CODE use OmniAuth::Builder do provider :#{provider}, ENV["#{provider.upcase}_KEY"], ENV["#{provider.upcase}_SECRET"] end CODE text = modular? ? indent(snippet, 4) : snippet insert_into_file("app.rb", after: /use Rack::Session::Cookie.+\n/) { text } end def add_routes routes = <<-CODE get "/login" do '<a href="/auth/#{provider}">Login</a>' end get "/auth/:provider/callback" do # TODO: Insert real authentication logic... MultiJson.encode(request.env['omniauth.auth']) end get "/auth/failure" do # TODO: Insert real error handling logic... halt 401, params[:message] end CODE if modular? insert_into_file("app.rb", after: /get.+?end$/m) { indent(routes, 4) } else append_file("app.rb", routes) end end def add_tests inject_into_class("test/unit/app_test.rb", "AppTest") do <<-CODE setup do OmniAuth.config.test_mode = true end test "GET /login" do get "/login" assert_equal('<a href="/auth/#{provider}">Login</a>', last_response.body) end test "GET /auth/#{provider}/callback" do auth_hash = { "provider" => "#{provider}", "uid" => "123545", "info" => { "name" => "John Doe" } } OmniAuth.config.mock_auth[:#{provider}] = auth_hash get "/auth/fitbit/callback" assert_equal(MultiJson.encode(auth_hash), last_response.body) end test "GET /auth/failure" do OmniAuth.config.mock_auth[:#{provider}] = :invalid_credentials get "/auth/failure" assert_response :not_authorized end CODE end end def reminders say "\nGemfile updated... don't forget to 'bundle install'" end private def gem_name "omniauth-#{provider}" end def modular? @modular ||= File.readlines("app.rb").grep(/Sinatra::Base/).any? end end require_relative "hoboken/add_ons/metrics" require_relative "hoboken/add_ons/internationalization" require_relative "hoboken/add_ons/heroku" require_relative "hoboken/add_ons/sprockets" class CLI < Thor desc "version", "Print version and quit" def version puts "Hoboken v#{Hoboken::VERSION}" end register(Generate, "generate", "generate [APP_NAME]", "Generate a new Sinatra app") tasks["generate"].options = Hoboken::Generate.class_options register(AddOns::Metrics, "add:metrics", "add:metrics", "Add metrics (flog, flay, simplecov)") register(AddOns::Internationalization, "add:i18n", "add:i18n", "Internationalization support using sinatra-r18n") register(AddOns::Heroku, "add:heroku", "add:heroku", "Heroku deployment support") register(OmniAuth, "add:omniauth", "add:omniauth", "OmniAuth authentication (allows you to select a provider)") register(AddOns::Sprockets, "add:sprockets", "add:sprockets", "Rack-based asset packaging system") register(Sequel, "add:sequel", "add:sequel", "Database access via Sequel gem") end end