devise_rpx_connectable 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2010 Nicolas Blanco
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.textile ADDED
@@ -0,0 +1,166 @@
1
+ h1. Devise RPX Connectable
2
+
3
+ _Devise << RPX_
4
+
5
+ h2. What is Devise?
6
+
7
+ A great authentication gem for Rails applications.
8
+
9
+ "http://github.com/plataformatec/devise":http://github.com/plataformatec/devise
10
+
11
+ h2. What is RPX?
12
+
13
+ RPX is a Software as a Service (SaaS) that helps you manage multiple authentication methods (FacebookConnect, Google, Twitter, OpenID, MySpace...) using a single API.
14
+ It also provides a multilingual connection widget.
15
+ Instead of managing multiple authentication providers and APIs, you just need to handle one.
16
+
17
+ RPX provides free and paid accounts.
18
+
19
+ See *"RPX official homepage":https://rpxnow.com/*. If you want to see what it looks like, you may signup on the RPX website as it uses RPX for signup :).
20
+
21
+ h2. What is Devise RPX Connectable?
22
+
23
+ Devise RPX Connectable is a gem to integrate RPX authentication in a Rails application using Devise.
24
+
25
+ h2. Dependencies
26
+
27
+ Devise RPX Connectable was tested using latest stable Rails and Devise gems.
28
+
29
+ Currently :
30
+
31
+ *Rails* : version 2.3.5
32
+ *Devise* : version 1.0.6
33
+
34
+ I also want it to be compatible with latest prerelease gems of Devise, Rails and Mongoid.
35
+ Therefore I also tested it with :
36
+
37
+ *Rails* : version 3.0.0beta3
38
+ *Mongoid* : version 2.0.0beta4
39
+ *Devise* : master branch.
40
+
41
+ h2. Installation
42
+
43
+ *Gem (Rails >= 2.3.5)*
44
+
45
+ <pre>
46
+ $ sudo gem install devise_rpx_connectable
47
+ </pre>
48
+
49
+ ...and in @config/environment.rb@:
50
+
51
+ <pre>
52
+ config.gem 'devise'
53
+ config.gem 'rpx_now'
54
+ config.gem 'devise_rpx_connectable'
55
+ </pre>
56
+
57
+ *Gem (Rails >= 3.0.0beta3)*
58
+
59
+ @Gemfile@
60
+
61
+ <pre>
62
+ gem 'devise', :git => 'git://github.com/plataformatec/devise.git'
63
+ gem 'rpx_now'
64
+ gem 'devise_rpx_connectable'
65
+ </pre>
66
+
67
+ h2. Setup
68
+
69
+ *Devise: Setup*
70
+
71
+ See "Devise":http://github.com/plataformatec/devise documentation for instructions on how to setup Devise.
72
+
73
+ *Devise: Model*
74
+
75
+ Add @:rpx_connectable@ in your Devise model (ie. User.rb)
76
+
77
+ <pre>
78
+ devise ..., :rpx_connectable
79
+ </pre>
80
+
81
+ *Devise:Setup*
82
+
83
+ In the Devise initializer (may be @config/initializers/devise.rb@) :
84
+
85
+ <pre>
86
+ Devise.setup do |config|
87
+ ...
88
+ config.rpx_application_name = "mytestingapp" # The name of your RPX application (this is the name, NOT the API key!)
89
+ end
90
+ </pre>
91
+
92
+ *RPXNow:API Key*
93
+
94
+ In @config/environment.rb@ :
95
+
96
+ <pre>
97
+ ...
98
+ config.after_initialize do # so rake gems:install works
99
+ RPXNow.api_key = "aaaabbbbbccccdddddeeeeefffff"
100
+ end
101
+ ...
102
+ </pre>
103
+
104
+ *Migrations*
105
+
106
+ Your model needs one attribute/column to store the RPX identifier. By default, this identifier is @rpx_identifier@.
107
+
108
+ *Views*
109
+
110
+ I added an easy to use helper to add a link to the RPX connection popup.
111
+
112
+ <pre>
113
+ <%= link_to_rpx "Signin using RPX!", user_session_url %>
114
+ </pre>
115
+
116
+ If you use the link alone, users will be redirected to a new page.
117
+ If you want the more sexy popup in overlay, you need to add the JS code before the @</body>@ of your layout.
118
+ An helper is also included for this task :
119
+
120
+ <pre>
121
+ ...
122
+ <%= javascript_include_rpx(user_session_url) %>
123
+ </body>
124
+ </html>
125
+ </pre>
126
+
127
+ h2. Advanced
128
+
129
+ There is some advanced features that you may use...
130
+
131
+ *Devise:Setup*
132
+
133
+ <pre>
134
+ Devise.setup do |config|
135
+ ...
136
+ config.rpx_auto_create_account = true # false if you don't want to create users automaticaly. True by default.
137
+ end
138
+ </pre>
139
+
140
+ *Devise:Model*
141
+
142
+ Some hooks are available to get the RPXNow user data objects before or after the connection. Read the RPXNow gem documentation for more information.
143
+
144
+ <pre>
145
+ def before_rpx_connect(rpx_user)
146
+ # Do something with rpx_user...
147
+ end
148
+
149
+ def after_rpx_connect(rpx_user)
150
+ # Do something with rpx_user
151
+ end
152
+ </pre>
153
+
154
+ h2. TODO
155
+
156
+ * With Rails 3 (only) I get an invalid auth token in sessions#create action. I have to skip the validation of the auth token. See why?
157
+ * Handle RPX multiple accounts mapping?
158
+
159
+ h2. Thanks
160
+
161
+ The base of this gem was heavily inspired from the "Devise Facebook Connectable gem":http://github.com/grimen/devise_facebook_connectable by "Jonas Grimfelt":http://github.com/grimen and other Devise gems.
162
+
163
+ h2. License
164
+
165
+ Released under the MIT license.<br />
166
+ Copyright (c) 2010 "Nicolas Blanco":http://github.com/slainer68
data/Rakefile ADDED
@@ -0,0 +1,30 @@
1
+ # encoding: utf-8
2
+ require 'rubygems'
3
+ require 'rake'
4
+ require 'rake/rdoctask'
5
+ require File.join(File.dirname(__FILE__), 'lib', 'devise_rpx_connectable', 'version')
6
+
7
+ NAME = "devise_rpx_connectable"
8
+
9
+ begin
10
+ gem 'jeweler'
11
+ require 'jeweler'
12
+ Jeweler::Tasks.new do |spec|
13
+ spec.name = NAME
14
+ spec.version = ::Devise::RpxConnectable::VERSION
15
+ spec.summary = %{Devise << RPX}
16
+ spec.description = spec.summary
17
+ spec.homepage = "http://github.com/slainer68/#{spec.name}"
18
+ spec.authors = ["Nicolas Blanco"]
19
+ spec.email = "slainer68@gmail.com"
20
+
21
+ spec.files = FileList['[A-Z]*', File.join(*%w[{lib,rails} ** *]).to_s]
22
+
23
+ spec.add_dependency 'devise', '>= 1.0.6'
24
+ spec.add_dependency 'rpx_now', '>= 0.6.19'
25
+ end
26
+ Jeweler::GemcutterTasks.new
27
+ rescue LoadError
28
+ puts "Jeweler - or one of its dependencies - is not available. " <<
29
+ "Install it with: sudo gem install jeweler -s http://gemcutter.org"
30
+ end
@@ -0,0 +1,4 @@
1
+ en:
2
+ devise:
3
+ sessions:
4
+ rpx_invalid: "Could not login. Invalid account."
@@ -0,0 +1,157 @@
1
+ # encoding: utf-8
2
+ require 'devise/models'
3
+
4
+ module Devise #:nodoc:
5
+ # module RpxConnectable #:nodoc:
6
+ module Models #:nodoc:
7
+
8
+ # RPX Connectable Module, responsible for validating authenticity of a
9
+ # user and storing credentials while signing in.
10
+ #
11
+ # == Configuration:
12
+ #
13
+ # You can overwrite configuration values by setting in globally in Devise (+Devise.setup+),
14
+ # using devise method, or overwriting the respective instance method.
15
+ #
16
+ # +rpx_identifier_field+ - Defines the name of the RPX identifier database attribute/column.
17
+ #
18
+ # +rpx_auto_create_account+ - Speifies if account should automatically be created upon connect
19
+ # if not already exists.
20
+ #
21
+ # == Examples:
22
+ #
23
+ # User.authenticate_with_rpx(:identifier => 'john@doe.com') # returns authenticated user or nil
24
+ # User.find(1).rpx_connected? # returns true/false
25
+ #
26
+ module RpxConnectable
27
+
28
+ def self.included(base) #:nodoc:
29
+ base.class_eval do
30
+ extend ClassMethods
31
+ end
32
+ end
33
+
34
+ # Store RPX account/session credentials.
35
+ #
36
+ def store_rpx_credentials!(attributes = {})
37
+ self.send(:"#{self.class.rpx_identifier_field}=", attributes[:identifier])
38
+
39
+ # Confirm without e-mail - if confirmable module is loaded.
40
+ self.skip_confirmation! if self.respond_to?(:skip_confirmation!)
41
+
42
+ # Only populate +email+ field if it's available (e.g. if +authenticable+ module is used).
43
+ self.email = attributes[:email] || '' if self.respond_to?(:email)
44
+
45
+ # Lazy hack: These database fields are required if +authenticable+/+confirmable+
46
+ # module(s) is used. Could be avoided with :null => true for authenticatable
47
+ # migration, but keeping this to avoid unnecessary problems.
48
+ self.password_salt = '' if self.respond_to?(:password_salt)
49
+ self.encrypted_password = '' if self.respond_to?(:encrypted_password)
50
+ end
51
+
52
+ # Checks if RPX connected.
53
+ #
54
+ def rpx_connected?
55
+ self.send(:"#{self.class.rpx_identifier_field}").present?
56
+ end
57
+ alias :is_rpx_connected? :rpx_connected?
58
+
59
+ # Hook that gets called *before* connect (each time). Useful for
60
+ # fetching additional user info (etc.) from RPX.
61
+ #
62
+ # Default: Do nothing.
63
+ #
64
+ # == Examples:
65
+ #
66
+ # # Overridden in RPX connectable model, e.g. "User".
67
+ # #
68
+ # def before_rpx_connect(rpx_user)
69
+ #
70
+ # # Get email (if the provider supports it)
71
+ # email = rpx_user["email"]
72
+ # # etc...
73
+ #
74
+ # end
75
+ #
76
+ # == For more info:
77
+ #
78
+ # * http://github.com/grosser/rpx_now
79
+ #
80
+ def on_before_rpx_connect(rpx_user)
81
+ if self.respond_to?(:before_rpx_connect)
82
+ self.send(:before_rpx_connect, rpx_user) rescue nil
83
+ end
84
+ end
85
+
86
+ # Hook that gets called *after* connect (each time). Useful for
87
+ # fetching additional user info (etc.) from RPX.
88
+ #
89
+ # Default: Do nothing.
90
+ #
91
+ # == Example:
92
+ #
93
+ # # Overridden in RPX connectable model, e.g. "User".
94
+ # #
95
+ # def after_rpx_connect(rpx_user)
96
+ # # See "on_before_rpx_connect" example.
97
+ # end
98
+ #
99
+ def on_after_rpx_connect(rpx_user)
100
+ if self.respond_to?(:after_rpx_connect)
101
+ self.send(:after_rpx_connect, rpx_user) rescue nil
102
+ end
103
+ end
104
+
105
+ module ClassMethods
106
+
107
+ # Configuration params accessible within +Devise.setup+ procedure (in initalizer).
108
+ #
109
+ # == Example:
110
+ #
111
+ # Devise.setup do |config|
112
+ # config.rpx_identifier_field = :rpx_identifier
113
+ # config.rpx_auto_create_account = true
114
+ # end
115
+ #
116
+ ::Devise::Models.config(self,
117
+ :rpx_identifier_field,
118
+ :rpx_auto_create_account
119
+ )
120
+
121
+ # Alias don't work for some reason, so...a more Ruby-ish alias
122
+ # for +rpx_auto_create_account+.
123
+ #
124
+ def rpx_auto_create_account?
125
+ self.rpx_auto_create_account
126
+ end
127
+
128
+ # Authenticate a user based on RPX Identifier.
129
+ #
130
+ def authenticate_with_rpx(attributes = {})
131
+ if attributes[:identifier].present?
132
+ self.find_for_rpx(attributes[:identifier])
133
+ end
134
+ end
135
+
136
+ protected
137
+
138
+ # Find first record based on conditions given (RPX identifier).
139
+ # Overwrite to add customized conditions, create a join, or maybe use a
140
+ # namedscope to filter records while authenticating.
141
+ #
142
+ def find_for_rpx(identifier)
143
+ self.first(:conditions => { rpx_identifier_field => identifier })
144
+ end
145
+
146
+ # Contains the logic used in authentication. Overwritten by other devise modules.
147
+ # In the RPX connect case; nothing fancy required.
148
+ #
149
+ def valid_for_rpx(resource, attributes)
150
+ true
151
+ end
152
+
153
+ end
154
+
155
+ end
156
+ end
157
+ end
@@ -0,0 +1,21 @@
1
+ # encoding: utf-8
2
+ require 'devise/schema'
3
+
4
+ module Devise #:nodoc:
5
+ module RpxConnectable #:nodoc:
6
+
7
+ module Schema
8
+
9
+ # Database migration schema for RPX.
10
+ #
11
+ def rpx_connectable
12
+ apply_schema ::Devise.rpx_identifier_field, String, :limit => 255
13
+ end
14
+
15
+ end
16
+ end
17
+ end
18
+
19
+ Devise::Schema.module_eval do
20
+ include ::Devise::RpxConnectable::Schema
21
+ end
@@ -0,0 +1,61 @@
1
+ # encoding: utf-8
2
+ require 'devise/strategies/base'
3
+
4
+ module Devise #:nodoc:
5
+ module RpxConnectable #:nodoc:
6
+ module Strategies #:nodoc:
7
+
8
+ # Default strategy for signing in a user using RPX.
9
+ # Redirects to sign_in page if it's not authenticated
10
+ #
11
+ class RpxConnectable < ::Devise::Strategies::Base
12
+
13
+ def valid?
14
+ valid_controller? && valid_params? && mapping.to.respond_to?('authenticate_with_rpx')
15
+ end
16
+
17
+ # Authenticate user with RPX.
18
+ #
19
+ def authenticate!
20
+ klass = mapping.to
21
+ begin
22
+
23
+ rpx_user = (RPXNow.user_data(params[:token]) rescue nil)
24
+
25
+ if rpx_user && user = klass.authenticate_with_rpx(:identifier => rpx_user["identifier"])
26
+ success!(user)
27
+ else
28
+ if klass.rpx_auto_create_account?
29
+ user = returning(klass.new) do |u|
30
+ u.store_rpx_credentials!(rpx_user)
31
+ end
32
+ begin
33
+ user.save(false)
34
+ success!(user)
35
+ rescue
36
+ fail!(:rpx_invalid)
37
+ end
38
+ else
39
+ fail!(:rpx_invalid)
40
+ end
41
+ end
42
+ rescue => e
43
+ fail!(e.message)
44
+ end
45
+ end
46
+
47
+ protected
48
+ def valid_controller?
49
+ params[:controller] == 'sessions'
50
+ end
51
+
52
+ def valid_params?
53
+ params[:token].present?
54
+ end
55
+
56
+ end
57
+ end
58
+ end
59
+ end
60
+
61
+ Warden::Strategies.add(:rpx_connectable, Devise::RpxConnectable::Strategies::RpxConnectable)
@@ -0,0 +1,5 @@
1
+ module Devise
2
+ module RpxConnectable
3
+ VERSION = "0.1.0".freeze
4
+ end
5
+ end
@@ -0,0 +1,55 @@
1
+ # encoding: utf-8
2
+ require 'devise/mapping'
3
+
4
+ module Devise #:nodoc:
5
+ module RpxConnectable #:nodoc:
6
+
7
+ # RPX view helpers to easily add the link to the RPX connection popup and also the necessary JS code.
8
+ #
9
+ module Helpers
10
+
11
+ # Creates the link to the RPX connection popup.
12
+ # If you create a link without putting the JS code, the popup will load in a new page.
13
+ # By default the RPX link will be linked to the RPX application name you defined in the configuration.
14
+ # It may be overriden using :application_name if the options.
15
+ # The second parameter is the return URL, it must be absolute (***_url).
16
+ #
17
+ # For example :
18
+ # <%= link_to_rpx "Signin using RPX!", user_session_url %>
19
+ #
20
+ def link_to_rpx(link_text, link_url, options={})
21
+ options = { :unobtrusive => true }.merge(options)
22
+ token_url = build_token_url(link_url)
23
+ out = RPXNow.popup_code(link_text, rpx_application_name_from_options(options), token_url, options)
24
+ out.respond_to?(:html_safe) ? out.html_safe : out
25
+ end
26
+
27
+ # Returns the necessary JS code for the RPX popup.
28
+ # It is recommended to put this code just before the </body> tag of your layout.
29
+ #
30
+ # For example :
31
+ # ...
32
+ # <%= javascript_include_rpx(user_session_url) %>
33
+ # </body>
34
+ # </html>
35
+ #
36
+ def javascript_include_rpx(link_url, options={})
37
+ token_url = build_token_url(link_url)
38
+ out = RPXNow.popup_source(rpx_application_name_from_options(options), token_url, options)
39
+ out.respond_to?(:html_safe) ? out.html_safe : out
40
+ end
41
+
42
+ protected
43
+ def rpx_application_name_from_options(options)
44
+ options[:application_name] ? options.delete(:application_name) : ::Devise.rpx_application_name
45
+ end
46
+
47
+ def build_token_url(return_url)
48
+ "#{return_url}?authenticity_token=#{form_authenticity_token}"
49
+ end
50
+
51
+ end
52
+ end
53
+ end
54
+
55
+ ::ActionView::Base.send :include, Devise::RpxConnectable::Helpers
@@ -0,0 +1,26 @@
1
+ # encoding: utf-8
2
+ require 'devise'
3
+ require 'rpx_now'
4
+
5
+ require 'devise_rpx_connectable/model'
6
+ require 'devise_rpx_connectable/strategy'
7
+ require 'devise_rpx_connectable/schema'
8
+ require 'devise_rpx_connectable/view_helpers'
9
+
10
+ module Devise
11
+ mattr_accessor :rpx_identifier_field
12
+ @@rpx_identifier_field = :rpx_identifier
13
+
14
+ mattr_accessor :rpx_auto_create_account
15
+ @@rpx_auto_create_account = true
16
+
17
+ mattr_accessor :rpx_application_name
18
+ @@rpx_application_name = nil
19
+ end
20
+
21
+ I18n.load_path.unshift File.join(File.dirname(__FILE__), *%w[devise_rpx_connectable locales en.yml])
22
+
23
+ Devise.add_module(:rpx_connectable,
24
+ :strategy => true,
25
+ :controller => :sessions,
26
+ :model => 'devise_rpx_connectable/model')
data/rails/init.rb ADDED
@@ -0,0 +1,2 @@
1
+ # encoding: utf-8
2
+ require 'devise_rpx_connectable'
metadata ADDED
@@ -0,0 +1,84 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: devise_rpx_connectable
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Nicolas Blanco
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2010-04-25 00:00:00 +02:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: devise
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 1.0.6
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: rpx_now
27
+ type: :runtime
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 0.6.19
34
+ version:
35
+ description: Devise << RPX
36
+ email: slainer68@gmail.com
37
+ executables: []
38
+
39
+ extensions: []
40
+
41
+ extra_rdoc_files:
42
+ - README.textile
43
+ files:
44
+ - MIT-LICENSE
45
+ - README.textile
46
+ - Rakefile
47
+ - lib/devise_rpx_connectable.rb
48
+ - lib/devise_rpx_connectable/locales/en.yml
49
+ - lib/devise_rpx_connectable/model.rb
50
+ - lib/devise_rpx_connectable/schema.rb
51
+ - lib/devise_rpx_connectable/strategy.rb
52
+ - lib/devise_rpx_connectable/version.rb
53
+ - lib/devise_rpx_connectable/view_helpers.rb
54
+ - rails/init.rb
55
+ has_rdoc: true
56
+ homepage: http://github.com/slainer68/devise_rpx_connectable
57
+ licenses: []
58
+
59
+ post_install_message:
60
+ rdoc_options:
61
+ - --charset=UTF-8
62
+ require_paths:
63
+ - lib
64
+ required_ruby_version: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: "0"
69
+ version:
70
+ required_rubygems_version: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: "0"
75
+ version:
76
+ requirements: []
77
+
78
+ rubyforge_project:
79
+ rubygems_version: 1.3.5
80
+ signing_key:
81
+ specification_version: 3
82
+ summary: Devise << RPX
83
+ test_files: []
84
+