Skip to content

Instantly share code, notes, and snippets.

@akinsgre
Created June 29, 2011 13:05
Show Gist options
  • Save akinsgre/1053784 to your computer and use it in GitHub Desktop.
Save akinsgre/1053784 to your computer and use it in GitHub Desktop.
class CommentsController < ApplicationController
include UrlHelper
OPEN_ID_ERRORS = {
:missing => "Sorry, the OpenID server couldn't be found",
:canceled => "OpenID verification was canceled",
:failed => "Sorry, the OpenID verification failed" }
before_filter :find_post, :except => [:new]
def index
if request.post? || using_open_id?
create
else
redirect_to(post_path(@post))
end
end
def new
@comment = Comment.build_for_preview(params[:comment])
respond_to do |format|
format.js do
render :partial => 'comment.html.erb', :locals => {:comment => @comment}
end
end
end
# TODO: Spec OpenID with cucumber and rack-my-id
def create
@comment = Comment.new((session[:pending_comment] || params[:comment] || {}).reject {|key, value| !Comment.protected_attribute?(key) })
@comment.post = @post
session[:pending_comment] = nil
if @comment.requires_openid_authentication?
session[:pending_comment] = params[:comment]
logger.info 'getting ready to comment' + @comment.author
authenticate_with_open_id(@comment.author, :optional => [:nickname, :fullname, :email]) do |result, identity_url, registration|
logger.info 'Entering the first authenticate block'
case result.status
when :missing
logger.info "Sorry, the OpenID server couldn't be found"
when :canceled
logger.info "OpenID verification was canceled"
when :failed
logger.info "Sorry, the OpenID verification failed"
when :successful
logger.info 'Was successful first.. time'
#call authenticate again to get results
authenticate_with_open_id(@comment.author, :optional => [:nickname, :fullname, :email]) do |result, identity_url, registration|
logger.info 'Was successful second time'
if result.status == :successful
logger.info 'Accumulating post information'
@comment.post = @post
@comment.author_url = @comment.author
@comment.author = (registration["fullname"] || registration["nickname"] || @comment.author_url).to_s
@comment.author_email = (registration["email"] || @comment.author_url).to_s
@comment.openid_error = ""
session[:pending_comment] = nil
else
logger.info 'Failed second time' + result.status + result.description
@comment.openid_error = OPEN_ID_ERRORS[ result.status ]
end #if result.status
end #inner authenticate
else
logger.info 'Failed first time'
@comment.openid_error = OPEN_ID_ERRORS[ result.status ]
end #case
end #outer authenticate
logger.info "done with authenticate"
else
@comment.blank_openid_fields
end
unless response.headers[Rack::OpenID::AUTHENTICATE_HEADER] # OpenID gem already provided a response
if @comment.save
redirect_to post_path(@post)
else
render :template => 'posts/show'
end
end
end
protected
def find_post
@post = Post.find_by_permalink(*[:year, :month, :day, :slug].collect {|x| params[x] })
end
end
Started POST "/2011/06/26/this-is-a-test-post/comments" for 127.0.0.1 at 2011-06-29 09:00:58 -0400
Processing by CommentsController#index as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"iXzczoX+lhosYK60Rm36RuH0/GWSfwA0Dbaz1a4+zuA=", "comment"=>{"author"=>"http://akinsgre.myopenid.com/", "body"=>"test"}, "commit"=>"Add Comment", "year"=>"2011", "month"=>"06", "day"=>"26", "slug"=>"this-is-a-test-post"}
Post Load (0.3ms) SELECT "posts".* FROM "posts" WHERE "posts"."slug" = 'this-is-a-test-post'
getting ready to commenthttp://akinsgre.myopenid.com/
done with authenticate
Completed 401 Unauthorized in 120ms
Generated checkid_setup request to http://www.myopenid.com/server with assocication {HMAC-SHA1}{4e0b214e}{JZ4Wgg==}
require 'uri'
require 'openid'
require 'rack/openid'
module OpenIdAuthentication
def self.new(app)
store = OpenIdAuthentication.store
if store.nil?
Rails.logger.warn "OpenIdAuthentication.store is nil. Using in-memory store."
end
::Rack::OpenID.new(app, OpenIdAuthentication.store)
end
def self.store
@@store
end
def self.store=(*store_option)
store, *parameters = *([ store_option ].flatten)
@@store = case store
when :memory
require 'openid/store/memory'
OpenID::Store::Memory.new
when :file
require 'openid/store/filesystem'
OpenID::Store::Filesystem.new(Rails.root.join('tmp/openids'))
when :memcache
require 'memcache'
require 'openid/store/memcache'
OpenID::Store::Memcache.new(MemCache.new(parameters))
else
store
end
end
self.store = nil
class Result
ERROR_MESSAGES = {
:missing => "Sorry, the OpenID server couldn't be found",
:invalid => "Sorry, but this does not appear to be a valid OpenID",
:canceled => "OpenID verification was canceled",
:failed => "OpenID verification failed",
:setup_needed => "OpenID verification needs setup"
}
def self.[](code)
new(code)
end
def initialize(code)
@code = code
end
def status
@code
end
ERROR_MESSAGES.keys.each { |state| define_method("#{state}?") { @code == state } }
def successful?
@code == :successful
end
def unsuccessful?
ERROR_MESSAGES.keys.include?(@code)
end
def message
ERROR_MESSAGES[@code]
end
end
protected
# The parameter name of "openid_identifier" is used rather than
# the Rails convention "open_id_identifier" because that's what
# the specification dictates in order to get browser auto-complete
# working across sites
def using_open_id?(identifier = nil) #:doc:
identifier ||= open_id_identifier
!identifier.blank? || request.env[Rack::OpenID::RESPONSE]
end
def authenticate_with_open_id(identifier = nil, options = {}, &block) #:doc:
raise "Test"
OpenID::Util.logger.info "Authenticating with open id" + identifier
identifier ||= open_id_identifier
if request.env[Rack::OpenID::RESPONSE]
complete_open_id_authentication(&block)
else
begin_open_id_authentication(identifier, options, &block)
end
end
private
def open_id_identifier
params[:openid_identifier] || params[:openid_url]
end
def begin_open_id_authentication(identifier, options = {})
options[:identifier] = identifier
value = Rack::OpenID.build_header(options)
response.headers[Rack::OpenID::AUTHENTICATE_HEADER] = value
head :unauthorized
end
def complete_open_id_authentication
response = request.env[Rack::OpenID::RESPONSE]
identifier = response.display_identifier
case response.status
when OpenID::Consumer::SUCCESS
yield Result[:successful], identifier,
OpenID::SReg::Response.from_success_response(response)
when :missing
yield Result[:missing], identifier, nil
when :invalid
yield Result[:invalid], identifier, nil
when OpenID::Consumer::CANCEL
yield Result[:canceled], identifier, nil
when OpenID::Consumer::FAILURE
yield Result[:failed], identifier, nil
when OpenID::Consumer::SETUP_NEEDED
yield Result[:setup_needed], response.setup_url, nil
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment