require 'rpx_now/api' require 'rpx_now/contacts_collection' require 'cgi' module RPXNow extend self attr_accessor :api_key attr_accessor :api_version attr_accessor :domain self.api_version = 2 self.domain = 'rpxnow.com' VERSION = File.read( File.join(File.dirname(__FILE__),'..','VERSION') ).strip # retrieve the users data # - cleaned Hash # - complete/unclean response when block was given user_data{|response| ...; return hash } # - nil when token was invalid / data was not found def user_data(token, options={}) options = options.dup return_raw = options.delete(:raw_response) data = begin auth_info(token, options) rescue ServerError return nil if $!.to_s=~/Data not found/ raise end result = (block_given? ? yield(data) : (return_raw ? data : parse_user_data(data, options))) with_indifferent_access(result) end # same data as user_data, but without any kind of post-processing def auth_info(token, options={}) data = Api.call("auth_info", options.merge(:token => token)) with_indifferent_access(data) end # same as for auth_info if Offline Profile Access is enabled, # but can be called at any time and does not need a token / does not expire def get_user_data(identifier, options={}) data = Api.call("get_user_data", options.merge(:identifier => identifier)) with_indifferent_access(data) end # set the users status def set_status(identifier, status, options={}) options = options.merge(:identifier => identifier, :status => status) Api.call("set_status", options) rescue ServerError return nil if $!.to_s=~/Data not found/ raise end # Post an activity update to the user's activity stream. # See more: https://rpxnow.com/docs#api_activity def activity(identifier, activity_options, options={}) options = options.merge(:identifier => identifier, :activity => activity_options.to_json) Api.call("activity", options) end # maps an identifier to an primary-key (e.g. user.id) def map(identifier, primary_key, options={}) Api.call("map", options.merge(:identifier => identifier, :primaryKey => primary_key)) end # un-maps an identifier to an primary-key (e.g. user.id) def unmap(identifier, primary_key, options={}) Api.call("unmap", options.merge(:identifier => identifier, :primaryKey => primary_key)) end # returns an array of identifiers which are mapped to one of your primary-keys (e.g. user.id) def mappings(primary_key, options={}) Api.call("mappings", options.merge(:primaryKey => primary_key))['identifiers'] end def all_mappings(options={}) Api.call("all_mappings", options)['mappings'] end def contacts(identifier, options={}) data = Api.call("get_contacts", options.merge(:identifier => identifier)) RPXNow::ContactsCollection.new(data['response']) end alias get_contacts contacts # embedded rpx login (via iframe) # options: :width, :height, :language, :flags, :api_version, :default_provider def embed_code(subdomain, url, options={}) options = {:width => '400', :height => '240'}.merge(options) <<-EOF EOF end # popup window for rpx login # options: :language, :flags, :unobtrusive, :api_version, :default_provider, :html def popup_code(text, subdomain, url, options = {}) if options[:unobtrusive] unobtrusive_popup_code(text, subdomain, url, options) else obtrusive_popup_code(text, subdomain, url, options) end end # javascript for popup # only needed in combination with popup_code(x,y,z, :unobtrusive => true) def popup_source(subdomain, url, options={}) <<-EOF EOF end # url for unobtrusive popup window # options: :language, :flags, :api_version, :default_provider def popup_url(subdomain, url, options={}) "#{Api.host(subdomain)}/openid/v#{extract_version(options)}/signin?#{embed_params(url, options)}" end def extract_version(options) options[:api_version] || api_version end private def self.embed_params(url, options) { :token_url => CGI::escape( url ), :language_preference => options[:language], :flags => options[:flags], :default_provider => options[:default_provider] }.map{|k,v| "#{k}=#{v}" if v}.compact.join('&') end def self.parse_user_data(response, options) user_data = response['profile'] data = {} data[:identifier] = user_data['identifier'] data[:email] = user_data['verifiedEmail'] || user_data['email'] data[:username] = user_data['preferredUsername'] || data[:email].to_s.sub(/@.*/,'') data[:name] = user_data['displayName'] || data[:username] data[:id] = user_data['primaryKey'] unless user_data['primaryKey'].to_s.empty? additional = (options[:additional] || []) additional << :extended if options[:extended] additional.each do |key| data[key] = case key when :raw warn "RPXNow :raw is deprecated, please use :raw_response + e.g. data['raw_response']['profile']['verifiedEmail']" user_data when :raw_response response when :extended response.reject{|k,v| ['profile','stat'].include?(k) } else user_data[key.to_s] end end data end def unobtrusive_popup_code(text, subdomain, url, options={}) options = options.dup html_options = options.delete(:html) || {} html_options[:class] = "rpxnow #{html_options[:class]}".strip html_options[:href] ||= popup_url(subdomain, url, options) html_options = html_options.sort_by{|k,v|k.to_s}.map{|k,v| %{#{k}="#{v}"}} %{#{text}} end def obtrusive_popup_code(text, subdomain, url, options = {}) unobtrusive_popup_code(text, subdomain, url, options) + popup_source(subdomain, url, options) end def with_indifferent_access(hash) hash.respond_to?(:with_indifferent_access) ? hash.with_indifferent_access : hash end class ServerError < RuntimeError; end #backwards compatibility / catch all class ApiError < ServerError; end class ServiceUnavailableError < ServerError; end end