opro 0.0.1.pre1.0.2 → 0.0.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.
Files changed (30) hide show
  1. data/Gemfile +1 -0
  2. data/Gemfile.lock +4 -0
  3. data/app/controllers/oauth/auth_controller.rb +10 -0
  4. data/app/controllers/oauth/tests_controller.rb +31 -3
  5. data/app/controllers/opro_application_controller.rb +1 -1
  6. data/app/models/oauth/access_grant.rb +11 -1
  7. data/app/models/oauth/client_application.rb +4 -0
  8. data/app/views/oauth/auth/new.html.erb +24 -4
  9. data/app/views/oauth/tests/index.html.erb +1 -1
  10. data/lib/generators/active_record/templates/access_grants.rb +8 -7
  11. data/lib/generators/active_record/templates/client_applications.rb +1 -0
  12. data/lib/generators/templates/opro.rb +8 -2
  13. data/lib/opro.rb +14 -5
  14. data/lib/opro/controllers/application_controller_helper.rb +17 -4
  15. data/lib/opro/controllers/concerns/error_messages.rb +23 -0
  16. data/lib/opro/controllers/concerns/permissions.rb +89 -0
  17. data/opro.gemspec +13 -5
  18. data/test/controllers/permissions_test.rb +27 -0
  19. data/test/dummy/app/controllers/products_controller.rb +8 -0
  20. data/test/dummy/app/views/pages/index.html.erb +2 -1
  21. data/test/dummy/app/views/products/create.html.erb +1 -0
  22. data/test/dummy/config/initializers/opro.rb +7 -1
  23. data/test/dummy/config/routes.rb +2 -0
  24. data/test/dummy/db/migrate/20120514060322_create_opro_access_grants.rb +15 -0
  25. data/test/dummy/db/migrate/{20120408165730_create_opro_client_applications.rb → 20120514060323_create_opro_client_applications.rb} +1 -0
  26. data/test/dummy/db/schema.rb +5 -3
  27. data/test/integration/auth_controller_test.rb +22 -8
  28. data/test/test_helper.rb +1 -3
  29. metadata +46 -30
  30. data/test/dummy/db/migrate/20120408165729_create_opro_access_grants.rb +0 -14
data/Gemfile CHANGED
@@ -7,6 +7,7 @@ gem "rails" , ">= 3.0.7"
7
7
  gem 'bluecloth'
8
8
 
9
9
  group :development, :test do
10
+ gem 'mocha'
10
11
  gem 'jeweler', "~> 1.6.4"
11
12
  gem "bundler", ">= 1.1.3"
12
13
 
@@ -64,7 +64,10 @@ GEM
64
64
  i18n (>= 0.4.0)
65
65
  mime-types (~> 1.16)
66
66
  treetop (~> 1.4.8)
67
+ metaclass (0.0.1)
67
68
  mime-types (1.18)
69
+ mocha (0.11.4)
70
+ metaclass (~> 0.0.1)
68
71
  multi_json (1.2.0)
69
72
  nokogiri (1.5.2)
70
73
  orm_adapter (0.0.7)
@@ -132,6 +135,7 @@ DEPENDENCIES
132
135
  devise
133
136
  jeweler (~> 1.6.4)
134
137
  launchy
138
+ mocha
135
139
  rails (>= 3.0.7)
136
140
  rcov
137
141
  simplecov
@@ -6,12 +6,15 @@ class Oauth::AuthController < ApplicationController
6
6
  def new
7
7
  @redirect_uri = params[:redirect_uri]
8
8
  @client_app = Oauth::ClientApplication.find_by_app_id(params[:client_id])
9
+ @scopes = scope_from_params(params)
9
10
  end
10
11
 
11
12
  def authorize
12
13
  application = Oauth::ClientApplication.find_by_app_id(params[:client_id])
14
+ permissions = params[:permissions]
13
15
  access_grant = Oauth::AccessGrant.where( :user_id => current_user.id, :application_id => application.id).first
14
16
  access_grant ||= Oauth::AccessGrant.create(:user => current_user, :application => application)
17
+ access_grant.update_attributes(:permissions => permissions) if access_grant.permissions != permissions
15
18
  redirect_to access_grant.redirect_uri_for(params[:redirect_uri])
16
19
  end
17
20
 
@@ -57,6 +60,13 @@ class Oauth::AuthController < ApplicationController
57
60
  Oauth::AccessGrant.where(:application_id => @client_app.id, :user_id => user.id).present?
58
61
  end
59
62
 
63
+ def scope_from_params(params)
64
+ requested_scope = (params[:scope]||[]).map(&:downcase)
65
+ default_scope = ::Opro.request_permissions.map(&:to_s).map(&:downcase)
66
+ return default_scope if requested_scope.blank?
67
+ requested_scope & default_scope
68
+ end
69
+
60
70
 
61
71
  # We're verifying that a post was made from our own site, indicating a user confirmed via form
62
72
  def user_authorizes_the_request?(request)
@@ -23,6 +23,23 @@ class Oauth::TestsController < ApplicationController
23
23
  end
