sorcery 0.1.1 → 0.2.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/Gemfile +4 -3
- data/Gemfile.lock +16 -13
- data/LICENSE.txt +1 -1
- data/README.rdoc +77 -63
- data/Rakefile +7 -13
- data/VERSION +1 -1
- data/lib/sorcery/controller/submodules/activity_logging.rb +58 -0
- data/lib/sorcery/controller/submodules/brute_force_protection.rb +15 -69
- data/lib/sorcery/controller/submodules/http_basic_auth.rb +65 -0
- data/lib/sorcery/controller/submodules/oauth/oauth1.rb +25 -0
- data/lib/sorcery/controller/submodules/oauth/oauth2.rb +23 -0
- data/lib/sorcery/controller/submodules/oauth/providers/facebook.rb +64 -0
- data/lib/sorcery/controller/submodules/oauth/providers/twitter.rb +61 -0
- data/lib/sorcery/controller/submodules/oauth.rb +95 -0
- data/lib/sorcery/controller/submodules/remember_me.rb +14 -5
- data/lib/sorcery/controller/submodules/session_timeout.rb +10 -2
- data/lib/sorcery/controller.rb +40 -22
- data/lib/sorcery/crypto_providers/bcrypt.rb +3 -7
- data/lib/sorcery/engine.rb +9 -2
- data/lib/sorcery/model/submodules/activity_logging.rb +40 -0
- data/lib/sorcery/model/submodules/brute_force_protection.rb +79 -0
- data/lib/sorcery/model/submodules/oauth.rb +53 -0
- data/lib/sorcery/model/submodules/remember_me.rb +6 -2
- data/lib/sorcery/model/submodules/reset_password.rb +96 -0
- data/lib/sorcery/model/submodules/user_activation.rb +44 -23
- data/lib/sorcery/model/temporary_token.rb +22 -0
- data/lib/sorcery/model.rb +13 -6
- data/lib/sorcery/test_helpers.rb +84 -0
- data/lib/sorcery.rb +17 -1
- data/sorcery.gemspec +85 -41
- data/spec/Gemfile +3 -2
- data/spec/Gemfile.lock +15 -2
- data/spec/rails3/app_root/.rspec +1 -0
- data/spec/rails3/{Gemfile → app_root/Gemfile} +5 -3
- data/spec/rails3/{Gemfile.lock → app_root/Gemfile.lock} +25 -2
- data/spec/rails3/app_root/app/controllers/application_controller.rb +48 -2
- data/spec/rails3/app_root/app/models/authentication.rb +3 -0
- data/spec/rails3/app_root/app/models/user.rb +4 -1
- data/spec/rails3/app_root/config/application.rb +1 -3
- data/spec/rails3/app_root/config/routes.rb +1 -9
- data/spec/rails3/app_root/db/migrate/activation/20101224223622_add_activation_to_users.rb +6 -4
- data/spec/rails3/app_root/db/migrate/activity_logging/20101224223624_add_activity_logging_to_users.rb +17 -0
- data/spec/rails3/app_root/db/migrate/brute_force_protection/20101224223626_add_brute_force_protection_to_users.rb +11 -0
- data/spec/rails3/app_root/db/migrate/core/20101224223620_create_users.rb +4 -4
- data/spec/rails3/app_root/db/migrate/oauth/20101224223628_create_authentications.rb +14 -0
- data/spec/rails3/app_root/db/migrate/reset_password/20101224223622_add_reset_password_to_users.rb +13 -0
- data/spec/rails3/app_root/spec/controller_activity_logging_spec.rb +84 -0
- data/spec/rails3/app_root/spec/controller_brute_force_protection_spec.rb +65 -0
- data/spec/rails3/app_root/spec/controller_http_basic_auth_spec.rb +50 -0
- data/spec/rails3/app_root/spec/controller_oauth2_spec.rb +117 -0
- data/spec/rails3/app_root/spec/controller_oauth_spec.rb +117 -0
- data/spec/rails3/{controller_remember_me_spec.rb → app_root/spec/controller_remember_me_spec.rb} +4 -4
- data/spec/rails3/{controller_session_timeout_spec.rb → app_root/spec/controller_session_timeout_spec.rb} +5 -4
- data/spec/rails3/{controller_spec.rb → app_root/spec/controller_spec.rb} +23 -16
- data/spec/rails3/app_root/spec/spec_helper.orig.rb +27 -0
- data/spec/rails3/app_root/spec/spec_helper.rb +61 -0
- data/spec/rails3/{user_activation_spec.rb → app_root/spec/user_activation_spec.rb} +62 -22
- data/spec/rails3/app_root/spec/user_activity_logging_spec.rb +36 -0
- data/spec/rails3/app_root/spec/user_brute_force_protection_spec.rb +76 -0
- data/spec/rails3/app_root/spec/user_oauth_spec.rb +39 -0
- data/spec/rails3/{user_remember_me_spec.rb → app_root/spec/user_remember_me_spec.rb} +4 -4
- data/spec/rails3/app_root/spec/user_reset_password_spec.rb +178 -0
- data/spec/rails3/{user_spec.rb → app_root/spec/user_spec.rb} +68 -38
- metadata +145 -61
- data/features/support/env.rb +0 -13
- data/lib/sorcery/model/submodules/password_reset.rb +0 -64
- data/spec/rails3/app_root/db/migrate/password_reset/20101224223622_add_password_reset_to_users.rb +0 -9
- data/spec/rails3/app_root/test/fixtures/users.yml +0 -9
- data/spec/rails3/app_root/test/performance/browsing_test.rb +0 -9
- data/spec/rails3/app_root/test/test_helper.rb +0 -13
- data/spec/rails3/app_root/test/unit/user_test.rb +0 -8
- data/spec/rails3/controller_brute_force_protection_spec.rb +0 -72
- data/spec/rails3/spec_helper.rb +0 -115
- data/spec/rails3/user_password_reset_spec.rb +0 -76
- /data/spec/rails3/{Rakefile → app_root/Rakefile} +0 -0
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
module Sorcery
|
|
2
|
-
module Model
|
|
3
|
-
module Submodules
|
|
4
|
-
# This submodule adds the ability to reset password via email confirmation.
|
|
5
|
-
module PasswordReset
|
|
6
|
-
def self.included(base)
|
|
7
|
-
base.sorcery_config.class_eval do
|
|
8
|
-
attr_accessor :reset_password_code_attribute_name, # reset password code attribute name.
|
|
9
|
-
:sorcery_mailer, # mailer class. Needed.
|
|
10
|
-
:reset_password_email_method_name # reset password email method on your mailer class.
|
|
11
|
-
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
base.sorcery_config.instance_eval do
|
|
15
|
-
@defaults.merge!(:@reset_password_code_attribute_name => :reset_password_code,
|
|
16
|
-
:@sorcery_mailer => nil,
|
|
17
|
-
:@reset_password_email_method_name => :reset_password_email)
|
|
18
|
-
|
|
19
|
-
reset!
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
base.class_eval do
|
|
23
|
-
clear_reset_password_code_proc = Proc.new do |record|
|
|
24
|
-
record.valid? && record.send(sorcery_config.password_attribute_name)
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
before_save :clear_reset_password_code, :if =>clear_reset_password_code_proc
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
base.sorcery_config.after_config << :validate_mailer_defined
|
|
31
|
-
|
|
32
|
-
base.extend(ClassMethods)
|
|
33
|
-
base.send(:include, InstanceMethods)
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
module ClassMethods
|
|
37
|
-
def validate_mailer_defined
|
|
38
|
-
msg = "To use password_reset submodule, you must define a mailer (config.sorcery_mailer = YourMailerClass)."
|
|
39
|
-
raise ArgumentError, msg if @sorcery_config.sorcery_mailer == nil
|
|
40
|
-
end
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
module InstanceMethods
|
|
44
|
-
def reset_password!
|
|
45
|
-
config = sorcery_config
|
|
46
|
-
self.send(:"#{config.reset_password_code_attribute_name}=", generate_random_code)
|
|
47
|
-
self.class.transaction do
|
|
48
|
-
self.save!(:validate => false)
|
|
49
|
-
generic_send_email(:reset_password_email_method_name)
|
|
50
|
-
end
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
protected
|
|
54
|
-
|
|
55
|
-
def clear_reset_password_code
|
|
56
|
-
config = sorcery_config
|
|
57
|
-
self.send(:"#{config.reset_password_code_attribute_name}=", nil)
|
|
58
|
-
end
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
end
|
|
62
|
-
end
|
|
63
|
-
end
|
|
64
|
-
end
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
ENV["RAILS_ENV"] = "test"
|
|
2
|
-
require File.expand_path('../../config/environment', __FILE__)
|
|
3
|
-
require 'rails/test_help'
|
|
4
|
-
|
|
5
|
-
class ActiveSupport::TestCase
|
|
6
|
-
# Setup all fixtures in test/fixtures/*.(yml|csv) for all tests in alphabetical order.
|
|
7
|
-
#
|
|
8
|
-
# Note: You'll currently still have to declare fixtures explicitly in integration tests
|
|
9
|
-
# -- they do not yet inherit this setting
|
|
10
|
-
fixtures :all
|
|
11
|
-
|
|
12
|
-
# Add more helper methods to be used by all tests here...
|
|
13
|
-
end
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
|
2
|
-
|
|
3
|
-
describe ApplicationController do
|
|
4
|
-
|
|
5
|
-
# ----------------- SESSION TIMEOUT -----------------------
|
|
6
|
-
describe ApplicationController, "with brute force protection features" do
|
|
7
|
-
before(:all) do
|
|
8
|
-
plugin_model_configure([:brute_force_protection])
|
|
9
|
-
create_new_user
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
after(:each) do
|
|
13
|
-
Sorcery::Controller::Config.reset!
|
|
14
|
-
plugin_set_controller_config_property(:user_class, User)
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
it "should have configuration for 'login_retries_amount_allowed' per session" do
|
|
18
|
-
plugin_set_controller_config_property(:login_retries_amount_allowed, 32)
|
|
19
|
-
Sorcery::Controller::Config.login_retries_amount_allowed.should equal(32)
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
it "should have configuration for 'login_retries_counter_reset_time'" do
|
|
23
|
-
plugin_set_controller_config_property(:login_retries_time_period, 32)
|
|
24
|
-
Sorcery::Controller::Config.login_retries_time_period.should equal(32)
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
it "should count login retries per session" do
|
|
28
|
-
3.times {get :test_login, :username => 'gizmo', :password => 'blabla'}
|
|
29
|
-
session[:failed_logins].should == 3
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
it "should reset the counter if enough time has passed" do
|
|
33
|
-
plugin_set_controller_config_property(:login_retries_amount_allowed, 5)
|
|
34
|
-
plugin_set_controller_config_property(:login_retries_time_period, 0.2)
|
|
35
|
-
get :test_login, :username => 'gizmo', :password => 'blabla'
|
|
36
|
-
sleep 0.4
|
|
37
|
-
get :test_login, :username => 'gizmo', :password => 'blabla'
|
|
38
|
-
session[:failed_logins].should == 1
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
it "should ban session when number of retries reached within an amount of time" do
|
|
42
|
-
plugin_set_controller_config_property(:login_retries_amount_allowed, 1)
|
|
43
|
-
plugin_set_controller_config_property(:login_retries_time_period, 50)
|
|
44
|
-
get :test_login, :username => 'gizmo', :password => 'blabla'
|
|
45
|
-
get :test_login, :username => 'gizmo', :password => 'blabla'
|
|
46
|
-
session[:banned].should == true
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
it "should clear ban after ban time limit passes" do
|
|
50
|
-
plugin_set_controller_config_property(:login_retries_amount_allowed, 1)
|
|
51
|
-
plugin_set_controller_config_property(:login_retries_time_period, 50)
|
|
52
|
-
plugin_set_controller_config_property(:login_ban_time_period, 0.2)
|
|
53
|
-
get :test_login, :username => 'gizmo', :password => 'blabla'
|
|
54
|
-
get :test_login, :username => 'gizmo', :password => 'blabla'
|
|
55
|
-
session[:banned].should == true
|
|
56
|
-
sleep 0.3
|
|
57
|
-
get :test_login, :username => 'gizmo', :password => 'blabla'
|
|
58
|
-
session[:banned].should == nil
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
it "banned session calls the configured banned action" do
|
|
62
|
-
plugin_set_controller_config_property(:login_retries_amount_allowed, 1)
|
|
63
|
-
plugin_set_controller_config_property(:login_retries_time_period, 50)
|
|
64
|
-
plugin_set_controller_config_property(:login_ban_time_period, 50)
|
|
65
|
-
get :test_login, :username => 'gizmo', :password => 'blabla'
|
|
66
|
-
get :test_login, :username => 'gizmo', :password => 'blabla'
|
|
67
|
-
get :test_login, :username => 'gizmo', :password => 'blabla'
|
|
68
|
-
session[:banned].should == true
|
|
69
|
-
response.body.should == " "
|
|
70
|
-
end
|
|
71
|
-
end
|
|
72
|
-
end
|
data/spec/rails3/spec_helper.rb
DELETED
|
@@ -1,115 +0,0 @@
|
|
|
1
|
-
$: << File.join(File.dirname(__FILE__), '..', '..', 'lib' )
|
|
2
|
-
|
|
3
|
-
require 'simplecov'
|
|
4
|
-
SimpleCov.root File.join(File.dirname(__FILE__), "app_root" )
|
|
5
|
-
SimpleCov.start do
|
|
6
|
-
add_filter "/config/"
|
|
7
|
-
|
|
8
|
-
add_group 'Controllers', 'app/controllers'
|
|
9
|
-
add_group 'Models', 'app/models'
|
|
10
|
-
add_group 'Helpers', 'app/helpers'
|
|
11
|
-
add_group 'Libraries', 'lib'
|
|
12
|
-
add_group 'Plugins', 'vendor/plugins'
|
|
13
|
-
add_group 'Migrations', 'db/migrate'
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
# Set the default environment to sqlite3's in_memory database
|
|
17
|
-
ENV['RAILS_ENV'] ||= 'in_memory'
|
|
18
|
-
ENV['RAILS_ROOT'] = 'app_root'
|
|
19
|
-
|
|
20
|
-
# Load the Rails environment and testing framework
|
|
21
|
-
require "#{File.dirname(__FILE__)}/app_root/config/environment"
|
|
22
|
-
#require "#{File.dirname(__FILE__)}/../../init" # for plugins
|
|
23
|
-
require 'rspec/rails'
|
|
24
|
-
#require 'sorcery'
|
|
25
|
-
|
|
26
|
-
# Undo changes to RAILS_ENV
|
|
27
|
-
silence_warnings {RAILS_ENV = ENV['RAILS_ENV']}
|
|
28
|
-
|
|
29
|
-
RSpec.configure do |config|
|
|
30
|
-
config.use_transactional_fixtures = true
|
|
31
|
-
config.use_instantiated_fixtures = false
|
|
32
|
-
config.include RSpec::Rails::ControllerExampleGroup, :example_group => { :file_path => /controller(.)*_spec.rb$/ }#:file_path => /\bspec[\\\/]controllers[\\\/]/ }
|
|
33
|
-
|
|
34
|
-
config.before(:suite) do
|
|
35
|
-
ActiveRecord::Migrator.migrate("#{Rails.root}/db/migrate/core")
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
config.after(:suite) do
|
|
39
|
-
ActiveRecord::Migrator.rollback("#{Rails.root}/db/migrate/core")
|
|
40
|
-
end
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
#----------------------------------------------------------------
|
|
44
|
-
#require File.join(File.dirname(__FILE__), 'app_root','app','models','user')
|
|
45
|
-
|
|
46
|
-
class TestUser < ActiveRecord::Base
|
|
47
|
-
activate_sorcery!
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
class TestMailer < ActionMailer::Base
|
|
51
|
-
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
module Sorcery
|
|
55
|
-
module Model
|
|
56
|
-
module Submodules
|
|
57
|
-
module TestSubmodule
|
|
58
|
-
def my_instance_method
|
|
59
|
-
end
|
|
60
|
-
end
|
|
61
|
-
end
|
|
62
|
-
end
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
def create_new_user
|
|
66
|
-
user_attributes_hash = {:username => 'gizmo', :email => "bla@bla.com", :password => 'secret'}
|
|
67
|
-
@user = User.new(user_attributes_hash)
|
|
68
|
-
@user.save!
|
|
69
|
-
end
|
|
70
|
-
|
|
71
|
-
def login_user
|
|
72
|
-
subject.send(:login_user,@user)
|
|
73
|
-
subject.send(:after_login!,@user,['gizmo','secret'])
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
# TODO: rename to sorcery_reload!(subs = [], model_opts = {}, controller_opts = {})
|
|
77
|
-
def plugin_model_configure(submodules = [], options = {})
|
|
78
|
-
reload_user_class
|
|
79
|
-
|
|
80
|
-
# return to no-module configuration
|
|
81
|
-
::Sorcery::Controller::Config.init!
|
|
82
|
-
::Sorcery::Controller::Config.reset!
|
|
83
|
-
|
|
84
|
-
# configure
|
|
85
|
-
::Sorcery::Controller::Config.submodules = submodules
|
|
86
|
-
::Sorcery::Controller::Config.user_class = nil # the next line will reset it to User
|
|
87
|
-
ApplicationController.send(:include,::Sorcery::Controller)
|
|
88
|
-
|
|
89
|
-
User.activate_sorcery! do |config|
|
|
90
|
-
options.each do |property,value|
|
|
91
|
-
config.send(:"#{property}=", value)
|
|
92
|
-
end
|
|
93
|
-
end
|
|
94
|
-
end
|
|
95
|
-
|
|
96
|
-
# TODO: rename to sorcery_model_property_set(prop, val)
|
|
97
|
-
def plugin_set_model_config_property(property, *values)
|
|
98
|
-
User.class_eval do
|
|
99
|
-
sorcery_config.send(:"#{property}=", *values)
|
|
100
|
-
end
|
|
101
|
-
end
|
|
102
|
-
|
|
103
|
-
# TODO: rename to sorcery_controller_property_set(prop, val)
|
|
104
|
-
def plugin_set_controller_config_property(property, value)
|
|
105
|
-
ApplicationController.activate_sorcery! do |config|
|
|
106
|
-
config.send(:"#{property}=", value)
|
|
107
|
-
end
|
|
108
|
-
end
|
|
109
|
-
|
|
110
|
-
private
|
|
111
|
-
|
|
112
|
-
def reload_user_class
|
|
113
|
-
Object.send(:remove_const,:User)
|
|
114
|
-
load 'user.rb'
|
|
115
|
-
end
|
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
|
2
|
-
|
|
3
|
-
describe "User with password_reset submodule" do
|
|
4
|
-
before(:all) do
|
|
5
|
-
ActiveRecord::Migrator.migrate("#{Rails.root}/db/migrate/password_reset")
|
|
6
|
-
end
|
|
7
|
-
|
|
8
|
-
after(:all) do
|
|
9
|
-
ActiveRecord::Migrator.rollback("#{Rails.root}/db/migrate/password_reset")
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
# ----------------- PLUGIN CONFIGURATION -----------------------
|
|
13
|
-
describe User, "loaded plugin configuration" do
|
|
14
|
-
|
|
15
|
-
before(:all) do
|
|
16
|
-
plugin_model_configure([:password_reset], :sorcery_mailer => ::SorceryMailer)
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
after(:each) do
|
|
20
|
-
User.sorcery_config.reset!
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
it "should respond to 'reset_password!'" do
|
|
24
|
-
create_new_user
|
|
25
|
-
@user.should respond_to(:reset_password!)
|
|
26
|
-
end
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
# ----------------- PLUGIN ACTIVATED -----------------------
|
|
30
|
-
describe User, "when activated with sorcery" do
|
|
31
|
-
|
|
32
|
-
before(:all) do
|
|
33
|
-
plugin_model_configure([:password_reset], :sorcery_mailer => ::SorceryMailer)
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
before(:each) do
|
|
37
|
-
User.delete_all
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
it "'reset_password!' should generate a reset_password_code" do
|
|
41
|
-
create_new_user
|
|
42
|
-
@user.reset_password_code.should be_nil
|
|
43
|
-
@user.reset_password!
|
|
44
|
-
@user.reset_password_code.should_not be_nil
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
it "the reset_password_code should be random" do
|
|
48
|
-
create_new_user
|
|
49
|
-
@user.reset_password!
|
|
50
|
-
old_password_code = @user.reset_password_code
|
|
51
|
-
@user.reset_password!
|
|
52
|
-
@user.reset_password_code.should_not == old_password_code
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
it "should send an email on reset" do
|
|
56
|
-
create_new_user
|
|
57
|
-
old_size = ActionMailer::Base.deliveries.size
|
|
58
|
-
@user.reset_password!
|
|
59
|
-
ActionMailer::Base.deliveries.size.should == old_size + 1
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
it "when a new password is set, should delete reset_password_code" do
|
|
63
|
-
create_new_user
|
|
64
|
-
@user.reset_password!
|
|
65
|
-
@user.reset_password_code.should_not be_nil
|
|
66
|
-
@user.password = "blabulsdf"
|
|
67
|
-
@user.save!
|
|
68
|
-
@user.reset_password_code.should be_nil
|
|
69
|
-
end
|
|
70
|
-
|
|
71
|
-
it "if mailer is nil on activation, throw exception!" do
|
|
72
|
-
expect{plugin_model_configure([:password_reset])}.to raise_error(ArgumentError)
|
|
73
|
-
end
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
end
|
|
File without changes
|