google-authenticator-rails 0.0.4 → 1.2.1

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 73fb9d2e9191704db8c7059225616e08336f4328
4
+ data.tar.gz: babaa2016345e654a937bed679374e3226e5fbe7
5
+ SHA512:
6
+ metadata.gz: eea521e18f89fe7f69e98ade4199a6b10386dd7f322fd91fb3ac24440d5f94bda5958eac67fb0997b0aee3ad3fa56f22fd01dd854a4629feb52940fffae6ca3e
7
+ data.tar.gz: b91ca64415d05ccf921508df87047f4b889ac84bd26870fe90d1e2fb6e574951d3cb04445a60c59cd8e9c9b86d3255bb60dbf98416068dfc94e741c0dae80019
data/.ruby-gemset ADDED
@@ -0,0 +1 @@
1
+ google-auth-rails
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ ruby-2.1.5
data/.travis.yml CHANGED
@@ -1,11 +1,9 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 1.8.7
4
- - 1.9.2
5
3
  - 1.9.3
4
+ - 2.0.0
5
+ - 2.1.0
6
6
  # - jruby-18mode # JRuby in 1.8 mode
7
7
  # - jruby-19mode # JRuby in 1.9 mode
8
- - rbx-18mode
9
- - rbx-19mode
10
- # uncomment this line if your project needs to run something other than `rake`:
11
- script: bundle exec rspec spec
8
+ # - rbx-18mode
9
+ # - rbx-19mode
data/Appraisals ADDED
@@ -0,0 +1,27 @@
1
+ version_info = RUBY_VERSION.split(".")
2
+
3
+ major = version_info.first.to_i
4
+ minor = version_info[1].to_i
5
+ hotfix = version_info.last.to_i
6
+
7
+ appraise "rails3.0" do
8
+ gem "activerecord", "~> 3.0.0"
9
+ end
10
+
11
+ appraise "rails3.1" do
12
+ gem "activerecord", "~> 3.1.0"
13
+ end
14
+
15
+ appraise "rails3.2." do
16
+ gem "activerecord", "~> 3.2.0"
17
+ end
18
+
19
+ appraise "rails4.0" do
20
+ gem "activerecord", "~> 4.0.0"
21
+ gem "protected_attributes"
22
+ end
23
+
24
+ appraise "rails4.1" do
25
+ gem "activerecord", "~> 4.1.0"
26
+ gem "protected_attributes"
27
+ end
data/README.md CHANGED
@@ -2,8 +2,9 @@
2
2
 
