diff --git a/Web-UI.md b/Web-UI.md new file mode 100644 index 0000000..52be6bd --- /dev/null +++ b/Web-UI.md @@ -0,0 +1,116 @@ +# Web UI + +Crono comes with a Sinatra application that can display the current state of a Crono jobs. + +# Installation + +Add `sinatra` and `haml` to your Gemfile + +```ruby +gem 'haml' +gem 'sinatra', require: nil +``` + +Add the following to your `config/routes.rb`: + +```ruby +require 'crono/web' + +Rails.application.routes.draw do + mount Crono::Web, at: '/crono' + ... +``` + +### Security + +In production, you probably want to protect access to this information. You can use the constraints feature of routing (in the `config/routes.rb` file) to accomplish this: + +#### Devise + +Allow any authenticated `User` + +```ruby +# config/routes.rb +authenticate :user do + mount Crono::Web, at: '/crono' +end +``` + +Same as above but also ensures that `User#admin?` returns true + +```ruby +# config/routes.rb +authenticate :user, lambda { |u| u.admin? } do + mount Crono::Web, at: '/crono' +end +``` + +#### Authlogic + +```ruby +# lib/admin_constraint.rb +class AdminConstraint + def matches?(request) + return false unless request.cookie_jar['user_credentials'].present? + user = User.find_by_persistence_token(request.cookie_jar['user_credentials'].split(':')[0]) + user && user.admin? + end +end + +# config/routes.rb +require "admin_constraint" +mount Crono::Web, at: '/crono', constraints: AdminConstraint.new +``` + +#### Restful Authentication or Sorcery + +Checks a `User` model instance that responds to `admin?` + +```ruby +# lib/admin_constraint.rb +class AdminConstraint + def matches?(request) + return false unless request.session[:user_id] + user = User.find request.session[:user_id] + user && user.admin? + end +end + +# config/routes.rb +require 'crono/web' +require 'admin_constraint' +mount Crono::Web, at: '/crono', constraints: AdminConstraint.new +``` + +#### Custom External Authentication + +```ruby +class AuthConstraint + def self.admin?(request) + return false unless (cookie = request.cookie_jar['auth']) + + Rails.cache.fetch(cookie['user'], :expires_in => 1.minute) do + auth_data = JSON.parse(Base64.decode64(cookie['data'])) + response = HTTParty.post(Auth.validate_url, :query => auth_data) + + response.code == 200 && JSON.parse(response.body)['roles'].to_a.include?('Admin') + end + end +end + +# config/routes.rb +constraints lambda {|request| AuthConstraint.admin?(request) } do + mount Crono::Web, at: '/admin/crono' +end +``` + +#### Rails HTTP Basic Auth from Routes + +```ruby +# config/routes.rb +require 'crono/web' +Crono::Web.use Rack::Auth::Basic do |username, password| + username == ENV["CRONO_USERNAME"] && password == ENV["CRONO_PASSWORD"] +end if Rails.env.production? +mount Crono::Web, at: '/crono' +```