24
24
  end
25
25
 
26
+ def create
27
+ result = if valid_oauth?
28
+ {:status => 200, :message => 'OAuth Worked!!', :params => params, :user_id => oauth_user.id }
29
+ else
30
+ {:status => 401, :message => "OAuth Did not Work D: #{generate_oauth_error_message!}", :params => params}
31
+ end
32
+
33
+ respond_to do |format|
34
+ format.html do
35
+ render :text => result.to_json, :status => result[:status], :layout => true
36
+ end
37
+ format.json do
38
+ render :json => result, :status => result[:status]
39
+ end
40
+ end
41
+ end
42
+
26
43
  def destroy
27
44
  result = if valid_oauth?
28
45
  {:status => 200, :message => 'OHNO!!! OAuth is Disabled on this Action, this is bad', :params => params}
@@ -44,9 +61,20 @@ class Oauth::TestsController < ApplicationController
44
61
 
45
62
  def generate_oauth_error_message!
46
63
  msg = ""
47
- msg << ' - No OAuth Token Provided!' if params[:access_token].blank?
48
- msg << ' - Allow OAuth set to false!' if allow_oauth? == false
49
- msg << ' - OAuth user not found!' if oauth_user.blank?
64
+ msg << ' - No OAuth Token Provided!' if params[:access_token].blank?
65
+ msg << ' - Allow OAuth set to false!' if allow_oauth? == false
66
+ msg << ' - OAuth user not found!' if oauth_user.blank?
67
+ generate_oauth_permissions_error_message!(msg)
68
+ msg
69
+ end
70
+
71
+ def generate_oauth_permissions_error_message!(msg = '')
72
+ if !oauth_client_has_permissions?
73
+ msg << ' - OAuth client not permitted'
74
+ oauth_required_permissions.each do |permission|
75
+ msg << "- #{permission} permission required;" unless oauth_client_has_permission?(permission)
76
+ end
77
+ end
50
78
  msg
51
79
  end
52
80
 
@@ -1,7 +1,7 @@
1
1
  class ApplicationController < ActionController::Base
2
2
 
3
3
  # Any code that would/should go into ApplicationController is
4
- # no in lib/opro/conrollers/application_controller_helper.rb
4
+ # now in lib/opro/conrollers/application_controller_helper.rb
5
5
  # it is loaded into ApplicationController in lib/opro/engine.rb
6
6
  # thanks for visiting, come back soon
7
7
 
@@ -12,13 +12,23 @@ class Oauth::AccessGrant < ActiveRecord::Base
12
12
 
13
13
  alias_attribute :token, :access_token
14
14
 
15
+ serialize :permissions, Hash
16
+
17
+ def can?(value)
18
+ permissions[value.to_s]
19
+ end
20
+
15
21
  def self.prune!
16
22
  # UPDATEME
17
23
  # delete_all(["created_at < ?", 3.days.ago])
18
24
  end
19
25
 
26
+ def self.find_for_token(token)
27
+ self.where(:access_token => token).includes(:user, :client_application).first
28
+ end
29
+
20
30
  def self.find_user_for_token(token)
21
- self.where(:access_token => token).first.try(:user)
31
+ find_app_for_token.try(:user)
22
32
  end
23
33
 
24
34
  def self.authenticate(code, application_id)
@@ -10,6 +10,10 @@ class Oauth::ClientApplication < ActiveRecord::Base
10
10
  alias_attribute :client_secret, :app_secret
11
11
  alias_attribute :secret, :app_secret
12
12
 
13
+ serialize :permissions, Hash
14
+
15
+
16
+
13
17
  def self.authenticate(app_id, app_secret)
14
18
  where(["app_id = ? AND app_secret = ?", app_id, app_secret]).first
15
19
  end
@@ -1,8 +1,28 @@
1
- <h2><%= @client_app.name %> Would like to access your Data</h2>
2
- Do not accept if you do not know them or you would not like to authorize this url: <%= @redirect_uri %>
1
+ <h2>Authorization Request</h2>
2
+
3
+
4
+ <p>
5
+ <%= @client_app.name %> would like to access your Data. Only accept if you know them, you will then be redirected back to: "<%= @redirect_uri %>".
6
+ </p>
3
7
 
4
8
  <%= form_for @client_app, :url => oauth_authorize_path(:client_id => @client_app.client_id, :redirect_uri => @redirect_uri), :method => :post do |f| %>
5
- <%= f.submit 'I Authorize This Application', :id => 'oauthAuthorize' %>
9
+
10
+
11
+ I Authorize <%= @client_app.name %> to:
12
+
13
+
14
+ <ul>
15
+
16
+ <li><%= check_box_tag 'permissions[read]', 1, true, {:disabled => true} %> Read</li>
17
+
18
+ <% @scopes.each do |permission| %>
19
+ <% is_checked = @client_app.permissions.key?(permission) ? @client_app.permissions[permission] : true %>
20
+ <li><%= check_box_tag "permissions[#{permission}]", 1, is_checked %> <%= permission.capitalize %></li>
21
+ <% end %>
22
+ </ul>
23
+
24
+ <%= f.submit 'Authorize This Application', :id => 'oauthAuthorize' %>
6
25
  <%- end -%>
