sorcery 0.1.4 → 0.3.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.
Files changed (111) hide show
  1. data/Gemfile +4 -2
  2. data/Gemfile.lock +16 -13
  3. data/README.rdoc +111 -78
  4. data/Rakefile +5 -0
  5. data/VERSION +1 -1
  6. data/lib/generators/sorcery_migration/sorcery_migration_generator.rb +24 -0
  7. data/lib/generators/sorcery_migration/templates/activity_logging.rb +17 -0
  8. data/lib/generators/sorcery_migration/templates/brute_force_protection.rb +11 -0
  9. data/lib/generators/sorcery_migration/templates/core.rb +16 -0
  10. data/lib/generators/sorcery_migration/templates/oauth.rb +14 -0
  11. data/lib/generators/sorcery_migration/templates/remember_me.rb +15 -0
  12. data/lib/generators/sorcery_migration/templates/reset_password.rb +13 -0
  13. data/lib/generators/sorcery_migration/templates/user_activation.rb +17 -0
  14. data/lib/sorcery/controller/adapters/sinatra.rb +97 -0
  15. data/lib/sorcery/controller/submodules/activity_logging.rb +20 -7
  16. data/lib/sorcery/controller/submodules/brute_force_protection.rb +9 -2
  17. data/lib/sorcery/controller/submodules/http_basic_auth.rb +18 -9
  18. data/lib/sorcery/controller/submodules/oauth/oauth1.rb +33 -0
  19. data/lib/sorcery/controller/submodules/oauth/oauth2.rb +24 -0
  20. data/lib/sorcery/controller/submodules/oauth/providers/facebook.rb +64 -0
  21. data/lib/sorcery/controller/submodules/oauth/providers/twitter.rb +61 -0
  22. data/lib/sorcery/controller/submodules/oauth.rb +95 -0
  23. data/lib/sorcery/controller/submodules/remember_me.rb +14 -5
  24. data/lib/sorcery/controller/submodules/session_timeout.rb +6 -1
  25. data/lib/sorcery/controller.rb +29 -17
  26. data/lib/sorcery/engine.rb +9 -2
  27. data/lib/sorcery/model/submodules/activity_logging.rb +13 -8
  28. data/lib/sorcery/model/submodules/brute_force_protection.rb +11 -8
  29. data/lib/sorcery/model/submodules/oauth.rb +53 -0
  30. data/lib/sorcery/model/submodules/remember_me.rb +5 -3
  31. data/lib/sorcery/model/submodules/reset_password.rb +16 -13
  32. data/lib/sorcery/model/submodules/user_activation.rb +38 -19
  33. data/lib/sorcery/model/temporary_token.rb +22 -0
  34. data/lib/sorcery/model.rb +10 -3
  35. data/lib/sorcery/sinatra.rb +14 -0
  36. data/lib/sorcery/test_helpers/rails.rb +57 -0
  37. data/lib/sorcery/test_helpers/sinatra.rb +131 -0
  38. data/lib/sorcery/test_helpers.rb +40 -0
  39. data/lib/sorcery.rb +20 -0
  40. data/sorcery.gemspec +144 -41
  41. data/spec/Gemfile +3 -2
  42. data/spec/Gemfile.lock +15 -2
  43. data/spec/rails3/app_root/.rspec +1 -0
  44. data/spec/rails3/{Gemfile → app_root/Gemfile} +4 -4
  45. data/spec/rails3/{Gemfile.lock → app_root/Gemfile.lock} +23 -3
  46. data/spec/rails3/app_root/app/controllers/application_controller.rb +42 -1
  47. data/spec/rails3/app_root/app/models/authentication.rb +3 -0
  48. data/spec/rails3/app_root/app/models/user.rb +4 -1
  49. data/spec/rails3/app_root/config/application.rb +1 -3
  50. data/spec/rails3/app_root/config/routes.rb +1 -10
  51. data/spec/rails3/app_root/db/migrate/activation/20101224223622_add_activation_to_users.rb +6 -4
  52. data/spec/rails3/app_root/db/migrate/core/20101224223620_create_users.rb +4 -4
  53. data/spec/rails3/app_root/db/migrate/oauth/20101224223628_create_authentications.rb +14 -0
  54. data/spec/rails3/{controller_activity_logging_spec.rb → app_root/spec/controller_activity_logging_spec.rb} +13 -13
  55. data/spec/rails3/{controller_brute_force_protection_spec.rb → app_root/spec/controller_brute_force_protection_spec.rb} +16 -6
  56. data/spec/rails3/{controller_http_basic_auth_spec.rb → app_root/spec/controller_http_basic_auth_spec.rb} +3 -3
  57. data/spec/rails3/app_root/spec/controller_oauth2_spec.rb +119 -0
  58. data/spec/rails3/app_root/spec/controller_oauth_spec.rb +122 -0
  59. data/spec/rails3/{controller_remember_me_spec.rb → app_root/spec/controller_remember_me_spec.rb} +4 -4
  60. data/spec/rails3/{controller_session_timeout_spec.rb → app_root/spec/controller_session_timeout_spec.rb} +6 -6
  61. data/spec/rails3/{controller_spec.rb → app_root/spec/controller_spec.rb} +20 -13
  62. data/spec/rails3/app_root/spec/spec_helper.orig.rb +27 -0
  63. data/spec/rails3/app_root/spec/spec_helper.rb +62 -0
  64. data/spec/rails3/{user_activation_spec.rb → app_root/spec/user_activation_spec.rb} +60 -20
  65. data/spec/rails3/{user_activity_logging_spec.rb → app_root/spec/user_activity_logging_spec.rb} +4 -4
  66. data/spec/rails3/{user_brute_force_protection_spec.rb → app_root/spec/user_brute_force_protection_spec.rb} +7 -7
  67. data/spec/rails3/app_root/spec/user_oauth_spec.rb +39 -0
  68. data/spec/rails3/{user_remember_me_spec.rb → app_root/spec/user_remember_me_spec.rb} +4 -4
  69. data/spec/rails3/{user_reset_password_spec.rb → app_root/spec/user_reset_password_spec.rb} +21 -41
  70. data/spec/rails3/app_root/spec/user_spec.rb +317 -0
  71. data/spec/sinatra/Gemfile +12 -0
  72. data/spec/sinatra/Gemfile.lock +134 -0
  73. data/spec/sinatra/Rakefile +10 -0
  74. data/spec/sinatra/authentication.rb +3 -0
  75. data/spec/sinatra/db/migrate/activation/20101224223622_add_activation_to_users.rb +17 -0
  76. data/spec/sinatra/db/migrate/activity_logging/20101224223624_add_activity_logging_to_users.rb +17 -0
  77. data/spec/sinatra/db/migrate/brute_force_protection/20101224223626_add_brute_force_protection_to_users.rb +11 -0
  78. data/spec/sinatra/db/migrate/core/20101224223620_create_users.rb +16 -0
  79. data/spec/sinatra/db/migrate/oauth/20101224223628_create_authentications.rb +14 -0
  80. data/spec/sinatra/db/migrate/remember_me/20101224223623_add_remember_me_token_to_users.rb +15 -0
  81. data/spec/sinatra/db/migrate/reset_password/20101224223622_add_reset_password_to_users.rb +13 -0
  82. data/spec/sinatra/filters.rb +21 -0
  83. data/spec/sinatra/myapp.rb +133 -0
  84. data/spec/sinatra/sorcery_mailer.rb +25 -0
  85. data/spec/sinatra/spec/controller_activity_logging_spec.rb +85 -0
  86. data/spec/sinatra/spec/controller_brute_force_protection_spec.rb +69 -0
  87. data/spec/sinatra/spec/controller_http_basic_auth_spec.rb +53 -0
  88. data/spec/sinatra/spec/controller_oauth2_spec.rb +119 -0
  89. data/spec/sinatra/spec/controller_oauth_spec.rb +121 -0
  90. data/spec/sinatra/spec/controller_remember_me_spec.rb +64 -0
  91. data/spec/sinatra/spec/controller_session_timeout_spec.rb +52 -0
  92. data/spec/sinatra/spec/controller_spec.rb +120 -0
  93. data/spec/sinatra/spec/spec.opts +4 -0
  94. data/spec/sinatra/spec/spec_helper.rb +44 -0
  95. data/spec/sinatra/spec/user_activation_spec.rb +188 -0
  96. data/spec/sinatra/spec/user_activity_logging_spec.rb +36 -0
  97. data/spec/sinatra/spec/user_brute_force_protection_spec.rb +76 -0
  98. data/spec/sinatra/spec/user_oauth_spec.rb +39 -0
  99. data/spec/sinatra/spec/user_remember_me_spec.rb +66 -0
  100. data/spec/sinatra/spec/user_reset_password_spec.rb +178 -0
  101. data/spec/{rails3 → sinatra/spec}/user_spec.rb +68 -38
  102. data/spec/sinatra/user.rb +6 -0
  103. data/spec/sinatra/views/test_login.erb +4 -0
  104. data/spec/untitled folder +18 -0
  105. metadata +201 -58
  106. data/spec/rails3/app_root/test/fixtures/users.yml +0 -9
  107. data/spec/rails3/app_root/test/performance/browsing_test.rb +0 -9
  108. data/spec/rails3/app_root/test/test_helper.rb +0 -13
  109. data/spec/rails3/app_root/test/unit/user_test.rb +0 -8
  110. data/spec/rails3/spec_helper.rb +0 -135
  111. /data/spec/rails3/{Rakefile → app_root/Rakefile} +0 -0
