-require 'openid'
-require 'openid/extension'
-require 'openid/extensions/sreg'
-require 'openid/store/filesystem'
-require 'openid/util'
-require 'rack/request'
-require 'rack/utils'
-require 'fileutils'
-
-
-module Rots
-
- class ServerApp
-
- attr_accessor :request,:openid_request,
- :response, :openid_response,
- :server
-
- def initialize(config, server_options)
- @server_options = server_options
- @sreg_fields = config['sreg']
- end
-
- def call(env)
- on_openid_request(env) do
- if !is_checkid_request?
- @openid_response = @server.handle_request(@openid_request)
- reply_consumer
- elsif is_checkid_immediate?
- process_immediate_checkid_request
- else
- process_checkid_request
- end
- end
- end
-
- protected
-
- def on_openid_request(env)
- create_wrappers(env)
- if @openid_request.nil?
- [200, {'Content-Type' => 'text/html'},
- ["<html><body><h1>ROTS => This is an OpenID endpoint</h1></body></html>"] ]
- else
- yield
- end
- end
-
- def create_wrappers(env)
- @request = Rack::Request.new(env)
- @server = OpenID::Server::Server.new(storage, op_endpoint)
- @openid_request = @server.decode_request(@request.params)
- @openid_sreg_request = OpenID::SReg::Request.from_openid_request(@openid_request) unless @openid_request.nil?
- end
-
- def is_checkid_request?
- @openid_request.is_a?(OpenID::Server::CheckIDRequest)
- end
-
- def is_checkid_immediate?
- @openid_request && @openid_request.immediate
- end
-
- def process_immediate_checkid_request
- # TODO: We should enable the user to configure
- # if she wants immediate request support or not
- url = OpenID::Util.append_args(@openid_request.return_to,
- @request.params.merge('openid.mode' => 'setup_needed'))
- redirect(url)
- end
-
- def process_checkid_request
- if checkid_request_is_valid?
- return_successful_openid_response
- else
- return_cancel_openid_response
- end
- end
-
- def checkid_request_is_valid?
- @request.params['openid.success'] == 'true'
- end
-
- def return_successful_openid_response
- @openid_response = @openid_request.answer(true)
- process_sreg_extension
- # TODO: Add support for SREG extension
- @server.signatory.sign(@openid_response) if @openid_response.needs_signing
- reply_consumer
- end
-
- def process_sreg_extension
- return if @openid_sreg_request.nil?
- response = OpenID::SReg::Response.extract_response(@openid_sreg_request, @sreg_fields)
- @openid_response.add_extension(response)
- end
-
- def return_cancel_openid_response
- redirect(@openid_request.cancel_url)
- end
-
- def reply_consumer
- web_response = @server.encode_response(@openid_response)
- case web_response.code
- when OpenID::Server::HTTP_OK
- success(web_response.body)
- when OpenID::Server::HTTP_REDIRECT
- redirect(web_response.headers['location'])
- else
- bad_request
- end
- end
-
- def redirect(uri)
- [ 303, {'Content-Length'=>'0', 'Content-Type'=>'text/plain',
- 'Location' => uri},
- [] ]
- end
-
- def bad_request()
- [ 400, {'Content-Type'=>'text/plain', 'Content-Length'=>'0'},
- [] ]
- end
-
- def storage
- # create the folder if it doesn't exist
- FileUtils.mkdir_p(@server_options[:storage]) unless File.exist?(@server_options[:storage])
- OpenID::Store::Filesystem.new(@server_options[:storage])
- end
-
- def success(text="")
- Rack::Response.new(text).finish
- end
-
- def op_endpoint
- if @request.url =~ /(.*\?openid.success=true)/
- $1
- elsif @request.url =~ /([^?]*)/
- $1
- else
- nil
- end
- end
-
- end
-
-end
\ No newline at end of file