7
26
 
8
- <%= button_to 'I Do Not Authorize This Application', request.referrer, :id => 'oauthNoAuthorize' %>
27
+ <%= button_to 'Decline this Request', request.referrer, :id => 'oauthNoAuthorize' %>
28
+
@@ -15,7 +15,7 @@
15
15
  <h2>Test OAuth Disallow</h2>
16
16
  <p>
17
17
  If you send a valid OAuth request using the 'DELETE' HTTP method to <%= oauth_test_path(:show_me_the_money) %> you should see a response like below.</p>
18
- <%= button_to oauth_test_path(:show_me_the_money), oauth_test_path(:show_me_the_money), :method => :delete %>
18
+ <%= button_to oauth_test_path(:show_me_the_money), oauth_test_path(:show_me_the_money), :method => :delete, :id => 'deleteButton' %>
19
19
  <pre><code><%= {:status => 401, :message => 'Oauth is Disabled on this Action, this is the correct result!', :params => {:id => 'show_me_the_money', :access_token => '3948fuAlo10gnsu'}}.to_json %></code></pre>
20
20
 
21
21
  <p>
@@ -1,12 +1,13 @@
1
1
  class CreateOproAccessGrants < ActiveRecord::Migration
2
2
  def change
3
- create_table :opro_access_grants do |t|
4
- t.string :code
5
- t.string :access_token
6
- t.string :refresh_token
7
- t.datetime :access_token_expires_at
8
- t.integer :user_id
9
- t.integer :application_id
3
+ create_table :opro_access_grants do |t|
4
+ t.string :code
5
+ t.string :access_token
6
+ t.string :refresh_token
7
+ t.text :permissions
8
+ t.datetime :access_token_expires_at
9
+ t.integer :user_id
10
+ t.integer :application_id
10
11
 
11
12
  t.timestamps
12
13
  end
@@ -4,6 +4,7 @@ class CreateOproClientApplications < ActiveRecord::Migration
4
4
  t.string :name
5
5
  t.string :app_id
6
6
  t.string :app_secret
7
+ t.text :permissions
7
8
  t.integer :user_id
8
9
  t.timestamps
9
10
  end
@@ -1,4 +1,10 @@
1
1
  Opro.setup do |config|
2
- ## Uncomment to configure devise
3
- # config.auth_strategy = :devise
2
+ ## Configure the auth_strategy or use set :login_method, :logout_method, & :authenticate_user_method
3
+ config.auth_strategy = :devise
4
+
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
9
+ config.request_permissions = [:write]
4
10
  end
@@ -1,7 +1,9 @@
1
1
  module Opro
2
-
3
2
  module Controllers
3
+ module Concerns
4
+ end
4
5
  end
6
+
5
7
  # Include helpers in the given scope to AC and AV.
6
8
  def self.include_helpers(scope)
7
9
  ActiveSupport.on_load(:action_controller) do
@@ -39,7 +41,7 @@ module Opro
39
41
  logout_method.call(*args)
40
42
  end
41
43
 
42
-
44
+ # Used by set_login_logout_methods to pre-define login, logout, and authenticate methods
43
45
  def self.auth_strategy(auth_strategy = nil)
44
46
  if auth_strategy.present?
45
47
  @auth_strategy = auth_strategy
@@ -61,6 +63,14 @@ module Opro
61
63
  end
62
64
  end
63
65
 
66
+ def self.request_permissions=(permissions)
67
+ @request_permissions = permissions
68
+ end
69
+
70
+ def self.request_permissions
71
+ @request_permissions || []
72
+ end
73
+
64
74
 
65
75
  def self.logout_method(&block)
66
76
  if block.present?
@@ -79,8 +89,7 @@ module Opro
79
89
  end
80
90
  end
81
91
 
82
- # require 'opro/controller/concerns/render_redirect'
83
- # require 'opro/controller/concerns/steps'
84
- # require 'opro/controller/concerns/path'
92
+ require 'opro/controllers/concerns/error_messages'
93
+ require 'opro/controllers/concerns/permissions'
85
94
  require 'opro/controllers/application_controller_helper'
86
95
  require 'opro/engine'
@@ -5,6 +5,9 @@ module Opro
5
5
  module ApplicationControllerHelper
6
6
  extend ActiveSupport::Concern
7
7
 
8
+ include Opro::Controllers::Concerns::Permissions
9
+ include Opro::Controllers::Concerns::ErrorMessages
10
+
8
11
  included do
9
12
  around_filter :oauth_auth!
10
13
  skip_before_filter :verify_authenticity_token, :if => :valid_oauth?
@@ -23,6 +26,7 @@ module Opro
23
26
  prepend_before_filter :disallow_oauth, options
24
27
  skip_before_filter :allow_oauth, options
25
28
  end
29
+
26
30
  end
27
31
 
28
32
  protected
