#!/usr/bin/env ruby $:.unshift File.dirname(__FILE__) + "/../../lib" require 'rubygems' require 'camping' require 'camping/db' require 'camping/session' require 'reststop' require 'httpauth' Camping.goes :Ctd module Ctd #http://rubyforge.org/pipermail/camping-list/2008-February/000589.html include Camping::Session include HTTPAuth::Digest REALM = "ctd" class Unauthorized < RuntimeError; end # call this at the start of methods that require authentication def authenticate raise Unauthorized unless @user end def service(*a) auth_h = @env["HTTP_AUTHORIZATION"] begin if auth_h credentials = Credentials.from_header(auth_h) user = credentials.h[:username] begin pass = password_for_user(user) rescue NameError raise "define #password_for_user on your app module" end if pass and credentials.validate(:password => pass, :method => @method.upcase) @user = user auth_info = AuthenticationInfo.from_credentials credentials @headers["Authentication-Info"] = auth_info.to_header end end super() rescue HTTPAuth::UnwellformedHeader # they probably sent eg. a Basic Authenticate header # just ignore it instead of exploding end super(*a) rescue Unauthorized @status = 401 challenge = Challenge.new :realm => REALM, :qop => ["auth"] @headers["WWW-Authenticate"] = challenge.to_header @body = authentication_failed self end # override this for a nicer error message def authentication_failed @headers["Content-Type"] = "text/plain" "you are not authorized." end def password_for_user(username) Ctd::Models::User.find( :first, :conditions => ['username = ?', username]).password end end module Ctd::Models class Device < Base; end class User < Base; validates_uniqueness_of :username end class CreateTheBasics < V 1.0 def self.up create_table :ctd_devices do |t| t.column :channel, :integer, :null => false t.column :on?, :boolean, :default => true end create_table :ctd_users do |t| t.column :username, :string t.column :password, :string end User.create :username => 'admin', :password => 'camping' (1..8).each {|n| Device.create :channel => n} end def self.down drop_table :ctd_users drop_table :ctd_devices end end end module Ctd::Controllers class NotFound def get(p) @status = 404 div do h1 'Lo Sentimos' h2 "Todos los circuitos están ocupados" h3 do text("Por favor ") text( a('cuelgue', :href => R(Index))) text( "y deje de marcar #{p}") end end end end class Info < R '/info/(\d+)', '/info/(\w+)/(\d+)', '/info', '/info/(\d+)/(\d+)/(\d+)/([\w-]+)' def get(*args) div do code args.inspect; br; br code @env.inspect; br code "Link: #{R(Info, 1, 2)}" end end end class Index < R '/' def get redirect "devices" end end class Devices < REST 'devices' # get /devices/1 def read(channel) authenticate #return redirect R(Index) if @state.user_id.blank? begin @device = Device.find channel rescue @device = nil end render :device end # get /devices def list authenticate @device = nil render :device end end end Markaby::Builder.set(:indent, 2) module Ctd::Views def layout html do head do title 'Call To Device' link :rel => 'stylesheet', :type => 'text/css', :href => '/styles.css', :media => 'screen' end body do h1.header { a 'Call To Device', :href => R(Index) } div.content do self << yield end end end end def device if @device p "Usted ha seleccionado el dispositivo #{@device.channel}" else p "Seleccione el dispositivo a administrar" end end end def Ctd.create Camping::Models::Session.create_schema Ctd::Models.create_schema :assume => (Ctd::Models::Device.table_exists? ? 1.0 : 0.0) end if __FILE__ == $0 require 'webrick/httpserver' require 'webrick/https' require 'camping/webrick' Camping::Models::Base.establish_connection :adapter => "sqlite3", :database => "ctd.db" Ctd.create s = WEBrick::HTTPServer.new( :SSLEnable => true, :SSLCertName => [ ["C","DO"], ["O","CTD.Com"], ["CN", "localhost"] ], :BindAddress => "0.0.0.0", :Port => 3301 ) s.mount "/", WEBrick::CampingHandler, Ctd # This lets Ctrl+C shut down your server trap(:INT) do s.shutdown end s.start end