##// END OF EJS Templates
Link to watched issues list on my page....
Link to watched issues list on my page. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@2457 e93f8b46-1217-0410-a6f0-8f06a7374b81

File last commit:

r2376:f70be197e0ae
r2396:5bdd4291624c
Show More
sreg.rb
277 lines | 9.4 KiB | text/x-ruby | RubyLexer
require 'openid/extension'
require 'openid/util'
require 'openid/message'
module OpenID
module SReg
DATA_FIELDS = {
'fullname'=>'Full Name',
'nickname'=>'Nickname',
'dob'=>'Date of Birth',
'email'=>'E-mail Address',
'gender'=>'Gender',
'postcode'=>'Postal Code',
'country'=>'Country',
'language'=>'Language',
'timezone'=>'Time Zone',
}
NS_URI_1_0 = 'http://openid.net/sreg/1.0'
NS_URI_1_1 = 'http://openid.net/extensions/sreg/1.1'
NS_URI = NS_URI_1_1
begin
Message.register_namespace_alias(NS_URI_1_1, 'sreg')
rescue NamespaceAliasRegistrationError => e
Util.log(e)
end
# raise ArgumentError if fieldname is not in the defined sreg fields
def OpenID.check_sreg_field_name(fieldname)
unless DATA_FIELDS.member? fieldname
raise ArgumentError, "#{fieldname} is not a defined simple registration field"
end
end
# Does the given endpoint advertise support for simple registration?
def OpenID.supports_sreg?(endpoint)
endpoint.uses_extension(NS_URI_1_1) || endpoint.uses_extension(NS_URI_1_0)
end
# Extract the simple registration namespace URI from the given
# OpenID message. Handles OpenID 1 and 2, as well as both sreg
# namespace URIs found in the wild, as well as missing namespace
# definitions (for OpenID 1)
def OpenID.get_sreg_ns(message)
[NS_URI_1_1, NS_URI_1_0].each{|ns|
if message.namespaces.get_alias(ns)
return ns
end
}
# try to add an alias, since we didn't find one
ns = NS_URI_1_1
begin
message.namespaces.add_alias(ns, 'sreg')
rescue IndexError
raise NamespaceError
end
return ns
end
# The simple registration namespace was not found and could not
# be created using the expected name (there's another extension
# using the name 'sreg')
#
# This is not <em>illegal</em>, for OpenID 2, although it probably
# indicates a problem, since it's not expected that other extensions
# will re-use the alias that is in use for OpenID 1.
#
# If this is an OpenID 1 request, then there is no recourse. This
# should not happen unless some code has modified the namespaces for
# the message that is being processed.
class NamespaceError < ArgumentError
end
# An object to hold the state of a simple registration request.
class Request < Extension
attr_reader :optional, :required, :ns_uri
attr_accessor :policy_url
def initialize(required = nil, optional = nil, policy_url = nil, ns_uri = NS_URI)
super()
@policy_url = policy_url
@ns_uri = ns_uri
@ns_alias = 'sreg'
@required = []
@optional = []
if required
request_fields(required, true, true)
end
if optional
request_fields(optional, false, true)
end
end
# Create a simple registration request that contains the
# fields that were requested in the OpenID request with the
# given arguments
# Takes an OpenID::CheckIDRequest, returns an OpenID::Sreg::Request
# return nil if the extension was not requested.
def self.from_openid_request(request)
# Since we're going to mess with namespace URI mapping, don't
# mutate the object that was passed in.
message = request.message.copy
ns_uri = OpenID::get_sreg_ns(message)
args = message.get_args(ns_uri)
return nil if args == {}
req = new(nil,nil,nil,ns_uri)
req.parse_extension_args(args)
return req
end
# Parse the unqualified simple registration request
# parameters and add them to this object.
#
# This method is essentially the inverse of
# getExtensionArgs. This method restores the serialized simple
# registration request fields.
#
# If you are extracting arguments from a standard OpenID
# checkid_* request, you probably want to use fromOpenIDRequest,
# which will extract the sreg namespace and arguments from the
# OpenID request. This method is intended for cases where the
# OpenID server needs more control over how the arguments are
# parsed than that method provides.
def parse_extension_args(args, strict = false)
required_items = args['required']
unless required_items.nil? or required_items.empty?
required_items.split(',').each{|field_name|
begin
request_field(field_name, true, strict)
rescue ArgumentError
raise if strict
end
}
end
optional_items = args['optional']
unless optional_items.nil? or optional_items.empty?
optional_items.split(',').each{|field_name|
begin
request_field(field_name, false, strict)
rescue ArgumentError
raise if strict
end
}
end
@policy_url = args['policy_url']
end
# A list of all of the simple registration fields that were
# requested, whether they were required or optional.
def all_requested_fields
@required + @optional
end
# Have any simple registration fields been requested?
def were_fields_requested?
!all_requested_fields.empty?
end
# Request the specified field from the OpenID user
# field_name: the unqualified simple registration field name
# required: whether the given field should be presented
# to the user as being a required to successfully complete
# the request
# strict: whether to raise an exception when a field is
# added to a request more than once
# Raises ArgumentError if the field_name is not a simple registration
# field, or if strict is set and a field is added more than once
def request_field(field_name, required=false, strict=false)
OpenID::check_sreg_field_name(field_name)
if strict
if (@required + @optional).member? field_name
raise ArgumentError, 'That field has already been requested'
end
else
return if @required.member? field_name
if @optional.member? field_name
if required
@optional.delete field_name
else
return
end
end
end
if required
@required << field_name
else
@optional << field_name
end
end
# Add the given list of fields to the request.
def request_fields(field_names, required = false, strict = false)
raise ArgumentError unless field_names.respond_to?(:each) and
field_names[0].is_a?(String)
field_names.each{|fn|request_field(fn, required, strict)}
end
# Get a hash of unqualified simple registration arguments
# representing this request.
# This method is essentially the inverse of parse_extension_args.
# This method serializes the simple registration request fields.
def get_extension_args
args = {}
args['required'] = @required.join(',') unless @required.empty?
args['optional'] = @optional.join(',') unless @optional.empty?
args['policy_url'] = @policy_url unless @policy_url.nil?
return args
end
def member?(field_name)
all_requested_fields.member?(field_name)
end
end
# Represents the data returned in a simple registration response
# inside of an OpenID id_res response. This object will be
# created by the OpenID server, added to the id_res response
# object, and then extracted from the id_res message by the Consumer.
class Response < Extension
attr_reader :ns_uri, :data
def initialize(data = {}, ns_uri=NS_URI)
@ns_alias = 'sreg'
@data = data
@ns_uri = ns_uri
end
# Take a Request and a hash of simple registration
# values and create a Response object containing that data.
def self.extract_response(request, data)
arf = request.all_requested_fields
resp_data = data.reject{|k,v| !arf.member?(k) || v.nil? }
new(resp_data, request.ns_uri)
end
# Create an Response object from an
# OpenID::Consumer::SuccessResponse from consumer.complete
# If you set the signed_only parameter to false, unsigned data from
# the id_res message from the server will be processed.
def self.from_success_response(success_response, signed_only = true)
ns_uri = OpenID::get_sreg_ns(success_response.message)
if signed_only
args = success_response.get_signed_ns(ns_uri)
return nil if args.nil? # No signed args, so fail
else
args = success_response.message.get_args(ns_uri)
end
args.reject!{|k,v| !DATA_FIELDS.member?(k) }
new(args, ns_uri)
end
# Get the fields to put in the simple registration namespace
# when adding them to an id_res message.
def get_extension_args
return @data
end
# Read-only hashlike interface.
# Raises an exception if the field name is bad
def [](field_name)
OpenID::check_sreg_field_name(field_name)
data[field_name]
end
def empty?
@data.empty?
end
# XXX is there more to a hashlike interface I should add?
end
end
end