data/Gemfile CHANGED
@@ -2,11 +2,13 @@ source "http://rubygems.org"
2
2
  # Add dependencies required to use your gem here.
3
3
  # Example:
4
4
  # gem "activesupport", ">= 2.3.5"
5
-
5
+ gem "rails", ">= 3.0.0"
6
+ gem 'json', ">= 1.5.1"
7
+ gem 'oauth', ">= 0.4.4"
8
+ gem 'oauth2', ">= 0.1.1"
6
9
  # Add dependencies to develop your gem here.
7
10
  # Include everything needed to run rake, tests, features, etc.
8
11
  group :development do
9
- gem "rails", ">= 3.0.0"
10
12
  gem "rspec", "~> 2.3.0"
11
13
  gem 'rspec-rails'
12
14
  gem 'ruby-debug19'
data/Gemfile.lock CHANGED
@@ -28,29 +28,25 @@ GEM
28
28
  activemodel (= 3.0.3)
29
29
  activesupport (= 3.0.3)
30
30
  activesupport (3.0.3)
31
+ addressable (2.2.4)
31
32
  archive-tar-minitar (0.5.2)
32
33
  arel (2.0.6)
33
34
  builder (2.1.2)
34
35
  columnize (0.3.2)
35
- cucumber (0.10.0)
36
- builder (>= 2.1.2)
37
- diff-lcs (~> 1.1.2)
38
- gherkin (~> 2.3.2)
39
- json (~> 1.4.6)
40
- term-ansicolor (~> 1.0.5)
41
36
  diff-lcs (1.1.2)
