opro 0.0.1 → 0.0.2

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 (52) hide show
  1. data/Gemfile +6 -2
  2. data/Gemfile.lock +37 -33
  3. data/README.md +60 -31
  4. data/Rakefile +8 -0
  5. data/VERSION +1 -1
  6. data/app/controllers/oauth/auth_controller.rb +35 -36
  7. data/app/controllers/oauth/client_app_controller.rb +24 -0
  8. data/app/controllers/oauth/docs_controller.rb +1 -1
  9. data/app/controllers/oauth/tests_controller.rb +4 -26
  10. data/app/controllers/oauth/token_controller.rb +40 -0
  11. data/app/controllers/opro_controller.rb +4 -0
  12. data/app/models/oauth/access_grant.rb +47 -14
  13. data/app/models/oauth/{client_application.rb → client_appl.rb} +1 -1
  14. data/app/views/oauth/{client_application → client_app}/create.html.erb +1 -1
  15. data/app/views/oauth/{client_application → client_app}/index.html.erb +1 -1
  16. data/app/views/oauth/{client_application → client_app}/new.html.erb +1 -1
  17. data/app/views/oauth/docs/index.html.erb +8 -0
  18. data/app/views/oauth/docs/markdown/oauth.md.erb +2 -2
  19. data/app/views/oauth/docs/markdown/permissions.md.erb +30 -0
  20. data/app/views/oauth/docs/markdown/quick_start.md.erb +1 -1
  21. data/app/views/oauth/docs/markdown/refresh_tokens.md.erb +18 -0
  22. data/config/routes.rb +5 -10
  23. data/lib/generators/active_record/opro_generator.rb +1 -1
  24. data/lib/generators/active_record/templates/access_grants.rb +1 -1
  25. data/lib/generators/active_record/templates/client_applications.rb +1 -1
  26. data/lib/generators/opro/install_generator.rb +5 -0
  27. data/lib/generators/templates/opro.rb +10 -3
  28. data/lib/opro.rb +7 -1
  29. data/lib/opro/controllers/application_controller_helper.rb +7 -2
  30. data/lib/opro/engine.rb +4 -0
  31. data/lib/opro/rails/routes.rb +17 -0
  32. data/opro.gemspec +27 -15
  33. data/test/controllers/refresh_token_test.rb +0 -0
  34. data/test/dummy/config/environments/test.rb +4 -0
  35. data/test/dummy/config/initializers/opro.rb +10 -3
  36. data/test/dummy/config/routes.rb +2 -0
  37. data/test/dummy/db/migrate/20120514060322_create_opro_access_grants.rb +1 -1
  38. data/test/dummy/db/migrate/20120514060323_create_opro_client_applications.rb +1 -1
  39. data/test/integration/action_dispatch/auth_controller_test.rb +64 -0
  40. data/test/integration/action_dispatch/oauth_flow_test.rb +34 -0
  41. data/test/integration/action_dispatch/refresh_token_test.rb +54 -0
  42. data/test/integration/auth_controller_test.rb +8 -7
  43. data/test/integration/client_app_controller_test.rb +24 -0
  44. data/test/integration/docs_controller_test.rb +9 -1
  45. data/test/integration/oauth_test.rb +1 -4
  46. data/test/integration/refresh_token_test.rb +32 -0
  47. data/test/support/integration_case.rb +10 -1
  48. data/test/test_helper.rb +7 -3
  49. metadata +56 -36
  50. data/app/controllers/oauth/client_application_controller.rb +0 -21
  51. data/app/controllers/opro_application_controller.rb +0 -8
  52. data/test/integration/client_application_controller_test.rb +0 -24
@@ -15,6 +15,7 @@ module Opro
15
15
 
16
16
  def opro_authenticate_user!
17
17
  Opro.authenticate_user_method.call(self)
18
+ true
18
19
  end
19
20
 
20
21
  module ClassMethods
@@ -37,7 +38,11 @@ module Opro
37
38
 
38
39
  # returns boolean if oauth request
39
40
  def valid_oauth?