@@ -31,6 +35,11 @@ module Opro
31
35
  @use_oauth ||= false
32
36
  end
33
37
 
38
+ # returns boolean if oauth request
39
+ def valid_oauth?
40
+ oauth? && oauth_user.present? && oauth_client_has_permissions?
41
+ end
42
+
34
43
  def disallow_oauth
35
44
  @use_oauth = false
36
45
  end
@@ -43,12 +52,16 @@ module Opro
43
52
  allow_oauth? && params[:access_token].present?
44
53
  end
45
54
 
46
- def oauth_user
47
- @oauth_user ||= Oauth::AccessGrant.find_user_for_token(params[:access_token])
55
+ def oauth_access_grant
56
+ @oauth_access_grant ||= Oauth::AccessGrant.find_for_token(params[:access_token])
48
57
  end
49
58
 
50
- def valid_oauth?
51
- oauth? && oauth_user.present?
59
+ def oauth_client_app
60
+ @oauth_client_app ||= oauth_access_grant.client_application
61
+ end
62
+
63
+ def oauth_user
64
+ @oauth_user ||= oauth_access_grant.user
52
65
  end
53
66
 
54
67
  def oauth_auth!
@@ -0,0 +1,23 @@
1
+ module Opro::Controllers::Concerns::ErrorMessages
2
+ extend ActiveSupport::Concern
3
+
4
+ def generate_oauth_error_message!
5
+ msg = ""
6
+ msg << ' - No OAuth Token Provided!' if params[:access_token].blank?
7
+ msg << ' - Allow OAuth set to false!' if allow_oauth? == false
8
+ msg << ' - OAuth user not found!' if oauth_user.blank?
9
+ msg = generate_oauth_permissions_error_message!(msg)
10
+ msg
11
+ end
12
+
13
+ def generate_oauth_permissions_error_message!(msg = '')
14
+ if !oauth_client_has_permissions?
15
+ msg << ' - OAuth client not permitted'
16
+ oauth_required_permissions.each do |permission|
17
+ msg << "- #{permission} permission required;" unless oauth_client_has_permission?(permission)
18
+ end
19
+ end
20
+ msg
21
+ end
22
+
23
+ end
@@ -0,0 +1,89 @@
1
+ module Opro::Controllers::Concerns::Permissions
2
+ extend ActiveSupport::Concern
3
+
4
+ # By default :write permission is required if included in Opro.request_permissions
5
+ # returns Array
6
+ def global_oauth_required_permissions
7
+ [:write] & Opro.request_permissions
8
+ end
9
+
10
+ # returns Array of permissions required for controller action
11
+ def oauth_required_permissions
12
+ (@oauth_required_permissions || global_oauth_required_permissions) - skip_oauth_required_permissions
13
+ end
14
+
15
+ def skip_oauth_required_permissions
16
+ @skip_oauth_required_permissions ||= []
17
+ end
18
+
19
+ def skip_oauth_required_permission(permission)
20
+ @skip_oauth_required_permissions << permission
21
+ @skip_oauth_required_permissions
22
+ end
23
+
24
+ def add_oauth_required_permission(permission)
25
+ @oauth_required_permissions ||= global_oauth_required_permissions
26
+ @oauth_required_permissions << permission
27
+ end
28
+
29
+ # Checks to make sure client has given permission
30
+ # permission checks can be extended by creating methods
31
+ # oauth_client_can_:method? so to over-write a default check for
32
+ # :write permission, you would need to define oauth_client_can_write?
33
+ def oauth_client_has_permissions?
34
+ permissions_valid_array = []
35
+ oauth_required_permissions.each do |permission|
36
+ permissions_valid_array << oauth_client_has_permission?(permission)
37
+ end
38
+
39
+ return true unless permissions_valid_array.include?(false)
40
+ false
41
+ end
42
+
43
+ def oauth_client_has_permission?(permission)
44
+ oauth_permission_method = "oauth_client_can_#{permission}?".to_sym
45
+ if respond_to?(oauth_permission_method)
46
+ has_permission = method(oauth_permission_method).call
47
+ else
48
+ has_permission = oauth_access_grant.can?(permission.to_sym)
49
+ end
50
+ has_permission
51
+ end
52
+
53
+ # Returns boolean
54
+ # if client has been granted write permissions or request is a 'GET' returns true
55
+ def oauth_client_can_write?
56
+ return true if env['REQUEST_METHOD'] == 'GET'
57
+ return true if oauth_access_grant.can?(:write)
58
+ false
59
+ end
60
+
61
+
62
+ module ClassMethods
63
+
64
+ def skip_oauth_permissions(*args)
65
+ options = args.last.is_a?(Hash) ? callbacks.pop : {}
66
+ permissions = args
67
+ prepend_before_filter(options) do
68
+ permissions.each do |permission|
69
+ controller.skip_oauth_required_permission(permission)
70
+ end
71
+ end
72
+ end
73
+ alias :skip_oauth_permission :skip_oauth_permissions
74
+
75
+ # pass in array of permissions to be validated, add options to pass to filter
76
+ def require_oauth_permissions(*args)
77
+ options = args.last.is_a?(Hash) ? args.pop : {}
78
+ permissions = args
79
+ prepend_before_filter(options) do
80
+ permissions.each do |permission|
81
+ raise "You must add #{permission.inspect} to the Opro request_permissions in an initializer" unless Opro.request_permissions.include?(permission)
82
+ controller.add_oauth_required_permission(permission)
83
+ end
84
+ end
85
+ end
86
+ alias :require_oauth_permission :require_oauth_permissions
87
+ end
88
+
89
+ end
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "opro"
8
- s.version = "0.0.1.pre1.0.2"
8
+ s.version = "0.0.1"
9
9
 