42
37
  erubis (2.6.6)
43
38
  abstract (>= 1.0.0)
44
- gherkin (2.3.2)
45
- json (~> 1.4.6)
46
- term-ansicolor (~> 1.0.5)
39
+ faraday (0.5.5)
40
+ addressable (~> 2.2.4)
41
+ multipart-post (~> 1.1.0)
42
+ rack (< 2, >= 1.1.0)
47
43
  git (1.2.5)
48
44
  i18n (0.5.0)
49
45
  jeweler (1.5.2)
50
46
  bundler (~> 1.0.0)
51
47
  git (>= 1.2.5)
52
48
  rake
53
- json (1.4.6)
49
+ json (1.5.1)
54
50
  linecache19 (0.5.11)
55
51
  ruby_core_source (>= 0.1.4)
56
52
  mail (2.2.13)
@@ -59,6 +55,12 @@ GEM
59
55
  mime-types (~> 1.16)
60
56
  treetop (~> 1.4.8)
61
57
  mime-types (1.16)
58
+ multi_json (0.0.5)
59
+ multipart-post (1.1.0)
60
+ oauth (0.4.4)
61
+ oauth2 (0.1.1)
62
+ faraday (~> 0.5.0)
63
+ multi_json (~> 0.0.4)
62
64
  polyglot (0.3.1)
63
65
  rack (1.2.1)
64
66
  rack-mount (0.6.13)
@@ -106,7 +108,6 @@ GEM
106
108
  simplecov-html (>= 0.3.7)
107
109
  simplecov-html (0.3.9)
108
110
  sqlite3-ruby (1.3.2)
109
- term-ansicolor (1.0.5)
110
111
  thor (0.14.6)
111
112
  treetop (1.4.9)
112
113
  polyglot (>= 0.3.1)
@@ -118,9 +119,11 @@ PLATFORMS
118
119
 
119
120
  DEPENDENCIES
120
121
  bundler (~> 1.0.0)
121
- cucumber
122
122
  jeweler (~> 1.5.2)