40
- oauth? && oauth_user.present? && oauth_client_has_permissions?
41
+ oauth? && oauth_user.present? && oauth_client_not_expired? && oauth_client_has_permissions?
42
+ end
43
+
44
+ def oauth_client_not_expired?
45
+ oauth_access_grant.not_expired?
41
46
  end
42
47
 
43
48
  def disallow_oauth
@@ -53,7 +58,7 @@ module Opro
53
58
  end
54
59
 
55
60
  def oauth_access_grant
56
- @oauth_access_grant ||= Oauth::AccessGrant.find_for_token(params[:access_token])
61
+ @oauth_access_grant ||= Oauth::AuthGrant.find_for_token(params[:access_token])
57
62
  end
58
63
 
59
64
  def oauth_client_app
data/lib/opro/engine.rb CHANGED
@@ -1,5 +1,9 @@
1
+ require 'opro/rails/routes'
2
+
1
3
  module Opro
2
4
  class Engine < Rails::Engine
5
+ isolate_namespace Opro
6
+
3
7
 
4
8
  initializer "opro.include_helpers" do
5
9
  Opro.include_helpers(Opro::Controllers)
@@ -0,0 +1,17 @@
1
+ module ActionDispatch::Routing
2
+ class Mapper
3
+ # Includes mount_opro_oauth method for routes. This method is responsible to
4
+ # generate all needed routes for oauth
5
+ def mount_opro_oauth(options = {})
6
+ skip_routes = options[:except].is_a?(Array) ? options[:except] : [options[:except]]
7
+
8
+ match 'oauth/new' => 'oauth/auth#new', :as => 'oauth_new'
9
+ match 'oauth/authorize' => 'oauth/auth#create', :as => 'oauth_authorize'
10
+ match 'oauth/token' => 'oauth/token#create', :as => 'oauth_token'
11
+
12
+ resources :oauth_docs, :controller => 'oauth/docs' unless skip_routes.include?(:docs)
13
+ resources :oauth_tests, :controller => 'oauth/tests' unless skip_routes.include?(:tests)
14
+ resources :oauth_client_apps, :controller => 'oauth/client_app' unless skip_routes.include?(:client_apps)
15
+ end
16
+ end
17
+ end
data/opro.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "opro"
8
- s.version = "0.0.1"
8
+ s.version = "0.0.2"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["schneems"]
12
- s.date = "2012-06-14"
12
+ s.date = "2012-06-18"
13
13
  s.description = " Enable OAuth clients (iphone, android, web sites, etc.) to access and use your Rails application, what you do with it is up to you"
14
14
  s.email = "richard.schneeman@gmail.com"
