omniauth-identity 1.0.0.beta1

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/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ /coverage
2
+ /pkg
3
+ /doc
4
+
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format=nested
2
+ --colour
data/Gemfile ADDED
@@ -0,0 +1,11 @@
1
+ source "http://rubygems.org"
2
+
3
+ gemspec
4
+
5
+ group :development, :test do
6
+ gem 'guard'
7
+ gem 'guard-rspec'
8
+ gem 'guard-bundler'
9
+ gem 'growl'
10
+ gem 'rb-fsevent'
11
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,77 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ omniauth-identity (1.0.0.beta1)
5
+ omniauth (= 1.0.0.beta1)
6
+
7
+ GEM
8
+ remote: http://rubygems.org/
9
+ specs:
10
+ activemodel (3.0.10)
11
+ activesupport (= 3.0.10)
12
+ builder (~> 2.1.2)
13
+ i18n (~> 0.5.0)
14
+ activerecord (3.0.10)
15
+ activemodel (= 3.0.10)
16
+ activesupport (= 3.0.10)
17
+ arel (~> 2.0.10)
18
+ tzinfo (~> 0.3.23)
19
+ activesupport (3.0.10)
20
+ arel (2.0.10)
21
+ bcrypt-ruby (2.1.4)
22
+ builder (2.1.2)
23
+ diff-lcs (1.1.3)
24
+ growl (1.0.3)
25
+ guard (0.8.4)
26
+ thor (~> 0.14.6)
27
+ guard-bundler (0.1.3)
28
+ bundler (>= 1.0.0)
29
+ guard (>= 0.2.2)
30
+ guard-rspec (0.4.5)
31
+ guard (>= 0.4.0)
32
+ hashie (1.2.0)
33
+ i18n (0.5.0)
34
+ maruku (0.6.0)
35
+ syntax (>= 1.0.0)
36
+ multi_json (1.0.3)
37
+ omniauth (1.0.0.beta1)
38
+ hashie (~> 1.2)
39
+ rack
40
+ rack (1.3.5)
41
+ rack-test (0.6.1)
42
+ rack (>= 1.0)
43
+ rake (0.9.2)
44
+ rb-fsevent (0.4.3.1)
45
+ rspec (2.6.0)
46
+ rspec-core (~> 2.6.0)
47
+ rspec-expectations (~> 2.6.0)
48
+ rspec-mocks (~> 2.6.0)
49
+ rspec-core (2.6.4)
50
+ rspec-expectations (2.6.0)
51
+ diff-lcs (~> 1.1.2)
52
+ rspec-mocks (2.6.0)
53
+ simplecov (0.5.3)
54
+ multi_json (~> 1.0.3)
55
+ simplecov-html (~> 0.5.3)
56
+ simplecov-html (0.5.3)
57
+ syntax (1.0.0)
58
+ thor (0.14.6)
59
+ tzinfo (0.3.30)
60
+
61
+ PLATFORMS
62
+ ruby
63
+
64
+ DEPENDENCIES
65
+ activerecord (~> 3.0)
66
+ bcrypt-ruby (~> 2.1.4)
67
+ growl
68
+ guard
69
+ guard-bundler
70
+ guard-rspec
71
+ maruku (~> 0.6)
72
+ omniauth-identity!
73
+ rack-test (~> 0.5)
74
+ rake (~> 0.8)
75
+ rb-fsevent
76
+ rspec (~> 2.5)
77
+ simplecov (~> 0.4)
data/Guardfile ADDED
@@ -0,0 +1,10 @@
1
+ guard 'rspec', :version => 2 do
2
+ watch(%r{^spec/.+_spec\.rb$})
3
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
4
+ watch('spec/spec_helper.rb') { "spec" }
5
+ end
6
+
7
+ guard 'bundler' do
8
+ watch('Gemfile')
9
+ watch(/^.+\.gemspec/)
10
+ end
data/README.markdown ADDED
@@ -0,0 +1,90 @@
1
+ # OmniAuth Identity
2
+
3
+ The OmniAuth Identity gem provides a way for applications to utilize a
4
+ traditional login/password based authentication system without the need
5
+ to give up the simple authentication flow provided by OmniAuth. Identity
6
+ is designed on purpose to be as featureless as possible: it provides the
7
+ basic construct for user management and then gets out of the way.
8
+
9
+ ## Usage
10
+
11
+ You use `oa-identity` just like you would any other OmniAuth provider: as a
12
+ Rack middleware. The basic setup for a email/password authentication would
13
+ look something like this:
14
+
15
+ use OmniAuth::Builder do
16
+ provider :identity, :fields => [:email]
17
+ end
18
+
19
+ Next, you need to create a model (called `Identity by default`) that will be
20
+ able to persist the information provided by the user. Luckily for you, there
21
+ are pre-built models for popular ORMs that make this dead simple. You just
22
+ need to subclass the relevant class:
23
+
24
+ class Identity < OmniAuth::Identity::Models::ActiveRecord
25
+ # Add whatever you like!
26
+ end
27
+
28
+ Adapters are provided for `ActiveRecord` and `MongoMapper` and are
29
+ autoloaded on request (but not loaded by default so no dependencies are
30
+ injected).
31
+
32
+ Once you've got an Identity persistence model and the strategy up and
33
+ running, you can point users to `/auth/identity` and it will request
34
+ that they log in or give them the opportunity to sign up for an account.
35
+ Once they have authenticated with their identity, OmniAuth will call
36
+ through to `/auth/identity/callback` with the same kinds of information
37
+ it would had the user authenticated through an external provider.
38
+ Simple!
39
+
40
+ ## Custom Auth Model
41
+
42
+ To use a class other than the default, specify the <tt>:model</tt> option to a
43
+ different class.
44
+
45
+ use OmniAuth::Builder do
46
+ provider :identity, :fields => [:email], :model => MyCustomClass
47
+ end
48
+
49
+ ## Customizing Registration Failure
50
+
51
+ To use your own custom registration form, create a form that POSTs to
52
+ '/auth/identity/register' with 'password', 'password_confirmation', and your
53
+ other fields.
54
+
55
+ <%= form_tag '/auth/identity/register' do |f| %>
56
+ <h1>Create an Account</h1>
57
+ <%= text_field_tag :email %>
58
+ <%= password_field_tag, :password %>
59
+ <%= password_field_tag, :password_confirmation %>
60
+ <%= submit_tag %>
61
+ <% end %>
62
+
63
+ Beware not to nest your form parameters within a namespace. This strategy
64
+ looks for the form parameters at the top level of the post params. If you are
65
+ using [simple\_form](https://github.com/plataformatec/simple_form), then you
66
+ can avoid the params nesting by specifying <tt>:input_html</tt>.
67
+
68
+ <%= simple_form_for @identity, :url => '/auth/identity/register' do |f| %>
69
+ <h1>Create an Account</h1>
70
+ <%# specify :input_html to avoid params nesting %>
71
+ <%= f.input :email, :input_html => {:name => 'email'} %>
72
+ <%= f.input :password, :as => 'password', :input_html => {:name => 'password'} %>
73
+ <%= f.input :password_confirmation, :label => "Confirm Password", :as => 'password', :input_html => {:name => 'password_confirmation'} %>
74
+ <button type='submit'>Sign Up</button>
75
+ <% end %>
76
+
77
+ Next you'll need to let OmniAuth know what action to call when a registration
78
+ fails. In your OmniAuth configuration, specify any valid rack endpoint in the
79
+ <tt>:on_failed_registration</tt> option.
80
+
81
+ use OmniAuth::Builder do
82
+ provider :identity,
83
+ :fields => [:email],
84
+ :on_failed_registration => UsersController.action(:new)
85
+ end
86
+
87
+ For more information on rack endpoints, check out [this
88
+ introduction](http://library.edgecase.com/Rails/2011/01/04/rails-routing-and-rack-endpoints.html)
89
+ and
90
+ [ActionController::Metal](http://rubydoc.info/docs/rails/ActionController/Metal)
data/Rakefile ADDED
@@ -0,0 +1,9 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require 'rspec/core/rake_task'
5
+ desc "Run specs."
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ task :default => :spec
9
+ task :test => :spec
@@ -0,0 +1,115 @@
1
+ module OmniAuth
2
+ module Identity
3
+ # This module provides an includable interface for implementing the
4
+ # necessary API for OmniAuth Identity to properly locate identities
5
+ # and provide all necessary information. All methods marked as
6
+ # abstract must be implemented in the including class for things to
7
+ # work properly.
8
+ module Model
9
+ def self.included(base)
10
+ base.extend ClassMethods
11
+ end
12
+
13
+ module ClassMethods
14
+ # Locate an identity given its unique login key.
15
+ #
16
+ # @abstract
17
+ # @param [String] key The unique login key.
18
+ # @return [Model] An instance of the identity model class.
19
+ def locate(key)
20
+ raise NotImplementedError
21
+ end
22
+
23
+ # Authenticate a user with the given key and password.
24
+ #
25
+ # @param [String] key The unique login key provided for a given identity.
26
+ # @param [String] password The presumed password for the identity.
27
+ # @return [Model] An instance of the identity model class.
28
+ def authenticate(key, password)
29
+ instance = locate(key)
30
+ return false unless instance
31
+ instance.authenticate(password)
32
+ end
33
+
34
+ # Used to set or retrieve the method that will be used to get
35
+ # and set the user-supplied authentication key.
36
+ # @return [String] The method name.
37
+ def auth_key(method = false)
38
+ @auth_key = method.to_s unless method == false
39
+ @auth_key = nil if @auth_key == ''
40
+
41
+ @auth_key || 'email'
42
+ end
43
+ end
44
+
45
+ # Returns self if the provided password is correct, false
46
+ # otherwise.
47
+ #
48
+ # @abstract
49
+ # @param [String] password The password to check.
50
+ # @return [self or false] Self if authenticated, false if not.
51
+ def authenticate(password)
52
+ raise NotImplementedError
53
+ end
54
+
55
+ SCHEMA_ATTRIBUTES = %w(name email nickname first_name last_name location description image phone)
56
+ # A hash of as much of the standard OmniAuth schema as is stored
57
+ # in this particular model. By default, this will call instance
58
+ # methods for each of the attributes it needs in turn, ignoring
59
+ # any for which `#respond_to?` is `false`.
60
+ #
61
+ # If `first_name`, `nickname`, and/or `last_name` is provided but
62
+ # `name` is not, it will be automatically calculated.
63
+ #
64
+ # @return [Hash] A string-keyed hash of user information.
65
+ def info
66
+ info = SCHEMA_ATTRIBUTES.inject({}) do |hash,attribute|
67
+ hash[attribute] = send(attribute) if respond_to?(attribute)
68
+ hash
69
+ end
70
+ info
71
+ end
72
+
73
+ # An identifying string that must be globally unique to the
74
+ # application. Defaults to stringifying the `id` method.
75
+ #
76
+ # @return [String] An identifier string unique to this identity.
77
+ def uid
78
+ if respond_to?('id')
79
+ return nil if self.id.nil?
80
+ self.id.to_s
81
+ else
82
+ raise NotImplementedError
83
+ end
84
+ end
85
+
86
+ # Used to retrieve the user-supplied authentication key (e.g. a
87
+ # username or email). Determined using the class method of the same name,
88
+ # defaults to `:email`.
89
+ #
90
+ # @return [String] An identifying string that will be entered by
91
+ # users upon sign in.
92
+ def auth_key
93
+ if respond_to?(self.class.auth_key)
94
+ send(self.class.auth_key)
95
+ else
96
+ raise NotImplementedError
97
+ end
98
+ end
99
+
100
+ # Used to set the user-supplied authentication key (e.g. a
101
+ # username or email. Determined using the `.auth_key` class
102
+ # method.
103
+ #
104
+ # @param [String] value The value to which the auth key should be
105
+ # set.
106
+ def auth_key=(value)
107
+ if respond_to?(self.class.auth_key + '=')
108
+ send(self.class.auth_key + '=', value)
109
+ else
110
+ raise NotImplementedError
111
+ end
112
+ end
113
+ end
114
+ end
115
+ end
@@ -0,0 +1,24 @@
1
+ require 'active_record'
2
+
3
+ module OmniAuth
4
+ module Identity
5
+ module Models
6
+ class ActiveRecord < ::ActiveRecord::Base
7
+ include OmniAuth::Identity::Model
8
+ include OmniAuth::Identity::SecurePassword
9
+
10
+ self.abstract_class = true
11
+ has_secure_password
12
+
13
+ def self.auth_key=(key)
14
+ super
15
+ validates_uniqueness_of key, :case_sensitive => false
16
+ end
17
+
18
+ def self.locate(key)
19
+ where(auth_key => key).first
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,78 @@
1
+ require 'bcrypt'
2
+
3
+ module OmniAuth
4
+ module Identity
5
+ # This is taken directly from Rails 3.1 code and is used if
6
+ # the version of ActiveModel that's being used does not
7
+ # include SecurePassword. The only difference is that instead of
8
+ # using ActiveSupport::Concern, it checks to see if there is already
9
+ # a has_secure_password method.
10
+ module SecurePassword
11
+ def self.included(base)
12
+ unless base.respond_to?(:has_secure_password)
13
+ base.extend ClassMethods
14
+ end
15
+ end
16
+
17
+ module ClassMethods
18
+ # Adds methods to set and authenticate against a BCrypt password.
19
+ # This mechanism requires you to have a password_digest attribute.
20
+ #
21
+ # Validations for presence of password, confirmation of password (using
22
+ # a "password_confirmation" attribute) are automatically added.
23
+ # You can add more validations by hand if need be.
24
+ #
25
+ # Example using Active Record (which automatically includes ActiveModel::SecurePassword):
26
+ #
27
+ # # Schema: User(name:string, password_digest:string)
28
+ # class User < ActiveRecord::Base
29
+ # has_secure_password
30
+ # end
31
+ #
32
+ # user = User.new(:name => "david", :password => "", :password_confirmation => "nomatch")
33
+ # user.save # => false, password required
34
+ # user.password = "mUc3m00RsqyRe"
35
+ # user.save # => false, confirmation doesn't match
36
+ # user.password_confirmation = "mUc3m00RsqyRe"
37
+ # user.save # => true
38
+ # user.authenticate("notright") # => false
39
+ # user.authenticate("mUc3m00RsqyRe") # => user
40
+ # User.find_by_name("david").try(:authenticate, "notright") # => nil
41
+ # User.find_by_name("david").try(:authenticate, "mUc3m00RsqyRe") # => user
42
+ def has_secure_password
43
+ attr_reader :password
44
+
45
+ validates_confirmation_of :password
46
+ validates_presence_of :password_digest
47
+
48
+ include InstanceMethodsOnActivation
49
+
50
+ if respond_to?(:attributes_protected_by_default)
51
+ def self.attributes_protected_by_default
52
+ super + ['password_digest']
53
+ end
54
+ end
55
+ end
56
+ end
57
+
58
+ module InstanceMethodsOnActivation
59
+ # Returns self if the password is correct, otherwise false.
60
+ def authenticate(unencrypted_password)
61
+ if BCrypt::Password.new(password_digest) == unencrypted_password
62
+ self
63
+ else
64
+ false
65
+ end
66
+ end
67
+
68
+ # Encrypts the password into the password_digest attribute.
69
+ def password=(unencrypted_password)
70
+ @password = unencrypted_password
71
+ unless unencrypted_password.blank?
72
+ self.password_digest = BCrypt::Password.create(unencrypted_password)
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,17 @@
1
+ require 'omniauth'
2
+
3
+ module OmniAuth
4
+ module Strategies
5
+ autoload :Identity, 'omniauth/strategies/identity'
6
+ end
7
+
8
+ module Identity
9
+ autoload :Model, 'omniauth/identity/model'
10
+ autoload :SecurePassword, 'omniauth/identity/secure_password'
11
+ module Models
12
+ autoload :ActiveRecord, 'omniauth/identity/models/active_record'
13
+ # autoload :MongoMapper, 'omniauth/identity/models/mongo_mapper'
14
+ # autoload :Mongoid, 'omniauth/identity/models/mongoid'
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,86 @@
1
+ module OmniAuth
2
+ module Strategies
3
+ # The identity strategy allows you to provide simple internal
4
+ # user authentication using the same process flow that you
5
+ # use for external OmniAuth providers.
6
+ class Identity
7
+ include OmniAuth::Strategy
8
+
9
+ option :fields, [:name, :email]
10
+ option :on_failed_registration, nil
11
+
12
+ def request_phase
13
+ OmniAuth::Form.build(
14
+ :title => (options[:title] || "Identity Verification"),
15
+ :url => callback_path
16
+ ) do |f|
17
+ f.text_field 'Login', 'auth_key'
18
+ f.password_field 'Password', 'password'
19
+ f.html "<p align='center'><a href='#{registration_path}'>Create an Identity</a></p>"
20
+ end.to_response
21
+ end
22
+
23
+ def callback_phase
24
+ return fail!(:invalid_credentials) unless identity
25
+ super
26
+ end
27
+
28
+ def other_phase
29
+ if on_registration_path?
30
+ if request.get?
31
+ registration_form
32
+ elsif request.post?
33
+ registration_phase
34
+ end
35
+ else
36
+ call_app!
37
+ end
38
+ end
39
+
40
+ def registration_form
41
+ OmniAuth::Form.build(:title => 'Register Identity') do |f|
42
+ options[:fields].each do |field|
43
+ f.text_field field.to_s.capitalize, field.to_s
44
+ end
45
+ f.password_field 'Password', 'password'
46
+ f.password_field 'Confirm Password', 'password_confirmation'
47
+ end.to_response
48
+ end
49
+
50
+ def registration_phase
51
+ attributes = (options[:fields] + [:password, :password_confirmation]).inject({}){|h,k| h[k] = request[k.to_s]; h}
52
+ @identity = model.create(attributes)
53
+ if @identity.persisted?
54
+ env['PATH_INFO'] = callback_path
55
+ callback_phase
56
+ else
57
+ if options[:on_failed_registration]
58
+ self.env['omniauth.identity'] = @identity
59
+ options[:on_failed_registration].call(self.env)
60
+ else
61
+ registration_form
62
+ end
63
+ end
64
+ end
65
+
66
+ uid{ identity.uid }
67
+ info{ identity.info }
68
+
69
+ def registration_path
70
+ options[:registration_path] || "#{path_prefix}/#{name}/register"
71
+ end
72
+
73
+ def on_registration_path?
74
+ on_path?(registration_path)
75
+ end
76
+
77
+ def identity
78
+ @identity ||= model.authenticate(request['auth_key'], request['password'])
79
+ end
80
+
81
+ def model
82
+ options[:model] || ::Identity
83
+ end
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,5 @@
1
+ module OmniAuth
2
+ module Identity
3
+ VERSION = '1.0.0.beta1'
4
+ end
5
+ end
@@ -0,0 +1,2 @@
1
+ require 'omniauth-identity/version'
2
+ require 'omniauth/identity'
@@ -0,0 +1,27 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.dirname(__FILE__) + '/lib/omniauth-identity/version'
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.add_runtime_dependency 'omniauth', '1.0.0.beta1'
6
+
7
+ gem.add_development_dependency 'maruku', '~> 0.6'
8
+ gem.add_development_dependency 'simplecov', '~> 0.4'
9
+ gem.add_development_dependency 'rack-test', '~> 0.5'
10
+ gem.add_development_dependency 'rake', '~> 0.8'
11
+ gem.add_development_dependency 'rspec', '~> 2.5'
12
+ gem.add_development_dependency 'bcrypt-ruby', '~> 2.1.4'
13
+ gem.add_development_dependency 'activerecord', '~> 3.0'
14
+
15
+ gem.name = 'omniauth-identity'
16
+ gem.version = OmniAuth::Identity::VERSION
17
+ gem.description = %q{Internal authentication handlers for OmniAuth.}
18
+ gem.summary = gem.description
19
+ gem.email = ['michael@intridea.com']
20
+ gem.homepage = 'http://github.com/intridea/omniauth-identity'
21
+ gem.authors = ['Michael Bleigh']
22
+ gem.executables = `git ls-files -- bin/*`.split("\n").map{|f| File.basename(f)}
23
+ gem.files = `git ls-files`.split("\n")
24
+ gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
25
+ gem.require_paths = ['lib']
26
+ gem.required_rubygems_version = Gem::Requirement.new('>= 1.3.6') if gem.respond_to? :required_rubygems_version=
27
+ end
@@ -0,0 +1,117 @@
1
+ require 'spec_helper'
2
+
3
+ class ExampleModel
4
+ include OmniAuth::Identity::Model
5
+ end
6
+
7
+ describe OmniAuth::Identity::Model do
8
+ context 'Class Methods' do
9
+ subject{ ExampleModel }
10
+
11
+ describe '.locate' do
12
+ it('should be abstract'){ lambda{ subject.locate('abc') }.should raise_error(NotImplementedError) }
13
+ end
14
+
15
+ describe '.authenticate' do
16
+ it 'should call locate and then authenticate' do
17
+ mocked_instance = mock('ExampleModel', :authenticate => 'abbadoo')
18
+ subject.should_receive(:locate).with('example').and_return(mocked_instance)
19
+ subject.authenticate('example','pass').should == 'abbadoo'
20
+ end
21
+
22
+ it 'should recover gracefully if locate is nil' do
23
+ subject.stub!(:locate).and_return(nil)
24
+ subject.authenticate('blah','foo').should be_false
25
+ end
26
+ end
27
+ end
28
+
29
+ context 'Instance Methods' do
30
+ subject{ ExampleModel.new }
31
+
32
+ describe '#authenticate' do
33
+ it('should be abstract'){ lambda{ subject.authenticate('abc') }.should raise_error(NotImplementedError) }
34
+ end
35
+
36
+ describe '#uid' do
37
+ it 'should default to #id' do
38
+ subject.should_receive(:respond_to?).with('id').and_return(true)
39
+ subject.stub!(:id).and_return 'wakka-do'
40
+ subject.uid.should == 'wakka-do'
41
+ end
42
+
43
+ it 'should stringify it' do
44
+ subject.stub!(:id).and_return 123
45
+ subject.uid.should == '123'
46
+ end
47
+
48
+ it 'should raise NotImplementedError if #id is not defined' do
49
+ subject.should_receive(:respond_to?).with('id').and_return(false)
50
+ lambda{ subject.uid }.should raise_error(NotImplementedError)
51
+ end
52
+ end
53
+
54
+ describe '#auth_key' do
55
+ it 'should default to #email' do
56
+ subject.should_receive(:respond_to?).with('email').and_return(true)
57
+ subject.stub!(:email).and_return('bob@bob.com')
58
+ subject.auth_key.should == 'bob@bob.com'
59
+ end
60
+
61
+ it 'should use the class .auth_key' do
62
+ subject.class.auth_key 'login'
63
+ subject.stub!(:login).and_return 'bob'
64
+ subject.auth_key.should == 'bob'
65
+ subject.class.auth_key nil
66
+ end
67
+
68
+ it 'should raise a NotImplementedError if the auth_key method is not defined' do
69
+ lambda{ subject.auth_key }.should raise_error(NotImplementedError)
70
+ end
71
+ end
72
+
73
+ describe '#auth_key=' do
74
+ it 'should default to setting email' do
75
+ subject.should_receive(:respond_to?).with('email=').and_return(true)
76
+ subject.should_receive(:email=).with 'abc'
77
+
78
+ subject.auth_key = 'abc'
79
+ end
80
+
81
+ it 'should use a custom .auth_key if one is provided' do
82
+ subject.class.auth_key 'login'
83
+ subject.should_receive(:respond_to?).with('login=').and_return(true)
84
+ subject.should_receive('login=').with('abc')
85
+
86
+ subject.auth_key = 'abc'
87
+ end
88
+
89
+ it 'should raise a NotImplementedError if the autH_key method is not defined' do
90
+ lambda{ subject.auth_key = 'broken' }.should raise_error(NotImplementedError)
91
+ end
92
+ end
93
+
94
+ describe '#info' do
95
+ it 'should include attributes that are set' do
96
+ subject.stub!(:name).and_return('Bob Bobson')
97
+ subject.stub!(:nickname).and_return('bob')
98
+
99
+ subject.info.should == {
100
+ 'name' => 'Bob Bobson',
101
+ 'nickname' => 'bob'
102
+ }
103
+ end
104
+
105
+ it 'should automatically set name off of nickname' do
106
+ subject.stub!(:nickname).and_return('bob')
107
+ subject.info['name'] == 'bob'
108
+ end
109
+
110
+ it 'should not overwrite a provided name' do
111
+ subject.stub!(:name).and_return('Awesome Dude')
112
+ subject.stub!(:first_name).and_return('Frank')
113
+ subject.info['name'].should == 'Awesome Dude'
114
+ end
115
+ end
116
+ end
117
+ end
@@ -0,0 +1,16 @@
1
+ require 'spec_helper'
2
+
3
+ describe(OmniAuth::Identity::Models::ActiveRecord, :db => true) do
4
+ class TestIdentity < OmniAuth::Identity::Models::ActiveRecord
5
+ auth_key :ham_sandwich
6
+ end
7
+
8
+ it 'should locate using the auth key using a where query' do
9
+ TestIdentity.should_receive(:where).with('ham_sandwich' => 'open faced').and_return(['wakka'])
10
+ TestIdentity.locate('open faced').should == 'wakka'
11
+ end
12
+
13
+ it 'should not use STI rules for its table name' do
14
+ TestIdentity.table_name.should == 'test_identities'
15
+ end
16
+ end
@@ -0,0 +1,27 @@
1
+ require 'spec_helper'
2
+
3
+ class HasTheMethod
4
+ def self.has_secure_password; end
5
+ end
6
+
7
+ class DoesNotHaveTheMethod
8
+ end
9
+
10
+ describe OmniAuth::Identity::SecurePassword do
11
+ it 'should extend with the class methods if it does not have the method' do
12
+ DoesNotHaveTheMethod.should_receive(:extend).with(OmniAuth::Identity::SecurePassword::ClassMethods)
13
+ DoesNotHaveTheMethod.send(:include, OmniAuth::Identity::SecurePassword)
14
+ end
15
+
16
+ it 'should not extend if the method is already defined' do
17
+ HasTheMethod.should_not_receive(:extend)
18
+ HasTheMethod.send(:include, OmniAuth::Identity::SecurePassword)
19
+ end
20
+
21
+ it 'should respond to has_secure_password afterwards' do
22
+ [HasTheMethod,DoesNotHaveTheMethod].each do |klass|
23
+ klass.send(:include, OmniAuth::Identity::SecurePassword)
24
+ klass.should be_respond_to(:has_secure_password)
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,130 @@
1
+ require 'spec_helper'
2
+
3
+ class MockIdentity; end
4
+
5
+ describe OmniAuth::Strategies::Identity do
6
+ attr_accessor :app
7
+
8
+ let(:auth_hash){ last_response.headers['env']['omniauth.auth'] }
9
+ let(:identity_hash){ last_response.headers['env']['omniauth.identity'] }
10
+
11
+ # customize rack app for testing, if block is given, reverts to default
12
+ # rack app after testing is done
13
+ def set_app!(identity_options = {})
14
+ identity_options = {:model => MockIdentity}.merge(identity_options)
15
+ old_app = self.app
16
+ self.app = Rack::Builder.app do
17
+ use Rack::Session::Cookie
18
+ use OmniAuth::Strategies::Identity, identity_options
19
+ run lambda{|env| [404, {'env' => env}, ["HELLO!"]]}
20
+ end
21
+ if block_given?
22
+ yield
23
+ self.app = old_app
24
+ end
25
+ self.app
26
+ end
27
+
28
+ before(:all) do
29
+ set_app!
30
+ end
31
+
32
+ describe '#request_phase' do
33
+ it 'should display a form' do
34
+ get '/auth/identity'
35
+ last_response.body.should be_include("<form")
36
+ end
37
+ end
38
+
39
+ describe '#callback_phase' do
40
+ let(:user){ mock(:uid => 'user1', :info => {'name' => 'Rockefeller'})}
41
+
42
+ context 'with valid credentials' do
43
+ before do
44
+ MockIdentity.should_receive('authenticate').with('john','awesome').and_return(user)
45
+ post '/auth/identity/callback', :auth_key => 'john', :password => 'awesome'
46
+ end
47
+
48
+ it 'should populate the auth hash' do
49
+ auth_hash.should be_kind_of(Hash)
50
+ end
51
+
52
+ it 'should populate the uid' do
53
+ auth_hash['uid'].should == 'user1'
54
+ end
55
+
56
+ it 'should populate the info hash' do
57
+ auth_hash['info'].should == {'name' => 'Rockefeller'}
58
+ end
59
+ end
60
+
61
+ context 'with invalid credentials' do
62
+ before do
63
+ OmniAuth.config.on_failure = lambda{|env| [401, {}, [env['omniauth.error.type'].inspect]]}
64
+ MockIdentity.should_receive(:authenticate).with('wrong','login').and_return(false)
65
+ post '/auth/identity/callback', :auth_key => 'wrong', :password => 'login'
66
+ end
67
+
68
+ it 'should fail with :invalid_credentials' do
69
+ last_response.body.should == ':invalid_credentials'
70
+ end
71
+ end
72
+ end
73
+
74
+ describe '#registration_form' do
75
+ it 'should trigger from /auth/identity/register by default' do
76
+ get '/auth/identity/register'
77
+ last_response.body.should be_include("Register Identity")
78
+ end
79
+ end
80
+
81
+ describe '#registration_phase' do
82
+ context 'with successful creation' do
83
+ let(:properties){ {
84
+ :name => 'Awesome Dude',
85
+ :email => 'awesome@example.com',
86
+ :password => 'face',
87
+ :password_confirmation => 'face'
88
+ } }
89
+
90
+ before do
91
+ m = mock(:uid => 'abc', :name => 'Awesome Dude', :email => 'awesome@example.com', :info => {:name => 'DUUUUDE!'}, :persisted? => true)
92
+ MockIdentity.should_receive(:create).with(properties).and_return(m)
93
+ end
94
+
95
+ it 'should set the auth hash' do
96
+ post '/auth/identity/register', properties
97
+ auth_hash['uid'].should == 'abc'
98
+ end
99
+ end
100
+
101
+ context 'with invalid identity' do
102
+ let(:properties) { {
103
+ :name => 'Awesome Dude',
104
+ :email => 'awesome@example.com',
105
+ :password => 'NOT',
106
+ :password_confirmation => 'MATCHING'
107
+ } }
108
+
109
+ before do
110
+ MockIdentity.should_receive(:create).with(properties).and_return(mock(:persisted? => false))
111
+ end
112
+
113
+ context 'default' do
114
+ it 'should show registration form' do
115
+ post '/auth/identity/register', properties
116
+ last_response.body.should be_include("Register Identity")
117
+ end
118
+ end
119
+
120
+ context 'custom on_failed_registration endpoint' do
121
+ it 'should set the identity hash' do
122
+ set_app!(:on_failed_registration => lambda{|env| [404, {'env' => env}, ["HELLO!"]]}) do
123
+ post '/auth/identity/register', properties
124
+ identity_hash.should_not be_nil
125
+ end
126
+ end
127
+ end
128
+ end
129
+ end
130
+ end
@@ -0,0 +1,14 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ Bundler.setup :default, :development, :test
4
+
5
+ require 'simplecov'
6
+ SimpleCov.start
7
+
8
+ require 'rack/test'
9
+ require 'omniauth/identity'
10
+
11
+ RSpec.configure do |config|
12
+ config.include Rack::Test::Methods
13
+ end
14
+
metadata ADDED
@@ -0,0 +1,158 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: omniauth-identity
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0.beta1
5
+ prerelease: 6
6
+ platform: ruby
7
+ authors:
8
+ - Michael Bleigh
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-10-19 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: omniauth
16
+ requirement: &70239729775760 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - =
20
+ - !ruby/object:Gem::Version
21
+ version: 1.0.0.beta1
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *70239729775760
25
+ - !ruby/object:Gem::Dependency
26
+ name: maruku
27
+ requirement: &70239729775260 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ~>
31
+ - !ruby/object:Gem::Version
32
+ version: '0.6'
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: *70239729775260
36
+ - !ruby/object:Gem::Dependency
37
+ name: simplecov
38
+ requirement: &70239729774800 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ~>
42
+ - !ruby/object:Gem::Version
43
+ version: '0.4'
44
+ type: :development
45
+ prerelease: false
46
+ version_requirements: *70239729774800
47
+ - !ruby/object:Gem::Dependency
48
+ name: rack-test
49
+ requirement: &70239729774340 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: '0.5'
55
+ type: :development
56
+ prerelease: false
57
+ version_requirements: *70239729774340
58
+ - !ruby/object:Gem::Dependency
59
+ name: rake
60
+ requirement: &70239729790260 !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ~>
64
+ - !ruby/object:Gem::Version
65
+ version: '0.8'
66
+ type: :development
67
+ prerelease: false
68
+ version_requirements: *70239729790260
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: &70239729789800 !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ~>
75
+ - !ruby/object:Gem::Version
76
+ version: '2.5'
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: *70239729789800
80
+ - !ruby/object:Gem::Dependency
81
+ name: bcrypt-ruby
82
+ requirement: &70239729789340 !ruby/object:Gem::Requirement
83
+ none: false
84
+ requirements:
85
+ - - ~>
86
+ - !ruby/object:Gem::Version
87
+ version: 2.1.4
88
+ type: :development
89
+ prerelease: false
90
+ version_requirements: *70239729789340
91
+ - !ruby/object:Gem::Dependency
92
+ name: activerecord
93
+ requirement: &70239729788880 !ruby/object:Gem::Requirement
94
+ none: false
95
+ requirements:
96
+ - - ~>
97
+ - !ruby/object:Gem::Version
98
+ version: '3.0'
99
+ type: :development
100
+ prerelease: false
101
+ version_requirements: *70239729788880
102
+ description: Internal authentication handlers for OmniAuth.
103
+ email:
104
+ - michael@intridea.com
105
+ executables: []
106
+ extensions: []
107
+ extra_rdoc_files: []
108
+ files:
109
+ - .gitignore
110
+ - .rspec
111
+ - Gemfile
112
+ - Gemfile.lock
113
+ - Guardfile
114
+ - README.markdown
115
+ - Rakefile
116
+ - lib/omniauth-identity.rb
117
+ - lib/omniauth-identity/version.rb
118
+ - lib/omniauth/identity.rb
119
+ - lib/omniauth/identity/model.rb
120
+ - lib/omniauth/identity/models/active_record.rb
121
+ - lib/omniauth/identity/secure_password.rb
122
+ - lib/omniauth/strategies/identity.rb
123
+ - omniauth-identity.gemspec
124
+ - spec/omniauth/identity/model_spec.rb
125
+ - spec/omniauth/identity/models/active_record_spec.rb
126
+ - spec/omniauth/identity/secure_password_spec.rb
127
+ - spec/omniauth/strategies/identity_spec.rb
128
+ - spec/spec_helper.rb
129
+ homepage: http://github.com/intridea/omniauth-identity
130
+ licenses: []
131
+ post_install_message:
132
+ rdoc_options: []
133
+ require_paths:
134
+ - lib
135
+ required_ruby_version: !ruby/object:Gem::Requirement
136
+ none: false
137
+ requirements:
138
+ - - ! '>='
139
+ - !ruby/object:Gem::Version
140
+ version: '0'
141
+ required_rubygems_version: !ruby/object:Gem::Requirement
142
+ none: false
143
+ requirements:
144
+ - - ! '>='
145
+ - !ruby/object:Gem::Version
146
+ version: 1.3.6
147
+ requirements: []
148
+ rubyforge_project:
149
+ rubygems_version: 1.8.10
150
+ signing_key:
151
+ specification_version: 3
152
+ summary: Internal authentication handlers for OmniAuth.
153
+ test_files:
154
+ - spec/omniauth/identity/model_spec.rb
155
+ - spec/omniauth/identity/models/active_record_spec.rb
156
+ - spec/omniauth/identity/secure_password_spec.rb
157
+ - spec/omniauth/strategies/identity_spec.rb
158
+ - spec/spec_helper.rb