123
- rails (= 3.0.3)
123
+ json (>= 1.5.1)
124
+ oauth (>= 0.4.4)
125
+ oauth2 (>= 0.1.1)
126
+ rails (>= 3.0.0)
124
127
  rspec (~> 2.3.0)
125
128
  rspec-rails
126
129
  ruby-debug19
data/README.rdoc CHANGED
@@ -1,30 +1,118 @@
1
1
  = sorcery
2
- Magical Authentication for Rails 3.
2
+ Magical Authentication for Rails 3 and Sinatra.
3
3
 
4
4
  Inspired by restful_authentication, Authlogic and Devise.
5
5
  Crypto code taken almost unchanged from Authlogic.
6
+ OAuth code inspired by OmniAuth and Ryan Bates's railscasts about it.
6
7
 
7
- == Example app using sorcery:
8
8
 
9
- https://github.com/NoamB/sorcery-example-app
9
+ == Summary
10
+
11
+
12
+ Sorcery is a stripped-down, bare-bones authentication library, with which you can write your own authentication flow.
13
+ It was built with a few goals in mind:
14
+
15
+ * Less is more - less than 20 public methods to remember for the entire feature-set make the lib easy to 'get'.
16
+ * No built-in or generated code - use the library's methods inside *your own* MVC structures, and don't fight to fix someone else's.
17
+ * Magic yes, Voodoo no - the lib should be easy to hack for most developers.
18
+ * Configuration over Confusion - Simple & short configuration as possible, not drowning in syntactic sugar.
19
+ * Keep MVC cleanly separated - DB is for models, sessions are for controllers. Models stay unaware of sessions.
20
+
21
+ Hopefully, I've achieved this. If not, let me know.
22
+
23
+
24
+ == Useful Links:
25
+
26
+
27
+ Example Rails 3 app using sorcery: https://github.com/NoamB/sorcery-example-app
28
+
29
+ Example Sinatra app using sorcery: https://github.com/NoamB/sorcery-example-app-sinatra
30
+
31
+ Documentation: http://rubydoc.info/gems/sorcery/0.3.0/frames
32
+
33
+ Check out the tutorials in the github wiki!
34
+
35
+
36
+ == Installation:
37
+
38
+
39
+ If using bundler, first add 'sorcery' to your Gemfile:
40
+
41
+ gem "sorcery"
42
+
43
+ And run
44
+
45
+ bundle install
46
+
47
+ Otherwise simply
48
+
49
+ gem install sorcery
50
+
51
+
52
+ == Configuration:
53
+
54
+
55
+ 1. config/application.rb
56
+
57
+ config.sorcery.submodules = [:user_activation, :remember_me] # add the submodules you want to use
58
+ # You can also configure here any controller and any controller-submodule option here. For example:
59
+ config.sorcery.session_timeout = 10.minutes
60
+
61
+ 2. app/models/user.rb (or another model of your choice, but a User class is assumed by default)
62
+
63
+ activate_sorcery! do |config|
64
+ config.user_activation_mailer = MyMailer
65
+ config.username_attribute_name = :email
66
+ end
67
+
68
+ 3. app/controllers/application_controller.rb (OPTIONAL: this is actually needed only in some cases)
69
+
70
+ activate_sorcery! do |config|
71
+ config.session_timeout = 10.minutes
72
+ end
73
+
74
+ The configuration options vary with the submodules you've chosen to use, so check the documentation or the wiki tutorials regarding the specific submodule.
75
+
76
+ For your convenience, Sorcery includes a migrations generator for Rails, which can be used like so:
77
+
78
+ rails g sorcery_migration [list of submodules]
79
+
80
+ For example, for only the core functionality use:
81
+
82
+ rails g sorcery_migration core
83
+
84
+ To generate migrations for both the core AND 'remember_me' submodule:
85
+
86
+ rails g sorcery_migration core remember_me
87
+
88
+ These migrations use the default fields. You can choose to use these migrations or make your own tables and fields. Sorcery tries not to impose a database structure and naming scheme on your application.
89
+
90
+
91
+ == Usage
92
+
93
+
94
+ Please see the tutorials in the github wiki.
95
+
10
96
 
11
97
  == Full Features List by module:
12
98
 
13
- Core (see lib/sorcery/model/model.rb and lib/sorcery/controller/controller.rb):
14
- * login/logout, optional redirect on login to where the user tried to reach before, configurable redirect for non-logged-in users.
99
+
100
+ Core (see lib/sorcery/model.rb and lib/sorcery/controller.rb):
101
+ * login/logout, optional return user to requested url on login, configurable redirect for non-logged-in users.
15
102
  * password encryption, algorithms: bcrypt(default), md5, sha1, sha256, sha512, aes256, custom(yours!), none. Configurable stretches and salt.