15
15
  s.extra_rdoc_files = [
@@ -24,20 +24,23 @@ Gem::Specification.new do |s|
24
24
  "Rakefile",
25
25
  "VERSION",
26
26
  "app/controllers/oauth/auth_controller.rb",
27
- "app/controllers/oauth/client_application_controller.rb",
27
+ "app/controllers/oauth/client_app_controller.rb",
28
28
  "app/controllers/oauth/docs_controller.rb",
29
29
  "app/controllers/oauth/tests_controller.rb",
30
- "app/controllers/opro_application_controller.rb",
30
+ "app/controllers/oauth/token_controller.rb",
31
+ "app/controllers/opro_controller.rb",
31
32
  "app/models/oauth/access_grant.rb",
32
- "app/models/oauth/client_application.rb",
33
+ "app/models/oauth/client_appl.rb",
33
34
  "app/views/oauth/auth/new.html.erb",
34
- "app/views/oauth/client_application/create.html.erb",
35
- "app/views/oauth/client_application/index.html.erb",
36
- "app/views/oauth/client_application/new.html.erb",
35
+ "app/views/oauth/client_app/create.html.erb",
36
+ "app/views/oauth/client_app/index.html.erb",
37
+ "app/views/oauth/client_app/new.html.erb",
37
38
  "app/views/oauth/docs/index.html.erb",
38
39
  "app/views/oauth/docs/markdown/curl.md.erb",
39
40
  "app/views/oauth/docs/markdown/oauth.md.erb",
41
+ "app/views/oauth/docs/markdown/permissions.md.erb",
40
42
  "app/views/oauth/docs/markdown/quick_start.md.erb",
43
+ "app/views/oauth/docs/markdown/refresh_tokens.md.erb",
41
44
  "app/views/oauth/docs/show.html.erb",
42
45
  "app/views/oauth/tests/index.html.erb",
43
46
  "config/routes.rb",
@@ -51,8 +54,10 @@ Gem::Specification.new do |s|
51
54
  "lib/opro/controllers/concerns/error_messages.rb",
52
55
  "lib/opro/controllers/concerns/permissions.rb",
53
56
  "lib/opro/engine.rb",
57
+ "lib/opro/rails/routes.rb",
54
58
  "opro.gemspec",
55
59
  "test/controllers/permissions_test.rb",
60
+ "test/controllers/refresh_token_test.rb",
56
61
  "test/dummy/Rakefile",
57
62
  "test/dummy/app/controllers/application_controller.rb",
58
63
  "test/dummy/app/controllers/pages_controller.rb",
@@ -96,10 +101,14 @@ Gem::Specification.new do |s|
96
101
  "test/dummy/public/javascripts/rails.js",
97
102
  "test/dummy/public/stylesheets/.gitkeep",
98
103
  "test/dummy/script/rails",
104
+ "test/integration/action_dispatch/auth_controller_test.rb",
105
+ "test/integration/action_dispatch/oauth_flow_test.rb",
106
+ "test/integration/action_dispatch/refresh_token_test.rb",
99
107
  "test/integration/auth_controller_test.rb",
100
- "test/integration/client_application_controller_test.rb",
108
+ "test/integration/client_app_controller_test.rb",
101
109
  "test/integration/docs_controller_test.rb",
102
110
  "test/integration/oauth_test.rb",
111
+ "test/integration/refresh_token_test.rb",
103
112
  "test/opro_test.rb",
104
113
  "test/support/integration_case.rb",
105
114
  "test/test_helper.rb"
@@ -114,10 +123,11 @@ Gem::Specification.new do |s|
114
123
  s.specification_version = 3
115
124
 
116
125
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
117
- s.add_runtime_dependency(%q<activesupport>, [">= 3.0.7"])
118
- s.add_runtime_dependency(%q<rails>, [">= 3.0.7"])
126
+ s.add_runtime_dependency(%q<activesupport>, [">= 3.1.0"])
127
+ s.add_runtime_dependency(%q<rails>, [">= 3.1.0"])
119
128
  s.add_runtime_dependency(%q<bluecloth>, [">= 0"])
120
129
  s.add_development_dependency(%q<mocha>, [">= 0"])
130
+ s.add_development_dependency(%q<timecop>, [">= 0"])
121
131
  s.add_development_dependency(%q<jeweler>, ["~> 1.6.4"])
122
132
  s.add_development_dependency(%q<bundler>, [">= 1.1.3"])
123
133
  s.add_development_dependency(%q<capybara>, [">= 0.4.0"])
@@ -127,10 +137,11 @@ Gem::Specification.new do |s|
127
137
  s.add_development_dependency(%q<rcov>, [">= 0"])
128
138
  s.add_development_dependency(%q<simplecov>, [">= 0"])
129
139
  else
130
- s.add_dependency(%q<activesupport>, [">= 3.0.7"])
131
- s.add_dependency(%q<rails>, [">= 3.0.7"])
140
+ s.add_dependency(%q<activesupport>, [">= 3.1.0"])
141
+ s.add_dependency(%q<rails>, [">= 3.1.0"])
132
142
  s.add_dependency(%q<bluecloth>, [">= 0"])
133
143
  s.add_dependency(%q<mocha>, [">= 0"])
144
+ s.add_dependency(%q<timecop>, [">= 0"])
134
145
  s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
135
146
  s.add_dependency(%q<bundler>, [">= 1.1.3"])
136
147
  s.add_dependency(%q<capybara>, [">= 0.4.0"])
@@ -141,10 +152,11 @@ Gem::Specification.new do |s|
141
152
  s.add_dependency(%q<simplecov>, [">= 0"])
142
153
  end
143
154
  else
144
- s.add_dependency(%q<activesupport>, [">= 3.0.7"])
145
- s.add_dependency(%q<rails>, [">= 3.0.7"])
155
+ s.add_dependency(%q<activesupport>, [">= 3.1.0"])
156
+ s.add_dependency(%q<rails>, [">= 3.1.0"])
146
157
  s.add_dependency(%q<bluecloth>, [">= 0"])
147
158
  s.add_dependency(%q<mocha>, [">= 0"])
159
+ s.add_dependency(%q<timecop>, [">= 0"])
148
160
  s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
149
161
  s.add_dependency(%q<bundler>, [">= 1.1.3"])
150
162
  s.add_dependency(%q<capybara>, [">= 0.4.0"])
File without changes
@@ -10,6 +10,10 @@ Dummy::Application.configure do
10
10
  # Log error messages when you accidentally call methods on nil.
11
11
  config.whiny_nils = true
12
12
 
13
+
14
+ config.log_level = :debug
15
+
16
+
13
17
  # Show full error reports and disable caching
14
18
  config.consider_all_requests_local = true
15
19
  config.action_controller.perform_caching = false
@@ -3,8 +3,15 @@ Opro.setup do |config|
3
3
  config.auth_strategy = :devise
4
4
 
5
5
  ## Add or remove application permissions
6
- # Read permission is turned on by default (any request with [GET])
7
- # Write permission is requestable by default (any request other than [GET])
8
- # Custom permissions can be configured by adding them to the request_permissions Array and configuring require_oauth_permissions in the controller
6
+ # Read permission (any request with [GET]) is turned on by default
7
+ # Write permission (any request other than [GET]) is requestable by default
8
+ # Custom permissions can be configured by adding them to `config.request_permissions`
9
+ # You can then require that permission on individual actions by calling
10
+ # `require_oauth_permissions` in the controller
9
11
  config.request_permissions = [:write]
12
+
13
+ ## Refresh Token config
14
+ # uncomment `config.require_refresh_within` to require refresh tokens
15
+ # this will expire tokens within the given time duration
16
+ # config.require_refresh_within = 1.month
10
17
  end
@@ -1,4 +1,6 @@
1
1
  Dummy::Application.routes.draw do
2
+ mount_opro_oauth
3
+
2
4
  devise_for :users
3
5
 
4
6
  resources :foo
@@ -1,4 +1,4 @@
1
- class CreateOproAccessGrants < ActiveRecord::Migration
1
+ class CreateOproAuthGrants < ActiveRecord::Migration
2
2
  def change
3
3
  create_table :opro_access_grants do |t|
4
4
  t.string :code
@@ -1,4 +1,4 @@
1
- class CreateOproClientApplications < ActiveRecord::Migration
1
+ class CreateOproClientApps < ActiveRecord::Migration
2
2
  def change
3
3
  create_table :opro_client_applications do |t|
4
4
  t.string :name
@@ -0,0 +1,64 @@
1
+ ## NOT CAPYBARA
2
+ # ActionDispatch::IntegrationTest
3
+ # http://guides.rubyonrails.org/testing.html#integration-testing
4
+ # used so we can test POST actions ^_^
5
+
6
+ require 'test_helper'
7
+
8
+ class AuthControllerTest < ActionDispatch::IntegrationTest
9
+ setup do
10
+ @user = create_user
11
+ @client_app = create_client_app
12
+ @redirect_uri = '/'
13
+ end
14
+
15
+
16
+ test "AUTHORIZE: previously authed user gets Authed immediately, permissions not changed" do
17
+ auth_grant = create_auth_grant_for_user(@user, @client_app)
18
+
19
+ params = { :client_id => @client_app.client_id ,
20
+ :client_secret => @client_app.client_secret,
21
+ :redirect_uri => @redirect_uri }
22
+
23
+ as_user(@user).post oauth_authorize_path(params)
24
+
25
+ assert_equal 302, status
26
+ follow_redirect!
27
+ assert_equal @redirect_uri, path
28
+ end
29
+
30
+
31
+ test "AUTHORIZE: app cannot force permissions change for previously authed user" do
32
+ auth_grant = create_auth_grant_for_user(@user, @client_app)
33
+ permissions = { 'foo' => 1 }
34
+ assert_not_equal auth_grant.permissions, permissions
35
+
36
+ params = { :client_id => @client_app.client_id ,
37
+ :client_secret => @client_app.client_secret,
38
+ :redirect_uri => @redirect_uri,
39
+ :permissions => permissions }
40
+
41
+ as_user(@user).post oauth_authorize_path(params)
42
+
43
+ assert_equal 302, status
44
+ follow_redirect!
45
+ assert_equal @redirect_uri, path
46
+ auth_grant = Oauth::AuthGrant.find(auth_grant.id)
47
+
48
+ refute auth_grant.permissions.has_key?(permissions.keys.first)
49
+ end
50
+
51
+
52
+ test "AUTHORIZE: user gets redirected to new form if not already authed" do
53
+ params = { :client_id => @client_app.client_id ,
54
+ :client_secret => @client_app.client_secret,
55
+ :redirect_uri => @redirect_uri }
56
+
57
+ as_user(@user).post oauth_authorize_path(params)
58
+
59
+ assert_equal 302, status
60
+ follow_redirect!
61
+ assert_equal oauth_new_path, path
62
+ end
63
+
64
+ end
@@ -0,0 +1,34 @@
1
+ ## NOT CAPYBARA
2
+ # ActionDispatch::IntegrationTest
3
+ # http://guides.rubyonrails.org/testing.html#integration-testing
4
+ # used so we can test POST actions ^_^
5
+
6
+ require 'test_helper'
7
+
8
+ class OauthTokenTest < ActionDispatch::IntegrationTest
9
+ setup do
10
+ @user = create_user
11
+ end
12
+
13
+
14
+ test "exchange a code for a token" do
15
+ user = create_user
16
+ auth_grant = create_auth_grant_for_user(user)
17
+ client = auth_grant.application
18
+ params = {:code => auth_grant.code,
19
+ :client_id => client.client_id,
20
+ :client_secret => client.client_secret}
21
+
22
+
23
+ as_user(@user).post oauth_token_path(params)
24
+
25
+ json_hash = JSON.parse(response.body)
26
+ assert json_hash["access_token"]
27
+ assert json_hash["access_token"], auth_grant.access_token
28
+
29
+ assert json_hash["refresh_token"]
30
+ assert json_hash["refresh_token"], auth_grant.refresh_token
31
+ end
32
+
33
+ end
34
+
@@ -0,0 +1,54 @@
1
+ ## NOT CAPYBARA
2
+ # ActionDispatch::IntegrationTest
3
+ # http://guides.rubyonrails.org/testing.html#integration-testing
4
+ # used so we can test POST actions ^_^
5
+
6
+ require 'test_helper'
7
+
8
+ class RefreshTokenTest < ActionDispatch::IntegrationTest
9
+ setup do
10
+ Timecop.freeze(Time.now)
11
+ Opro.setup do |config|
12
+ config.require_refresh_within = 1.month
13
+ end
14
+
15
+ @user = create_user
16
+ @auth_grant = create_auth_grant_for_user(@user)
17
+ @client_app = @auth_grant.application
18
+ end
19
+
20
+ teardown do
21
+ Timecop.return # "turn off" Timecop
22
+ end
23
+
24
+ test "clients get a valid refresh token" do
25
+ params = {:client_id => @client_app.client_id ,
26
+ :client_secret => @client_app.client_secret,
27
+ :code => @auth_grant.code}
28
+ as_user(@user).post oauth_token_path(params)
29
+ json_hash = JSON.parse(response.body)
30
+ assert_equal json_hash['expires_in'], @auth_grant.expires_in
31
+ end
32
+
33
+ test "exchange a refresh_token for an access_token" do
34
+ params = {:client_id => @client_app.client_id ,
35
+ :client_secret => @client_app.client_secret,
36
+ :refresh_token => @auth_grant.refresh_token}
37
+
38
+ Timecop.travel(2.days.from_now)
39
+
40
+ as_user(@user).post oauth_token_path(params)
41
+
42
+ json_hash = JSON.parse(response.body)
43
+ refute_equal json_hash['access_token'], @auth_grant.access_token
44
+ refute_equal json_hash['refresh_token'], @auth_grant.refresh_token
45
+ refute_equal json_hash['expires_in'], @auth_grant.expires_in
46
+
47
+
48
+ auth_grant = Oauth::AuthGrant.find(@auth_grant.id)
49
+ assert_equal json_hash['access_token'], auth_grant.access_token
50
+ assert_equal json_hash['refresh_token'], auth_grant.refresh_token
51
+ assert_equal json_hash['expires_in'], auth_grant.expires_in
52
+ end
53
+
54
+ end
@@ -1,6 +1,6 @@
1
1
  require 'test_helper'
2
2
 
3
- class AuthControllerTest < ActiveSupport::IntegrationCase
3
+ class CapybaraAuthControllerTest < ActiveSupport::IntegrationCase
4
4
 
5
5
  setup do
6
6
  @app = create_client_app
@@ -14,13 +14,14 @@ class AuthControllerTest < ActiveSupport::IntegrationCase
14
14
  end
15
15
 
16
16
  test 'auth entry point is accessible to logged IN users' do
17
+ as_user(@user) do
18
+ visit oauth_new_path(:client_id => @app.client_id, :redirect_uri => @redirect_uri)
17
19
 
18
- as_user(@user).visit oauth_new_path(:client_id => @app.client_id, :redirect_uri => @redirect_uri)
19
-
20
- assert_equal '/oauth/new', current_path
20
+ assert_equal '/oauth/new', current_path
21
+ click_button 'oauthAuthorize'
22
+ end
21
23
 
22
- click_button 'oauthAuthorize'
23
- access_grant = Oauth::AccessGrant.where(:user_id => @user.id, :application_id => @app.id).first
24
+ access_grant = Oauth::AuthGrant.where(:user_id => @user.id, :application_id => @app.id).first
24
25
  assert_equal @redirect_uri, current_path
25
26
  assert access_grant.present?
26
27
  assert access_grant.can?(:write) # write access is checked by default
@@ -31,7 +32,7 @@ class AuthControllerTest < ActiveSupport::IntegrationCase
31
32
 
32
33
  uncheck('permissions_write') # uncheck write access
33
34
  click_button 'oauthAuthorize'
34
- access_grant = Oauth::AccessGrant.where(:user_id => @user.id, :application_id => @app.id).first
35
+ access_grant = Oauth::AuthGrant.where(:user_id => @user.id, :application_id => @app.id).first
35
36
  refute access_grant.can?(:write)
36
37
  end
37
38
  end
@@ -0,0 +1,24 @@
1
+ require 'test_helper'
2
+
3
+ class ClientAppControllerTest < ActiveSupport::IntegrationCase
4
+ test 'must be logged in' do
5
+ visit new_oauth_client_app_path
6
+ assert_equal '/users/sign_in', current_path
7
+ end
8
+
9
+ test 'create client application' do
10
+ user = create_user
11
+ as_user(user).visit new_oauth_client_app_path
12
+ assert_equal '/oauth_client_apps/new', current_path
13
+
14
+ fill_in 'oauth_client_app_name', :with => rand_name
15
+
16
+ click_button 'submitApp'
17
+ assert_equal '/oauth_client_apps', current_path
18
+
19
+ last_client = Oauth::ClientApp.order(:created_at).last
20
+ assert has_content?(last_client.name)
21
+ assert has_content?(last_client.client_id)
22
+ assert has_content?(last_client.client_secret)
23
+ end
24
+ end