3
3
  [![Gem Version](https://badge.fury.io/rb/google-authenticator-rails.png)](http://badge.fury.io/rb/google-authenticator-rails)
4
4
  [![Build Status](https://secure.travis-ci.org/jaredonline/google-authenticator.png)](http://travis-ci.org/jaredonline/google-authenticator)
5
+ [![Code Climate](https://codeclimate.com/github/jaredonline/google-authenticator.png)](https://codeclimate.com/github/jaredonline/google-authenticator)
5
6
 
6
- Rails (ActiveRecord) integration with the Google Authenticator apps for Android and the iPhone. Uses the Authlogic style for cookie management.
7
+ Rails (ActiveRecord) integration with the Google Authenticator apps for [Android](https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2) and the [iPhone](https://itunes.apple.com/us/app/google-authenticator/id388497605?mt=8). Uses the Authlogic style for cookie management.
7
8
 
8
9
  ## Installation
9
10
 
@@ -25,30 +26,29 @@ Example:
25
26
 
26
27
  ```ruby
27
28
  class User
28
- acts_as_google_authenticated
29
+ acts_as_google_authenticated
29
30
  end
30
31
 
31
32
  @user = User.new
32
33
  @user.set_google_secret # => true
33
34
  @user.google_qr_uri # => http://path.to.google/qr?with=params
34
- @user.google_authentic?(123456) # => true
35
+ @user.google_authentic?(123456) # => true
35
36
  ```
36
37
 
37
- Google Labels
38
- When setting up an account with the GoogleAuthenticator you need to provide
39
- a label for that account (to distinguish it from other accounts).
38
+ ## Google Labels
39
+
40
+ When setting up an account with `GoogleAuthenticatorRails` you need to provide a label for that account (to distinguish it from other accounts).
40
41
 
41
- GoogleAuthenticatorRails allows you to customize how the record will create
42
- that label. There are three options:
43
- - The default just uses the column "email" on the model
44
- - You can specify a custom column with the :column_name option
42
+ `GoogleAuthenticatorRails` allows you to customize how the record will create that label. There are three options:
43
+ - The default just uses the column `email` on the model
44
+ - You can specify a custom column with the `:column_name` option
45
45
  - You can specify a custom method via a symbol or a proc
46
46
 
47
- Examples:
47
+ Example:
48
48
 
49
49
  ```ruby
50
50
  class User
51
- acts_as_google_authenticated :column => :user_name
51
+ acts_as_google_authenticated :column => :user_name
52
52
  end
53
53
 
54
54
  @user = User.new(:user_name => "ted")
@@ -77,6 +77,14 @@ end
77
77
  @user.google_label # => "TED@EXAMPLE.COM"
78
78
  ```
79
79
 
80
+ Here's what the labels look like in Google Authenticator for iPhone:
81
+
82
+ ![iPhone Label Screenshot](http://jaredonline.github.io/google-authenticator/images/gar-label.png)
83
+
84
+ ## Google Secret
85
+ The "google secret" is where `GoogleAuthenticatorRails` stores the
86
+ secret token used to generate the MFA code.
87
+
80
88
  You can also specify a column for storing the google secret. The default is `google_secret`.
81
89
 
82
90
  Example
@@ -91,19 +99,153 @@ end
91
99
  @user.mfa_secret # => "56ahi483"
92
100
  ```
93
101
 
102
+ ## Drift
103
+
104
+ You can specify a custom drift value. Drift is the number of seconds that the client
105
+ and server are allowed to drift apart. Default value is 5 seconds.
106
+
107
+ ```ruby
108
+ class User
109
+ act_as_google_authenticated :drift => 31
110
+ end
111
+ ```
112
+
113
+ ## Lookup Token
114
+
115
+ You can also specify which column the appropriate `MfaSession` subclass should use to look up the record:
116
+
117
+ Example
118
+
119
+ ```ruby
120
+ class User
121
+ acts_as_google_authenticated :lookup_token => :salt
122
+ end
123
+ ```
124
+
125
+ The above will cause the `UserMfaSession` class to call `User.where(:salt => cookie_salt)` or `User.scoped(:conditions => { :salt => cookie_salt })` to find the appropriate record.
126
+
127
+ ### A note about record lookup
128
+
129
+ `GoogleAuthenticatorRails` makes one very large assumption when attempting to lookup a record. If your `MfaSession` subclass is named `UserMfaSession` it assumes you're trying to lookup a `User` record. Currently, there is no way to configure this, so if you're trying to lookup a `VeryLongModelNameForUser` you'll need to name your `MfaSession` subclass `VeryLongModelNameForUserMfaSession`.
130
+
131
+ For example:
132
+
133
+ ```ruby
134
+ # app/models/user.rb
135
+ class User < ActiveRecord::Base
136
+ acts_as_google_authentic
137
+ end
138
+
139
+ # app/models/user_mfa_session.rb
140
+ class UserMfaSession < GoogleAuthenticatorRails::Session::Base
141
+ end
142
+ ```
143
+
144
+ ### A note about cookie creation and `Session::Persistence::TokenNotFound`
145
+
146
+ `GoogleAuthenticatorRails` looks up the record based on the cookie created when you call `MfaSession#create`. The `#create` method looks into the record class (in our example, `User`) and looks at the configured `:lookup_token` option. It uses that option to save two pieces of information into the cookie, the `id` of the record and the token, which defaults to `persistence_token`. `persistence_token` is what Authlogic uses, which this gem was originally designed to work with.
147
+
148
+ This can cause a lot of headaches if the model isn't configured correctly, and will cause a `GoogleAuthenticatorRails::Session::Persistence::TokenNotFound` error.
149
+
150
+ This error appears for one of three reasons:
151
+
152
+ 1. `user` is `nil`
153
+ 2. `user` doesn't respond to `:persistence_token`
154
+ 3. `user.persistence_token` is blank
155
+
156
+ For example:
157
+
158
+ ```ruby
159
+ # app/models/user.rb
160
+ class User < ActiveRecord::Base
161
+ acts_as_google_authentic
162
+ end
163
+
164
+ # Model has attributes:
165
+ # id: integer
166
+ # name: string
167
+ # salt: string
168
+
169
+ # app/models/user_mfa_session.rb
170
+ class UserMfaSession < GoogleAuthenticatorRails::Session::Base
171
+ end
172
+
173
+ # app/controllers/mfa_session_controller.rb
174
+ class MfaSessionController < ApplicationController
175
+ def create
176
+ UserMfaSession.create(user) # => Error: GoogleAuthenticatorRails::Session::Persistence::TokenNotFound
177
+ end
178
+ end
179
+ ```
180
+
181
+ The above example will fail because the `User` class doesn't have a `persistence_token` method. The fix for this is to configure `actions_as_google_authentic` to use the right column:
182
+
183
+ ```ruby
184
+ # app/models/user.rb
185
+ class User < ActiveRecord::Base
186
+ acts_as_google_authentic :lookup_token => :salt
187
+ end
188
+
189
+ # Model has attributes:
190
+ # id: integer
191
+ # name: string
192
+ # salt: string
193
+
194
+ # app/models/user_mfa_session.rb
195
+ class UserMfaSession < GoogleAuthenticatorRails::Session::Base
196
+ end
197
+
198
+ # app/controllers/mfa_session_controller.rb
199
+ def class MfaSessionController < ApplicationController
200
+ def create
201
+ UserMfaSession.create(user)
202
+ end
203
+ end
204
+ ```
205
+
206
+ This call to `#create` will succeed (as long as `user.salt` is not `nil`).
207
+
208
+
209
+ ## Issuer
210
+
211
+ You can also specify a name for the 'issuer' (the name of the website) where the user is using this token:
212
+
213
+ Example
214
+
215
+ ```ruby
216
+ class User
217
+ acts_as_google_authenticated :issuer => 'example.com'
218
+ end
219
+ ```
220
+
221
+ This way your user will have the name of your site at the authenticator card besides the current token.
222
+
223
+ Here's what the issuers look like in Google Authenticator for iPhone:
224
+
225
+ ![iPhone Label Screenshot](http://jaredonline.github.io/google-authenticator/images/gar-issuer.png)
226
+
94
227
  ## Sample Rails Setup
95
228
 
96
- This is a very rough outline of how GoogleAuthenticatorRails is meant to manage the sessions and cookies for a Rails app.
229
+ This is a very rough outline of how `GoogleAuthenticatorRails` is meant to manage the sessions and cookies for a Rails app.
97
230
 
98
231
  ```ruby
99
- Gemfile
232
+ # Gemfile
100
233
 
101
234
  gem 'rails'
102
235
  gem 'google-authenticator-rails'
103
236
  ```
104
237
 
238
+ First add a field to your user model to hold the Google token.
239
+ ```ruby
240
+ class AddGoogleSecretToUser < ActiveRecord::Migration
241
+ def change
242
+ add_column :users, :google_secret, :string
243
+ end
244
+ end
245
+ ```
246
+
105
247
  ```ruby
106
- app/models/users.rb
248
+ # app/models/users.rb
107
249
 
108
250
  class User < ActiveRecord::Base
109
251
  acts_as_google_authenticated
@@ -113,18 +255,18 @@ end
113
255
  If you want to authenticate based on a model called `User`, then you should name your session object `UserMfaSession`.
114
256
 
115
257
  ```ruby
116
- app/models/user_mfa_session.rb
258
+ # app/models/user_mfa_session.rb
117
259
 
118
- class UserMfaSession < GoogleAuthenticator::Session::Base
260
+ class UserMfaSession < GoogleAuthenticatorRails::Session::Base
119
261
  # no real code needed here
120
262
  end
121
263
  ```
122
264
 
123
265
  ```ruby
124
- app/controllers/user_mfa_session_controller.rb
266
+ # app/controllers/user_mfa_session_controller.rb
125
267
 
126
268
  class UserMfaSessionController < ApplicationController
127
-
269
+
128
270
  def new
129
271
  # load your view
130
272
  end
@@ -144,27 +286,46 @@ end
144
286
  ```
145
287
 
146
288
  ```ruby
147
- app/controllers/application_controller.rb
289
+ # app/controllers/application_controller.rb
148
290
 
149
291
  class ApplicationController < ActionController::Base
150
292
  before_filter :check_mfa
151
293
 
152
294
  private
153
295
  def check_mfa
154
- if !(user_mfa_session = UserMfaSession.find) && user_mfa_session.record == current_user
296
+ if !(user_mfa_session = UserMfaSession.find) && (user_mfa_session ? user_mfa_session.record == current_user : !user_mfa_session)
155
297
  redirect_to new_user_mfa_session_path
156
298
  end
157
299
  end
158
300
  end
159
301
  ```
160
302
 
161
- By default, the cookie related to the MfaSession expires in 24 hours, but this can be changed:
303
+ ## Cookie options
304
+
305
+ You can configure the MfaSession cookie by creating an initializer:
306
+
162
307
  ```ruby
163
- config/initializers/google_authenticator_rails.rb
308
+ # config/initializers/google_authenticator_rails.rb
164
309
 
310
+ # The cookie normally expires in 24 hours, you can change this to 1 month
165
311
  GoogleAuthenticatorRails.time_until_expiration = 1.month
312
+
313
+ # You can override the suffix of the cookie's key, by default this is mfa_credentials
314
+ GoogleAuthenticatorRails.cookie_key_suffix = 'mfa_credentials'
315
+
316
+ # Rails offers a few more cookie options, by default only :httponly is turned on, you can change it to HTTPS only:
317
+ GoogleAuthenticatorRails.cookie_options = { :httponly => true, :secure => true, :domain => :all }
166
318
  ```
167
319
 
320
+ Additional cookie option symbols can be found in the [Ruby on Rails guide](http://api.rubyonrails.org/classes/ActionDispatch/Cookies.html).
321
+
322
+ ## Destroying the Cookie
323
+
324
+ If you want to manually destroy the MFA cookie (for example, when a user logs out), just call
325
+
326
+ ```ruby
327
+ UserMfaSession::destroy
328
+ ```
168
329
 
169
330
  ## Contributing
170
331
 
@@ -177,3 +338,4 @@ GoogleAuthenticatorRails.time_until_expiration = 1.month
177
338
  ## License
178
339
 
179
340
  MIT.
341
+
data/Rakefile CHANGED
@@ -1,2 +1,28 @@
1
1
  #!/usr/bin/env rake
2
+ require "bundler/setup"
2
3
  require "bundler/gem_tasks"
4
+ require "appraisal"
5
+
6
+ begin
7
+ # RSpec 2
8
+ require "rspec/core/rake_task"
9
+
10
+ RSpec::Core::RakeTask.new do |t|
11
+ t.pattern = "spec/**/*_spec.rb"
12
+ t.rspec_opts = "--color --format documentation --backtrace"
13
+ end
14
+ rescue LoadError
15
+ # RSpec 1
16
+ require "spec/rake/spectask"
17
+
18
+ Spec::Rake::SpecTask.new(:spec) do |t|
19
+ t.pattern = "spec/**/*_spec.rb"
20
+ t.spec_opts = ["--color", "--format nested", "--backtrace"]
21
+ end
22
+ end
23
+
24
+ desc "Default: Test the gem under all supported Rails versions."
25
+ task :default => ["appraisal:install"] do
26
+ exec("rake appraisal spec")
27
+ end
28
+
@@ -0,0 +1,7 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "activerecord", "~> 2.3.8"
6
+
7
+ gemspec :path=>"../"
@@ -0,0 +1,45 @@
1
+ PATH
2
+ remote: ../
3
+ specs:
4
+ google-authenticator-rails (0.0.11)
5
+ actionpack
6
+ activerecord
7
+ google-qr
8
+ rotp (= 1.6.1)
9
+
10
+ GEM
11
+ remote: https://rubygems.org/
12
+ specs:
13
+ actionpack (2.3.18)
14
+ activesupport (= 2.3.18)
15
+ rack (~> 1.1.0)
16
+ activerecord (2.3.18)
17
+ activesupport (= 2.3.18)
18
+ activesupport (2.3.18)
19
+ appraisal (0.5.2)
20
+ bundler
21
+ rake
22
+ diff-lcs (1.1.3)
23
+ google-qr (0.2.2)
24
+ rack (1.1.6)
25
+ rake (10.1.1)
26
+ rotp (1.6.1)
27
+ rspec (2.8.0)
28
+ rspec-core (~> 2.8.0)
29
+ rspec-expectations (~> 2.8.0)
30
+ rspec-mocks (~> 2.8.0)
31
+ rspec-core (2.8.0)
32
+ rspec-expectations (2.8.0)
33
+ diff-lcs (~> 1.1.2)
34
+ rspec-mocks (2.8.0)
35
+ sqlite3 (1.3.8)
36
+
37
+ PLATFORMS
38
+ ruby
39
+
40
+ DEPENDENCIES
41
+ activerecord (~> 2.3.8)
42
+ appraisal (~> 0.5.1)
43
+ google-authenticator-rails!
44
+ rspec (~> 2.8.0)
45
+ sqlite3
@@ -0,0 +1,7 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "activerecord", "~> 3.0.0"
6
+
7
+ gemspec :path=>"../"
@@ -0,0 +1,70 @@
1
+ PATH
2
+ remote: ../
3
+ specs:
4
+ google-authenticator-rails (0.0.11)
5
+ actionpack
6
+ activerecord
7
+ google-qr
8
+ rotp (= 1.6.1)
9
+
10
+ GEM
11
+ remote: https://rubygems.org/
12
+ specs:
13
+ abstract (1.0.0)
14
+ actionpack (3.0.20)
15
+ activemodel (= 3.0.20)
16
+ activesupport (= 3.0.20)
17
+ builder (~> 2.1.2)
18
+ erubis (~> 2.6.6)
19
+ i18n (~> 0.5.0)
20
+ rack (~> 1.2.5)
21
+ rack-mount (~> 0.6.14)
22
+ rack-test (~> 0.5.7)
23
+ tzinfo (~> 0.3.23)
24
+ activemodel (3.0.20)
25
+ activesupport (= 3.0.20)
26
+ builder (~> 2.1.2)
27
+ i18n (~> 0.5.0)
28
+ activerecord (3.0.20)
29
+ activemodel (= 3.0.20)
30
+ activesupport (= 3.0.20)
31
+ arel (~> 2.0.10)
32
+ tzinfo (~> 0.3.23)
33
+ activesupport (3.0.20)
34
+ appraisal (0.5.2)
35
+ bundler
36
+ rake
37
+ arel (2.0.10)
38
+ builder (2.1.2)
39
+ diff-lcs (1.1.3)
40
+ erubis (2.6.6)
41
+ abstract (>= 1.0.0)
42
+ google-qr (0.2.2)
43
+ i18n (0.5.3)
44
+ rack (1.2.8)
45
+ rack-mount (0.6.14)
46
+ rack (>= 1.0.0)
47
+ rack-test (0.5.7)
48
+ rack (>= 1.0)
49
+ rake (10.1.1)
50
+ rotp (1.6.1)
51
+ rspec (2.8.0)
52
+ rspec-core (~> 2.8.0)
53
+ rspec-expectations (~> 2.8.0)
54
+ rspec-mocks (~> 2.8.0)
55
+ rspec-core (2.8.0)
56
+ rspec-expectations (2.8.0)
57
+ diff-lcs (~> 1.1.2)
58
+ rspec-mocks (2.8.0)
59
+ sqlite3 (1.3.8)
60
+ tzinfo (0.3.38)
61
+
62
+ PLATFORMS
63
+ ruby
64
+
65
+ DEPENDENCIES
66
+ activerecord (~> 3.0.0)
67
+ appraisal (~> 0.5.1)
68
+ google-authenticator-rails!
69
+ rspec (~> 2.8.0)
70
+ sqlite3
@@ -0,0 +1,7 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "activerecord", "~> 3.1.0"
6
+
7
+ gemspec :path=>"../"
@@ -0,0 +1,79 @@
1
+ PATH
2
+ remote: ../
3
+ specs:
4
+ google-authenticator-rails (0.0.11)
5
+ actionpack
6
+ activerecord
7
+ google-qr
8
+ rotp (= 1.6.1)
9
+
10
+ GEM
11
+ remote: https://rubygems.org/
12
+ specs:
13
+ actionpack (3.1.12)
14
+ activemodel (= 3.1.12)
15
+ activesupport (= 3.1.12)
16
+ builder (~> 3.0.0)
17
+ erubis (~> 2.7.0)
18
+ i18n (~> 0.6)
19
+ rack (~> 1.3.6)
20
+ rack-cache (~> 1.2)
21
+ rack-mount (~> 0.8.2)
22
+ rack-test (~> 0.6.1)
23
+ sprockets (~> 2.0.4)
24
+ activemodel (3.1.12)
25
+ activesupport (= 3.1.12)
26
+ builder (~> 3.0.0)
27
+ i18n (~> 0.6)
28
+ activerecord (3.1.12)
29
+ activemodel (= 3.1.12)
30
+ activesupport (= 3.1.12)
31
+ arel (~> 2.2.3)
32
+ tzinfo (~> 0.3.29)
33
+ activesupport (3.1.12)
34
+ multi_json (~> 1.0)
35
+ appraisal (0.5.2)
36
+ bundler
37
+ rake
38
+ arel (2.2.3)
39
+ builder (3.0.4)
40
+ diff-lcs (1.1.3)
41
+ erubis (2.7.0)
42
+ google-qr (0.2.2)
43
+ hike (1.2.3)
44
+ i18n (0.6.9)
45
+ multi_json (1.8.4)
46
+ rack (1.3.10)
47
+ rack-cache (1.2)
48
+ rack (>= 0.4)
49
+ rack-mount (0.8.3)
50
+ rack (>= 1.0.0)
51
+ rack-test (0.6.2)
52
+ rack (>= 1.0)
53
+ rake (10.1.1)
54
+ rotp (1.6.1)
55
+ rspec (2.8.0)
56
+ rspec-core (~> 2.8.0)
57
+ rspec-expectations (~> 2.8.0)
58
+ rspec-mocks (~> 2.8.0)
59
+ rspec-core (2.8.0)
60
+ rspec-expectations (2.8.0)
61
+ diff-lcs (~> 1.1.2)
62
+ rspec-mocks (2.8.0)
63
+ sprockets (2.0.5)
64
+ hike (~> 1.2)
65
+ rack (~> 1.0)
66
+ tilt (~> 1.1, != 1.3.0)
67
+ sqlite3 (1.3.8)
68
+ tilt (1.4.1)
69
+ tzinfo (0.3.38)
70
+
71
+ PLATFORMS
72
+ ruby
73
+
74
+ DEPENDENCIES
75
+ activerecord (~> 3.1.0)
76
+ appraisal (~> 0.5.1)
77
+ google-authenticator-rails!
78
+ rspec (~> 2.8.0)
79
+ sqlite3
@@ -0,0 +1,7 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "activerecord", "~> 3.2.0"
6
+
7
+ gemspec :path=>"../"
@@ -0,0 +1,78 @@
1
+ PATH
2
+ remote: ../
3
+ specs:
4
+ google-authenticator-rails (0.0.11)
5
+ actionpack
6
+ activerecord
7
+ google-qr
8
+ rotp (= 1.6.1)
9
+
10
+ GEM
11
+ remote: https://rubygems.org/
12
+ specs:
13
+ actionpack (3.2.13)
14
+ activemodel (= 3.2.13)
15
+ activesupport (= 3.2.13)
16
+ builder (~> 3.0.0)
17
+ erubis (~> 2.7.0)
18
+ journey (~> 1.0.4)
19
+ rack (~> 1.4.5)
20
+ rack-cache (~> 1.2)
21
+ rack-test (~> 0.6.1)
22
+ sprockets (~> 2.2.1)
23
+ activemodel (3.2.13)
24
+ activesupport (= 3.2.13)
25
+ builder (~> 3.0.0)
26
+ activerecord (3.2.13)
27
+ activemodel (= 3.2.13)
28
+ activesupport (= 3.2.13)
29
+ arel (~> 3.0.2)
30
+ tzinfo (~> 0.3.29)
31
+ activesupport (3.2.13)
32
+ i18n (= 0.6.1)
33
+ multi_json (~> 1.0)
34
+ appraisal (0.5.2)
35
+ bundler
36
+ rake
37
+ arel (3.0.2)
38
+ builder (3.0.4)
39
+ diff-lcs (1.1.3)
40
+ erubis (2.7.0)
41
+ google-qr (0.2.2)
42
+ hike (1.2.3)
43
+ i18n (0.6.1)
44
+ journey (1.0.4)
45
+ multi_json (1.8.4)
46
+ rack (1.4.5)
47
+ rack-cache (1.2)
48
+ rack (>= 0.4)
49
+ rack-test (0.6.2)
50
+ rack (>= 1.0)
51
+ rake (10.1.1)
52
+ rotp (1.6.1)
53
+ rspec (2.8.0)
54
+ rspec-core (~> 2.8.0)
55
+ rspec-expectations (~> 2.8.0)
56
+ rspec-mocks (~> 2.8.0)
57
+ rspec-core (2.8.0)
58
+ rspec-expectations (2.8.0)
59
+ diff-lcs (~> 1.1.2)
60
+ rspec-mocks (2.8.0)
61
+ sprockets (2.2.3)
62
+ hike (~> 1.2)
63
+ multi_json (~> 1.0)
64
+ rack (~> 1.0)
65
+ tilt (~> 1.1, != 1.3.0)
66
+ sqlite3 (1.3.8)
67
+ tilt (1.4.1)
68
+ tzinfo (0.3.38)
69
+
70
+ PLATFORMS
71
+ ruby
72
+
73
+ DEPENDENCIES
74
+ activerecord (~> 3.2.0)
75
+ appraisal (~> 0.5.1)
76
+ google-authenticator-rails!
77
+ rspec (~> 2.8.0)
78
+ sqlite3