10
- s.required_rubygems_version = Gem::Requirement.new("> 1.3.1") if s.respond_to? :required_rubygems_version=
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-04-13"
12
+ s.date = "2012-06-14"
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 = [
@@ -48,15 +48,20 @@ Gem::Specification.new do |s|
48
48
  "lib/generators/templates/opro.rb",
49
49
  "lib/opro.rb",
50
50
  "lib/opro/controllers/application_controller_helper.rb",
51
+ "lib/opro/controllers/concerns/error_messages.rb",
52
+ "lib/opro/controllers/concerns/permissions.rb",
51
53
  "lib/opro/engine.rb",
52
54
  "opro.gemspec",
55
+ "test/controllers/permissions_test.rb",
53
56
  "test/dummy/Rakefile",
54
57
  "test/dummy/app/controllers/application_controller.rb",
55
58
  "test/dummy/app/controllers/pages_controller.rb",
59
+ "test/dummy/app/controllers/products_controller.rb",
56
60
  "test/dummy/app/helpers/application_helper.rb",
57
61
  "test/dummy/app/models/user.rb",
58
62
  "test/dummy/app/views/layouts/application.html.erb",
59
63
  "test/dummy/app/views/pages/index.html.erb",
64
+ "test/dummy/app/views/products/create.html.erb",
60
65
  "test/dummy/config.ru",
61
66
  "test/dummy/config/application.rb",
62
67
  "test/dummy/config/boot.rb",
@@ -76,8 +81,8 @@ Gem::Specification.new do |s|
76
81
  "test/dummy/config/locales/en.yml",
77
82
  "test/dummy/config/routes.rb",
78
83
  "test/dummy/db/migrate/20120408163038_devise_create_users.rb",
79
- "test/dummy/db/migrate/20120408165729_create_opro_access_grants.rb",
80
- "test/dummy/db/migrate/20120408165730_create_opro_client_applications.rb",
84
+ "test/dummy/db/migrate/20120514060322_create_opro_access_grants.rb",
85
+ "test/dummy/db/migrate/20120514060323_create_opro_client_applications.rb",
81
86
  "test/dummy/db/schema.rb",
82
87
  "test/dummy/public/404.html",
83
88
  "test/dummy/public/422.html",
@@ -112,6 +117,7 @@ Gem::Specification.new do |s|
112
117
  s.add_runtime_dependency(%q<activesupport>, [">= 3.0.7"])
113
118
  s.add_runtime_dependency(%q<rails>, [">= 3.0.7"])
114
119
  s.add_runtime_dependency(%q<bluecloth>, [">= 0"])
120
+ s.add_development_dependency(%q<mocha>, [">= 0"])
115
121
  s.add_development_dependency(%q<jeweler>, ["~> 1.6.4"])
116
122
  s.add_development_dependency(%q<bundler>, [">= 1.1.3"])
117
123
  s.add_development_dependency(%q<capybara>, [">= 0.4.0"])
@@ -124,6 +130,7 @@ Gem::Specification.new do |s|
124
130
  s.add_dependency(%q<activesupport>, [">= 3.0.7"])
125
131
  s.add_dependency(%q<rails>, [">= 3.0.7"])
126
132
  s.add_dependency(%q<bluecloth>, [">= 0"])
133
+ s.add_dependency(%q<mocha>, [">= 0"])
127
134
  s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
128
135
  s.add_dependency(%q<bundler>, [">= 1.1.3"])
129
136
  s.add_dependency(%q<capybara>, [">= 0.4.0"])
@@ -137,6 +144,7 @@ Gem::Specification.new do |s|
137
144
  s.add_dependency(%q<activesupport>, [">= 3.0.7"])
138
145
  s.add_dependency(%q<rails>, [">= 3.0.7"])
139
146
  s.add_dependency(%q<bluecloth>, [">= 0"])
147
+ s.add_dependency(%q<mocha>, [">= 0"])
140
148
  s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
141
149
  s.add_dependency(%q<bundler>, [">= 1.1.3"])
142
150
  s.add_dependency(%q<capybara>, [">= 0.4.0"])
@@ -0,0 +1,27 @@
1
+ require 'test_helper'
2
+
3
+ class Oauth::TestsControllerTest < ActionController::TestCase
4
+ tests Oauth::TestsController
5
+ include Devise::TestHelpers
6
+
7
+ setup do
8
+ @user = create_user
9
+ @auth_grant = create_auth_grant_for_user(@user)
10
+ end
11
+
12
+ test "access_token with write ability can :POST" do
13
+ permissions = {'write' => true}
14
+ @auth_grant.update_attributes(:permissions => permissions)
15
+
16
+ post :create, access_token: @auth_grant.access_token, format: :json
17
+ assert_response :success
18
+ end
19
+
20
+
21
+ test "access_token with NO write ability can NOT POST" do
22
+ permissions = {:write => false}
23
+ @auth_grant.update_attributes(:permissions => permissions)
24
+ post :create, access_token: @auth_grant.access_token, format: :json
25
+ assert_response 401
26
+ end
27
+ end
@@ -0,0 +1,8 @@
1
+ class ProductsController < ApplicationController
2
+ protect_from_forgery
3
+
4
+ def create
5
+ # stub route
6
+ end
7
+
8
+ end
@@ -1 +1,2 @@
1
- Home
1
+ Home
2
+
@@ -1,4 +1,10 @@
1
1
  Opro.setup do |config|
2
- ## Uncomment to configure devise
2
+ ## Configure the auth_strategy or use set :login_method, :logout_method, & :authenticate_user_method
3
3
  config.auth_strategy = :devise
4
+
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
9
+ config.request_permissions = [:write]
4
10
  end
@@ -4,6 +4,8 @@ Dummy::Application.routes.draw do
4
4
  resources :foo
5
5
  resources :bar
6
6
 
7
+ resources :products
8
+
7
9
  # The priority is based upon order of creation:
8
10
  # first created -> highest priority.
9
11
 
@@ -0,0 +1,15 @@
1
+ class CreateOproAccessGrants < ActiveRecord::Migration
2
+ def change
3
+ create_table :opro_access_grants do |t|
4
+ t.string :code
5
+ t.string :access_token
6
+ t.string :refresh_token
7
+ t.text :permissions
8
+ t.datetime :access_token_expires_at
9
+ t.integer :user_id
10
+ t.integer :application_id
11
+
12
+ t.timestamps
13
+ end
14
+ end
15
+ end
@@ -4,6 +4,7 @@ class CreateOproClientApplications < ActiveRecord::Migration
4
4
  t.string :name
5
5
  t.string :app_id
6
6
  t.string :app_secret
7
+ t.text :permissions
7
8
  t.integer :user_id
8
9
  t.timestamps
9
10
  end
@@ -11,12 +11,13 @@
11
11
  #
12
12
  # It's strongly recommended to check this file into your version control system.
13
13
 
14
- ActiveRecord::Schema.define(:version => 20120408165730) do
14
+ ActiveRecord::Schema.define(:version => 20120514060323) do
15
15
 
16
16
  create_table "opro_access_grants", :force => true do |t|
17
17
  t.string "code"
18
18
  t.string "access_token"
19
19
  t.string "refresh_token"
20
+ t.text "permissions"
20
21
  t.datetime "access_token_expires_at"
21
22
  t.integer "user_id"
22
23
  t.integer "application_id"
@@ -28,9 +29,10 @@ ActiveRecord::Schema.define(:version => 20120408165730) do
28
29
  t.string "name"
29
30
  t.string "app_id"
30
31
  t.string "app_secret"
32
+ t.text "permissions"
31
33
  t.integer "user_id"
32
- t.datetime "created_at", :null => false
33
- t.datetime "updated_at", :null => false
34
+ t.datetime "created_at", :null => false
35
+ t.datetime "updated_at", :null => false
34
36
  end
35
37
 
36
38
  create_table "users", :force => true do |t|
@@ -2,22 +2,36 @@ require 'test_helper'
2
2
 
3
3
  class AuthControllerTest < ActiveSupport::IntegrationCase
4
4
 
5
+ setup do
6
+ @app = create_client_app
7
+ @user = create_user
8
+ @redirect_uri = '/'
9
+ end
10
+
5
11
  test 'auth entry point should not be accessable to logged OUT users' do
6
- visit oauth_new_path
12
+ visit oauth_new_path(:client_id => @app.client_id, :redirect_uri => '/')
7
13
  assert_equal '/users/sign_in', current_path
8
14
  end
9
15
 
10
- test 'auth entry point is accessable to logged IN users' do
11
- app = create_client_app
12
- user = create_user
13
- redirect_uri = '/'
16
+ test 'auth entry point is accessible to logged IN users' do
14
17
 
15
- as_user(user).visit oauth_new_path(:client_id => app.client_id, :redirect_uri => redirect_uri)
18
+ as_user(@user).visit oauth_new_path(:client_id => @app.client_id, :redirect_uri => @redirect_uri)
16
19
 
17
20
  assert_equal '/oauth/new', current_path
18
21
 
19
22
  click_button 'oauthAuthorize'
20
- assert_equal '/', current_path
21
- assert Oauth::AccessGrant.where(:user_id => user.id, :application_id => app.id).present?
23
+ access_grant = Oauth::AccessGrant.where(:user_id => @user.id, :application_id => @app.id).first
24
+ assert_equal @redirect_uri, current_path
25
+ assert access_grant.present?
26
+ assert access_grant.can?(:write) # write access is checked by default
27
+ end
28
+
29
+ test 'user can remove permissions' do
30
+ as_user(@user).visit oauth_new_path(:client_id => @app.client_id, :redirect_uri => @redirect_uri)
31
+
32
+ uncheck('permissions_write') # uncheck write access
33
+ click_button 'oauthAuthorize'
34
+ access_grant = Oauth::AccessGrant.where(:user_id => @user.id, :application_id => @app.id).first
35
+ refute access_grant.can?(:write)
22
36
  end
23
37
  end
@@ -2,13 +2,11 @@
2
2
  ENV["RAILS_ENV"] = "test"
3
3
 
4
4
 
5
-
6
5
  ENGINE_RAILS_ROOT=File.join(File.dirname(__FILE__), '../')
7
6
  require File.expand_path("../dummy/config/environment.rb", __FILE__)
8
7
  require "rails/test_help"
9
8
 
10
-
11
-
9
+ require 'mocha'
12
10
 
13
11
  ActionMailer::Base.delivery_method = :test
14
12
  ActionMailer::Base.perform_deliveries = true
metadata CHANGED
@@ -1,19 +1,19 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: opro
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1.pre1.0.2
5
- prerelease: 6
4
+ version: 0.0.1
5
+ prerelease:
6
6
  platform: ruby
7
7
  authors:
8
8
  - schneems
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-04-13 00:00:00.000000000Z
12
+ date: 2012-06-14 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport
16
- requirement: &70160889026080 !ruby/object:Gem::Requirement
16
+ requirement: &70350386690460 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: 3.0.7
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70160889026080
24
+ version_requirements: *70350386690460
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: rails
27
- requirement: &70160889025500 !ruby/object:Gem::Requirement
27
+ requirement: &70350386683340 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: 3.0.7
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *70160889025500
35
+ version_requirements: *70350386683340
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: bluecloth
38
- requirement: &70160889024900 !ruby/object:Gem::Requirement
38
+ requirement: &70350386682740 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,10 +43,21 @@ dependencies:
43
43
  version: '0'
44
44
  type: :runtime
45
45
  prerelease: false
46
- version_requirements: *70160889024900
46
+ version_requirements: *70350386682740
47
+ - !ruby/object:Gem::Dependency
48
+ name: mocha
49
+ requirement: &70350386682120 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ type: :development
56
+ prerelease: false
57
+ version_requirements: *70350386682120
47
58
  - !ruby/object:Gem::Dependency
48
59
  name: jeweler
49
- requirement: &70160889024280 !ruby/object:Gem::Requirement
60
+ requirement: &70350386681480 !ruby/object:Gem::Requirement
50
61
  none: false
51
62
  requirements:
52
63
  - - ~>
@@ -54,10 +65,10 @@ dependencies:
54
65
  version: 1.6.4
55
66
  type: :development
56
67
  prerelease: false
57
- version_requirements: *70160889024280
68
+ version_requirements: *70350386681480
58
69
  - !ruby/object:Gem::Dependency
59
70
  name: bundler
60
- requirement: &70160889023620 !ruby/object:Gem::Requirement
71
+ requirement: &70350386680760 !ruby/object:Gem::Requirement
61
72
  none: false
62
73
  requirements:
63
74
  - - ! '>='
@@ -65,10 +76,10 @@ dependencies:
65
76
  version: 1.1.3
66
77
  type: :development
67
78
  prerelease: false
68
- version_requirements: *70160889023620
79
+ version_requirements: *70350386680760
69
80
  - !ruby/object:Gem::Dependency
70
81
  name: capybara
71
- requirement: &70160889023000 !ruby/object:Gem::Requirement
82
+ requirement: &70350386679900 !ruby/object:Gem::Requirement
72
83
  none: false
73
84
  requirements:
74
85
  - - ! '>='
@@ -76,10 +87,10 @@ dependencies:
76
87
  version: 0.4.0
77
88
  type: :development
78
89
  prerelease: false
79
- version_requirements: *70160889023000
90
+ version_requirements: *70350386679900
80
91
  - !ruby/object:Gem::Dependency
81
92
  name: sqlite3
82
- requirement: &70160889003480 !ruby/object:Gem::Requirement
93
+ requirement: &70350386678780 !ruby/object:Gem::Requirement
83
94
  none: false
84
95
  requirements:
85
96
  - - ! '>='
@@ -87,10 +98,10 @@ dependencies:
87
98
  version: '0'
88
99
  type: :development
89
100
  prerelease: false
90
- version_requirements: *70160889003480
101
+ version_requirements: *70350386678780
91
102
  - !ruby/object:Gem::Dependency
92
103
  name: launchy
93
- requirement: &70160889002560 !ruby/object:Gem::Requirement
104
+ requirement: &70350386678200 !ruby/object:Gem::Requirement
94
105
  none: false
95
106
  requirements:
96
107
  - - ! '>='
@@ -98,10 +109,10 @@ dependencies:
98
109
  version: '0'
99
110
  type: :development
100
111
  prerelease: false
101
- version_requirements: *70160889002560
112
+ version_requirements: *70350386678200
102
113
  - !ruby/object:Gem::Dependency
103
114
  name: devise
104
- requirement: &70160889001680 !ruby/object:Gem::Requirement
115
+ requirement: &70350386677300 !ruby/object:Gem::Requirement
105
116
  none: false
106
117
  requirements:
107
118
  - - ! '>='
@@ -109,10 +120,10 @@ dependencies:
109
120
  version: '0'
110
121
  type: :development
111
122
  prerelease: false
112
- version_requirements: *70160889001680
123
+ version_requirements: *70350386677300
113
124
  - !ruby/object:Gem::Dependency
114
125
  name: rcov
115
- requirement: &70160889000620 !ruby/object:Gem::Requirement
126
+ requirement: &70350386676560 !ruby/object:Gem::Requirement
116
127
  none: false
117
128
  requirements:
118
129
  - - ! '>='
@@ -120,10 +131,10 @@ dependencies:
120
131
  version: '0'
121
132
  type: :development
122
133
  prerelease: false
123
- version_requirements: *70160889000620
134
+ version_requirements: *70350386676560
124
135
  - !ruby/object:Gem::Dependency
125
136
  name: simplecov
126
- requirement: &70160888999860 !ruby/object:Gem::Requirement
137
+ requirement: &70350386675920 !ruby/object:Gem::Requirement
127
138
  none: false
128
139
  requirements:
129
140
  - - ! '>='
@@ -131,7 +142,7 @@ dependencies:
131
142
  version: '0'
132
143
  type: :development
133
144
  prerelease: false
134
- version_requirements: *70160888999860
145
+ version_requirements: *70350386675920
135
146
  description: ! ' Enable OAuth clients (iphone, android, web sites, etc.) to access
136
147
  and use your Rails application, what you do with it is up to you'
137
148
  email: richard.schneeman@gmail.com
@@ -172,15 +183,20 @@ files:
172
183
  - lib/generators/templates/opro.rb
173
184
  - lib/opro.rb
174
185
  - lib/opro/controllers/application_controller_helper.rb
186
+ - lib/opro/controllers/concerns/error_messages.rb
187
+ - lib/opro/controllers/concerns/permissions.rb
175
188
  - lib/opro/engine.rb
176
189
  - opro.gemspec
190
+ - test/controllers/permissions_test.rb
177
191
  - test/dummy/Rakefile
178
192
  - test/dummy/app/controllers/application_controller.rb
179
193
  - test/dummy/app/controllers/pages_controller.rb
194
+ - test/dummy/app/controllers/products_controller.rb
180
195
  - test/dummy/app/helpers/application_helper.rb
181
196
  - test/dummy/app/models/user.rb
182
197
  - test/dummy/app/views/layouts/application.html.erb
183
198
  - test/dummy/app/views/pages/index.html.erb
199
+ - test/dummy/app/views/products/create.html.erb
184
200
  - test/dummy/config.ru
185
201
  - test/dummy/config/application.rb
186
202
  - test/dummy/config/boot.rb
@@ -200,8 +216,8 @@ files:
200
216
  - test/dummy/config/locales/en.yml
201
217
  - test/dummy/config/routes.rb
202
218
  - test/dummy/db/migrate/20120408163038_devise_create_users.rb
203
- - test/dummy/db/migrate/20120408165729_create_opro_access_grants.rb
204
- - test/dummy/db/migrate/20120408165730_create_opro_client_applications.rb
219
+ - test/dummy/db/migrate/20120514060322_create_opro_access_grants.rb
220
+ - test/dummy/db/migrate/20120514060323_create_opro_client_applications.rb
205
221
  - test/dummy/db/schema.rb
206
222
  - test/dummy/public/404.html
207
223
  - test/dummy/public/422.html
@@ -237,13 +253,13 @@ required_ruby_version: !ruby/object:Gem::Requirement
237
253
  version: '0'
238
254
  segments:
239
255
  - 0
240
- hash: -3455292628874218809
256
+ hash: -2087592437685873043
241
257
  required_rubygems_version: !ruby/object:Gem::Requirement
242
258
  none: false
243
259
  requirements:
244
- - - ! '>'
260
+ - - ! '>='
245
261
  - !ruby/object:Gem::Version
246
- version: 1.3.1
262
+ version: '0'
247
263
  requirements: []
248
264
  rubyforge_project:
249
265
  rubygems_version: 1.8.10
@@ -1,14 +0,0 @@
1
- class CreateOproAccessGrants < ActiveRecord::Migration
2
- def change
3
- create_table :opro_access_grants do |t|
4
- t.string :code
5
- t.string :access_token
6
- t.string :refresh_token
7
- t.datetime :access_token_expires_at
8
- t.integer :user_id
9
- t.integer :application_id
10
-
11
- t.timestamps
12
- end
13
- end
14
- end