16
103
  * configurable attribute names for username, password and email.
17
104
 
18
105
  User Activation (see lib/sorcery/model/submodules/user_activation.rb):
19
106
  * User activation by email with optional success email.
20
107
  * configurable attribute names.
21
- * configurable mailer.
108
+ * configurable mailer, method name, and attribute name.
109
+ * configurable temporary token expiration.
22
110
  * Optionally prevent non-active users to login.
23
111
 
24
112
  Reset Password (see lib/sorcery/model/submodules/reset_password.rb):
25
113
  * Reset password with email verification.
26
114
  * configurable mailer, method name, and attribute name.
27
- * configurable expiration.
115
+ * configurable temporary token expiration.
28
116
  * configurable time between emails (hammering protection).
29
117
 
30
118
  Remember Me (see lib/sorcery/model/submodules/remember_me.rb):
@@ -49,82 +137,24 @@ Activity Logging (see lib/sorcery/model/submodules/activity_logging.rb):
49
137
  * an easy method of collecting the list of currently logged in users.
50
138
  * configurable timeout by which to decide whether to include a user in the list of logged in users.
51
139
 
52
- Other:
53
- * Modular design, load only the modules you need.
54
- * 100% TDD'd code, 100% test coverage.
140
+ Oauth (see lib/sorcery/controller/submodules/oauth.rb):
141
+ * OAuth1 and OAuth2 support (currently twitter & facebook)
142
+ * configurable db field names and authentications table.
143
+
55
144
 
56
145
  == Next Planned Features:
57
146
 
58
- I've got many plans which include:
147
+
148
+ I've got many plans which include (by priority):
149
+ * Scoping logins (to a subdomain or another arbitrary field)
150
+ * Simple auth (no user)
151
+ * Switching authentication mode at runtime (Maintenance mode)
152
+ * Mongoid support
59
153
  * Configurable Auto login on registration/activation
60
154
  * Other reset password strategies (security questions?)
61
155
  * Other brute force protection strategies (captcha)
62
- * Sinatra support
63
- * Mongoid support
64
- * OAuth1 and OAuth2 support
65
156
  * Have an idea? Let me know, and it might get into the gem!
66
157
 
67
- == Project Goals:
68
-
69
- This gem plugin was started out of a few personal goals which are not related to the problem solved by it at all:
70
- * I wanted to write something 100% TDD from start to finish.
71
- * I wanted to learn how to write an engine for Rails 3.
72
-
73
- In addition to the above goals, when I decided this will be an authentication plugin, and while looking at existing solutions, these goals came up:
74
- * Simple & short configuration as possible, not drowning in syntactic sugar.
75
- * Keep MVC cleanly separated - DB is for models, sessions are for controllers. Models stay unaware of sessions.
76
- * Magic yes, Voodoo no.
77
- * No generated code polluting the application's code.
78
- * No built-in controllers, models, mailers, migrations or templates; Real apps will need all of these custom made.
79
-
80
- Hopefully, I've achieved this. If not, let me know.
81
-
82
- == Installation:
83
-
84
- You can either git clone and then 'rake install' to live on the edge (unstable),
85
-
86
- Or simply (stable):
87
-
88
- gem install sorcery
89
-
90
- == Configuration:
91
-
92
- First add 'sorcery' to your Gemfile:
93
-
94
- gem "sorcery"
95
-
96
- And run
97
-
98
- bundle install
99
-
100
- There are 2 required places to configure the plugin, and an optional one:
101
- 1. config/application.rb
102
-
103
- config.sorcery.submodules = [:user_activation, :remember_me] # add the modules you want to use
104
-
105
- You can also configure here any controller and any controller-submodule option here.
106
- For example:
107
-
108
- config.sorcery.session_timeout = 10.minutes
109
-
110
-
111
- 2. app/models/user.rb (or another model of your choice)
112
-
113
- activate_sorcery! do |config|
114
- config.user_activation_mailer = MyMailer
115
- config.username_attribute_name = :email
116
- end
117
-
118
- 3. app/controllers/application_controller.rb (OPTIONAL: this is actually needed only in some cases)
119
-
120
- activate_sorcery! do |config|
121
- config.session_timeout = 10.minutes
122
- end
123
-
124
- Also check the migrations in the example app to see what database fields are expected.
125
-
126
- The configuration options vary with the modules you've chosen to use.
127
-
128
158
 
129
159
  == Contributing to sorcery
130
160
 
@@ -134,19 +164,22 @@ For this:
134
164
 
135
165
  * Fork the project.
136
166
  * Make your feature addition or bug fix.
137
- * Add tests for it. This is important so I don’t break it in a future version unintentionally.
167
+ * Add tests for it. I've used RSpec so far, please remain consistent with it.
138
168
  * Commit, do not mess with Rakefiles, version, or history. (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
139
169
  * Send me a pull request. Bonus points for topic branches.
140
170
 
141
171
  If you feel my work has made your life easier, and you would like to thank me through a donation, my paypal email is in the contact details.
142
172
 
173
+
143
174
  == Contact
144
175
 
176
+ Feel free to ask questions using these contact details:
177
+
145
178
  email: nbenari@gmail.com ( also for paypal )
146
179
  twitter: @nbenari
147
180
 
181
+
148
182
  == Copyright
149
183
 
150
- Copyright (c) 2010 Noam Ben Ari (nbenari@gmail.com). See LICENSE.txt for further details.
151
- Released with permission from Kontera (http://www.kontera.com), where I work.
152
184
 
185
+ Copyright (c) 2010 Noam Ben Ari (nbenari@gmail.com). See LICENSE.txt for further details.
data/Rakefile CHANGED
@@ -1,4 +1,5 @@
1
1
  # require 'bundler'
2
+ # -- Commented because it's slow
2
3
  # begin
3
4
  # Bundler.setup(:default, :development)
4
5
  # rescue Bundler::BundlerError => e
@@ -6,6 +7,8 @@
6
7
  # $stderr.puts "Run `bundle install` to install missing gems"
7
8
  # exit e.status_code
8
9
  # end
10
+ # --
11
+
9
12
  require 'rake'
10
13
 
11
14
  require 'jeweler'
@@ -23,6 +26,8 @@ Jeweler::Tasks.new do |gem|
23
26
  # gem.add_runtime_dependency 'jabber4r', '> 0.1'
24
27
  # gem.add_development_dependency 'rspec', '> 1.2.3'
25
28
  gem.add_runtime_dependency 'bcrypt-ruby', '~> 2.1.4'
29
+ gem.add_runtime_dependency 'oauth', '>= 0.4.4'
30
+ gem.add_runtime_dependency 'oauth2', '>= 0.1.1'
26
31
  end
27
32
  Jeweler::RubygemsDotOrgTasks.new
28
33
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.4
1
+ 0.3.0
@@ -0,0 +1,24 @@
1
+ require 'rails/generators'
2
+ require 'rails/generators/migration'
3
+
4
+ class SorceryMigrationGenerator < Rails::Generators::Base
5
+ include Rails::Generators::Migration
6
+
7
+ source_root File.join(File.dirname(__FILE__), 'templates')
8
+ argument :submodules, :type => :array, :required => true
9
+
10
+ def self.next_migration_number(dirname)
11
+ if ActiveRecord::Base.timestamped_migrations
12
+ Time.new.utc.strftime("%Y%m%d%H%M%S")
13
+ else
14
+ "%.3d" % (current_migration_number(dirname) + 1)
15
+ end
16
+ end
17
+
18
+ def create_migration_file
19
+ self.submodules.each do |submodule|
20
+ migration_template "#{submodule}.rb", "db/migrate/sorcery_#{submodule}.rb"
21
+ sleep 1 # for the timestamp to change
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,17 @@
1
+ class SorceryActivityLogging < ActiveRecord::Migration
2
+ def self.up
3
+ add_column :users, :last_login_at, :datetime, :default => nil
4
+ add_column :users, :last_logout_at, :datetime, :default => nil
5
+ add_column :users, :last_activity_at, :datetime, :default => nil
6
+
7
+ add_index :users, [:last_logout_at, :last_activity_at]
8
+ end
9
+
10
+ def self.down
11
+ remove_index :users, [:last_logout_at, :last_activity_at]
12
+
13
+ remove_column :users, :last_activity_at
14
+ remove_column :users, :last_logout_at
15
+ remove_column :users, :last_login_at
16
+ end
17
+ end
@@ -0,0 +1,11 @@
1
+ class SorceryBruteForceProtection < ActiveRecord::Migration
2
+ def self.up
3
+ add_column :users, :failed_logins_count, :integer, :default => 0
4
+ add_column :users, :lock_expires_at, :datetime, :default => nil
5
+ end
6
+
7
+ def self.down
8
+ remove_column :users, :lock_expires_at
9
+ remove_column :users, :failed_logins_count
10
+ end
11
+ end
@@ -0,0 +1,16 @@
1
+ class SorceryCore < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :users do |t|
4
+ t.string :username, :null => false
5
+ t.string :email, :default => nil
6
+ t.string :crypted_password, :default => nil
7
+ t.string :salt, :default => nil
8
+
9
+ t.timestamps
10
+ end
11
+ end
12
+
13
+ def self.down
14
+ drop_table :users
15
+ end
16
+ end
@@ -0,0 +1,14 @@
1
+ class SorceryOauth < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :authentications do |t|
4
+ t.integer :user_id, :null => false
5
+ t.string :provider, :uid, :null => false
6
+
7
+ t.timestamps
8
+ end
9
+ end
10
+
11
+ def self.down
12
+ drop_table :authentications
13
+ end
14
+ end
@@ -0,0 +1,15 @@
1
+ class SorceryRememberMe < ActiveRecord::Migration
2
+ def self.up
3
+ add_column :users, :remember_me_token, :string, :default => nil
4
+ add_column :users, :remember_me_token_expires_at, :datetime, :default => nil
5
+
6
+ add_index :users, :remember_me_token
7
+ end
8
+
9
+ def self.down
10
+ remove_index :users, :remember_me_token
11
+
12
+ remove_column :users, :remember_me_token_expires_at
13
+ remove_column :users, :remember_me_token
14
+ end
15
+ end
@@ -0,0 +1,13 @@
1
+ class SorceryResetPassword < ActiveRecord::Migration
2
+ def self.up
3
+ add_column :users, :reset_password_token, :string, :default => nil
4
+ add_column :users, :reset_password_token_expires_at, :datetime, :default => nil
5
+ add_column :users, :reset_password_email_sent_at, :datetime, :default => nil
6
+ end
7
+
8
+ def self.down
9
+ remove_column :users, :reset_password_email_sent_at
10
+ remove_column :users, :reset_password_token_expires_at
11
+ remove_column :users, :reset_password_token
12
+ end
13
+ end
@@ -0,0 +1,17 @@
1
+ class SorceryUserActivation < ActiveRecord::Migration
2
+ def self.up
3
+ add_column :users, :activation_state, :string, :default => nil
4
+ add_column :users, :activation_token, :string, :default => nil
5
+ add_column :users, :activation_token_expires_at, :datetime, :default => nil
6
+
7
+ add_index :users, :activation_token
8
+ end
9
+
10
+ def self.down
11
+ remove_index :users, :activation_token
12
+
13
+ remove_column :users, :activation_token_expires_at
14
+ remove_column :users, :activation_token
15
+ remove_column :users, :activation_state
16
+ end
17
+ end
@@ -0,0 +1,97 @@
1
+ module Sorcery
2
+ module Controller
3
+ module Adapters
4
+ # This module does the magic of translating Rails commands to Sinatra.
5
+ # This way the Rails code doesn't change, but it actually now calls Sinatra calls.
6
+ module Sinatra
7
+ def self.included(base)
8
+ base.class_eval do
9
+ class << self
10
+ # prepend a filter
11
+ def prepend_filter(type, path = nil, options = {}, &block)
12
+ return filters[type].unshift block unless path
13
+ path, options = //, path if path.respond_to?(:each_pair)
14
+ block, *arguments = compile!(type, path, block, options)
15
+ prepend_filter(type) do
16
+ process_route(*arguments) { instance_eval(&block) }
17
+ end
18
+ end
19
+
20
+ def after_filter(filter)
21
+ after do
22
+ send(filter)
23
+ end
24
+ end
25
+ end
26
+ end
27
+
28
+ ::Sinatra::Request.class_eval do
29
+ def authorization
30
+ env['HTTP_AUTHORIZATION'] ||
31
+ env['X-HTTP_AUTHORIZATION'] ||
32
+ env['X_HTTP_AUTHORIZATION'] ||
33
+ env['REDIRECT_X_HTTP_AUTHORIZATION'] || nil
34
+ end
35
+ end
36
+
37
+ base.send(:include, InstanceMethods)
38
+ base.extend(ClassMethods)
39
+ end
40
+
41
+ module InstanceMethods
42
+ def reset_session
43
+ session.clear
44
+ end
45
+
46
+ def redirect_to(*args)
47
+ args.pop if args.last.is_a?(Hash)
48
+ redirect(*args)
49
+ end
50
+
51
+ def root_path
52
+ '/'
53
+ end
54
+
55
+ helpers do
56
+ def request_http_basic_authentication(realm)
57
+ response.header['WWW-Authenticate'] = %(Basic realm="#{realm}")
58
+ response.status = 401
59
+ end
60
+
61
+ def authenticate_with_http_basic(&blk)
62
+ @auth ||= Rack::Auth::Basic::Request.new(request.env)
63
+ yield @auth.credentials if ( @auth.provided? && @auth.basic? && @auth.credentials )
64
+ end
65
+ end
66
+
67
+ def cookies
68
+ @cookie_proxy ||= CookieProxy.new(request,response)
69
+ end
70
+ end
71
+
72
+ class CookieProxy
73
+ def initialize(request,response)
74
+ @request = request
75
+ @response = response
76
+ end
77
+
78
+ def [](key)
79
+ @request.cookies[key.to_s]
80
+ end
81
+
82
+ def []=(key, value)
83
+ @response.set_cookie(key, value)
84
+ end
85
+ end
86
+
87
+ module ClassMethods
88
+ def prepend_before_filter(filter)
89
+ prepend_filter(:before) do
90
+ send(filter)
91
+ end
92
+ end
93
+ end
94
+ end
95
+ end
96
+ end
97
+ end
@@ -1,6 +1,13 @@
1
1
  module Sorcery
2
2
  module Controller
3
3
  module Submodules
4
+ # This submodule keeps track of events such as login, logout, and last activity time, per user.
5
+ # It helps in estimating which users are active now in the site.
6
+ # This cannot be determined absolutely because a user might be reading a page without clicking anything for a while.
7
+
8
+ # This is the controller part of the submodule, which adds hooks to register user events,
9
+ # and methods to collect active users data for use in the app.
10
+ # see Socery::Model::Submodules::ActivityLogging for configuration options.
4
11
  module ActivityLogging
5
12
  def self.included(base)
6
13
  base.send(:include, InstanceMethods)
@@ -10,33 +17,39 @@ module Sorcery
10
17
  end
11
18
 
12
19
  module InstanceMethods
13
- def logged_in_users
14
- Config.user_class.logged_in_users
20
+ # Returns an array of the active users.
21
+ def current_users
22
+ Config.user_class.current_users
15
23
  # A possible patch here:
16
- # we'll add the logged_in_user to the users list if he's not in it (can happen when he was inactive for more than activity timeout):
24
+ # we'll add the current_user to the users list if he's not in it (can happen when he was inactive for more than activity timeout):
17
25
  #
18
- # users.unshift!(logged_in_user) if logged_in? && users.find {|u| u.id == logged_in_user.id}.nil?
26
+ # users.unshift!(current_user) if logged_in? && users.find {|u| u.id == current_user.id}.nil?
19
27
  #
20
28
  # disadvantages: can hurt performance.
21
29
  end
22
30
 
23
31
  protected
24
32
 
33
+ # registers last login time on every login.
34
+ # This runs as a hook just after a successful login.
25
35
  def register_login_time_to_db(user, credentials)
26
36
  user.send(:"#{user.sorcery_config.last_login_at_attribute_name}=", Time.now.utc.to_s(:db))
27
37
  user.save!(:validate => false)
28
38
  end
29
39
 
40
+ # registers last logout time on every logout.
41
+ # This runs as a hook just before a logout.
30
42
  def register_logout_time_to_db(user)
31
43
  user.send(:"#{user.sorcery_config.last_logout_at_attribute_name}=", Time.now.utc.to_s(:db))
32
44
  user.save!(:validate => false)
33
45
  end
34
46
 
35
- # we do not update activity on logout
47
+ # Updates last activity time on every request.
48
+ # The only exception is logout - we do not update activity on logout
36
49
  def register_last_activity_time_to_db
37
50
  return if !logged_in?
38
- logged_in_user.send(:"#{logged_in_user.sorcery_config.last_activity_at_attribute_name}=", Time.now.utc.to_s(:db))
39
- logged_in_user.save!(:validate => false)
51
+ current_user.send(:"#{current_user.sorcery_config.last_activity_at_attribute_name}=", Time.now.utc.to_s(:db))
52
+ current_user.save!(:validate => false)
40
53
  end
41
54
  end
42
55
  end