opro 0.0.1.pre

Sign up to get free protection for your applications and to get access to all the features.
Files changed (81) hide show
  1. data/CHANGELOG.md +3 -0
  2. data/Gemfile +39 -0
  3. data/Gemfile.lock +138 -0
  4. data/MIT-LICENSE +20 -0
  5. data/README.md +90 -0
  6. data/Rakefile +50 -0
  7. data/VERSION +1 -0
  8. data/app/controllers/oauth/auth_controller.rb +74 -0
  9. data/app/controllers/oauth/client_application_controller.rb +15 -0
  10. data/app/controllers/oauth/docs_controller.rb +36 -0
  11. data/app/controllers/opro_application_controller.rb +8 -0
  12. data/app/models/oauth/access_grant.rb +42 -0
  13. data/app/models/oauth/client_application.rb +30 -0
  14. data/app/views/oauth/auth/new.html.erb +8 -0
  15. data/app/views/oauth/client_application/create.html.erb +11 -0
  16. data/app/views/oauth/client_application/index.html.erb +18 -0
  17. data/app/views/oauth/client_application/new.html.erb +13 -0
  18. data/app/views/oauth/docs/index.html.erb +14 -0
  19. data/app/views/oauth/docs/markdown/curl.md.erb +6 -0
  20. data/app/views/oauth/docs/markdown/oauth.md.erb +1 -0
  21. data/app/views/oauth/docs/markdown/quick_start.md.erb +70 -0
  22. data/app/views/oauth/docs/show.html.erb +1 -0
  23. data/config/routes.rb +9 -0
  24. data/lib/generators/active_record/opro_generator.rb +28 -0
  25. data/lib/generators/active_record/templates/access_grants.rb +14 -0
  26. data/lib/generators/active_record/templates/client_applications.rb +11 -0
  27. data/lib/generators/opro/install_generator.rb +21 -0
  28. data/lib/generators/templates/opro.rb +4 -0
  29. data/lib/opro.rb +86 -0
  30. data/lib/opro/controllers/application_controller_helper.rb +38 -0
  31. data/lib/opro/engine.rb +8 -0
  32. data/opro.gemspec +148 -0
  33. data/test/dummy/Rakefile +7 -0
  34. data/test/dummy/app/controllers/application_controller.rb +3 -0
  35. data/test/dummy/app/controllers/pages_controller.rb +8 -0
  36. data/test/dummy/app/helpers/application_helper.rb +2 -0
  37. data/test/dummy/app/models/user.rb +10 -0
  38. data/test/dummy/app/views/layouts/application.html.erb +20 -0
  39. data/test/dummy/app/views/pages/index.html.erb +1 -0
  40. data/test/dummy/config.ru +4 -0
  41. data/test/dummy/config/application.rb +49 -0
  42. data/test/dummy/config/boot.rb +10 -0
  43. data/test/dummy/config/database.yml +22 -0
  44. data/test/dummy/config/environment.rb +5 -0
  45. data/test/dummy/config/environments/development.rb +26 -0
  46. data/test/dummy/config/environments/production.rb +49 -0
  47. data/test/dummy/config/environments/test.rb +35 -0
  48. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  49. data/test/dummy/config/initializers/devise.rb +223 -0
  50. data/test/dummy/config/initializers/inflections.rb +10 -0
  51. data/test/dummy/config/initializers/mime_types.rb +5 -0
  52. data/test/dummy/config/initializers/opro.rb +4 -0
  53. data/test/dummy/config/initializers/secret_token.rb +7 -0
  54. data/test/dummy/config/initializers/session_store.rb +8 -0
  55. data/test/dummy/config/locales/devise.en.yml +57 -0
  56. data/test/dummy/config/locales/en.yml +5 -0
  57. data/test/dummy/config/routes.rb +63 -0
  58. data/test/dummy/db/migrate/20120408163038_devise_create_users.rb +49 -0
  59. data/test/dummy/db/migrate/20120408165729_create_opro_access_grants.rb +14 -0
  60. data/test/dummy/db/migrate/20120408165730_create_opro_client_applications.rb +11 -0
  61. data/test/dummy/db/schema.rb +54 -0
  62. data/test/dummy/public/404.html +26 -0
  63. data/test/dummy/public/422.html +26 -0
  64. data/test/dummy/public/500.html +26 -0
  65. data/test/dummy/public/favicon.ico +0 -0
  66. data/test/dummy/public/javascripts/application.js +2 -0
  67. data/test/dummy/public/javascripts/controls.js +965 -0
  68. data/test/dummy/public/javascripts/dragdrop.js +974 -0
  69. data/test/dummy/public/javascripts/effects.js +1123 -0
  70. data/test/dummy/public/javascripts/prototype.js +6001 -0
  71. data/test/dummy/public/javascripts/rails.js +202 -0
  72. data/test/dummy/public/stylesheets/.gitkeep +0 -0
  73. data/test/dummy/script/rails +6 -0
  74. data/test/integration/auth_controller_test.rb +23 -0
  75. data/test/integration/client_application_controller_test.rb +24 -0
  76. data/test/integration/docs_controller_test.rb +8 -0
  77. data/test/integration/oauth_test.rb +17 -0
  78. data/test/opro_test.rb +24 -0
  79. data/test/support/integration_case.rb +5 -0
  80. data/test/test_helper.rb +99 -0
  81. metadata +251 -0
@@ -0,0 +1,8 @@
1
+ class ApplicationController < ActionController::Base
2
+
3
+ # Any code that would/should go into ApplicationController is
4
+ # no in lib/opro/conrollers/application_controller_helper.rb
5
+ # it is loaded into ApplicationController in lib/opro/engine.rb
6
+ # thanks for visiting, come back soon
7
+
8
+ end
@@ -0,0 +1,42 @@
1
+ class Oauth::AccessGrant < ActiveRecord::Base
2
+
3
+ self.table_name = :opro_access_grants
4
+
5
+ belongs_to :user
6
+ belongs_to :client_application, :class_name => "Oauth::ClientApplication"
7
+ belongs_to :application, :class_name => "Oauth::ClientApplication"
8
+
9
+ validates :application_id, :uniqueness => {:scope => :user_id, :message => "Applicaiton is already authed for this user"}, :presence => true
10
+
11
+ before_create :generate_tokens
12
+
13
+ def self.prune!
14
+ # UPDATEME
15
+ # delete_all(["created_at < ?", 3.days.ago])
16
+ end
17
+
18
+ def self.find_user_for_token(token)
19
+ self.where(:access_token => token).first.try(:user)
20
+ end
21
+
22
+ def self.authenticate(code, application_id)
23
+ self.where("code = ? AND application_id = ?", code, application_id).first
24
+ end
25
+
26
+ def generate_tokens
27
+ self.code, self.access_token, self.refresh_token = SecureRandom.hex(16), SecureRandom.hex(16), SecureRandom.hex(16)
28
+ end
29
+
30
+ def redirect_uri_for(redirect_uri)
31
+ if redirect_uri =~ /\?/
32
+ redirect_uri + "&code=#{code}&response_type=code"
33
+ else
34
+ redirect_uri + "?code=#{code}&response_type=code"
35
+ end
36
+ end
37
+
38
+ def start_expiry_period!
39
+ # UPDATEME
40
+ # self.update_attribute(:access_token_expires_at, 2.days.from_now)
41
+ end
42
+ end
@@ -0,0 +1,30 @@
1
+ class Oauth::ClientApplication < ActiveRecord::Base
2
+ self.table_name = :opro_client_applications
3
+
4
+ belongs_to :user
5
+ validates :app_id, :uniqueness => true
6
+ validates :name, :uniqueness => true
7
+
8
+ alias_attribute :client_id, :app_id
9
+
10
+ alias_attribute :client_secret, :app_secret
11
+ alias_attribute :secret, :app_secret
12
+
13
+ def self.authenticate(app_id, app_secret)
14
+ where(["app_id = ? AND app_secret = ?", app_id, app_secret]).first
15
+ end
16
+
17
+ def self.create_with_user_and_name(user, name)
18
+ create(:user => user, :name => name, :app_id => generate_id, :app_secret => SecureRandom.hex(16))
19
+ end
20
+
21
+ def self.generate_id
22
+ app_id = SecureRandom.hex(16)
23
+ client_app = where(:app_id => app_id)
24
+ if client_app.present?
25
+ generate_id
26
+ else
27
+ return app_id
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,8 @@
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 %>
3
+
4
+ <%= 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' %>
6
+ <%- end -%>
7
+
8
+ <%= button_to 'I Do Not Authorize This Application', request.referrer, :id => 'oauthNoAuthorize' %>
@@ -0,0 +1,11 @@
1
+ <h2>Success! Here is your App</h2>
2
+ <table>
3
+ <tr><td>Name: </td><td><%= @client_app.name %></td></tr>
4
+ <tr><td>Client Id: </td><td><%= @client_app.app_id %></td></tr>
5
+ <tr><td>Secret:</td><td><%= @client_app.app_secret %></td></tr>
6
+ </table>
7
+
8
+ <div>
9
+ <%= link_to 'Register an New App', new_oauth_client_application_path %>
10
+ </div>
11
+
@@ -0,0 +1,18 @@
1
+ <%- if @client_apps.blank? -%>
2
+ <h2>You have no Apps</h2>
3
+ <%- else -%>
4
+ <h2>Your Apps</h2>
5
+ <% @client_apps.each do |client_app| %>
6
+ <table>
7
+ <tr><td>Name: </td><td> <%= client_app.name %></td></tr>
8
+ <tr><td>id: </td><td> <%= client_app.app_id %></td></tr>
9
+ <tr><td>Secret: </td><td> <%= client_app.app_secret %></td></tr>
10
+ </table>
11
+ <hr />
12
+ <%- end -%>
13
+ <%- end -%>
14
+
15
+
16
+ <div>
17
+ <%= link_to 'Register an New App', new_oauth_client_application_path %>
18
+ </div>
@@ -0,0 +1,13 @@
1
+ <h2>Create An App</h2>
2
+ <div>
3
+ <%= form_for @client_app do |f| %>
4
+ <%= f.label :name %>:
5
+ <%= f.text_field :name, :placeholder => 'App Name' %>
6
+ <%= f.submit 'Create Oauth Client', :id => 'submitApp' %>
7
+ <%- end -%>
8
+ </div>
9
+
10
+
11
+ <div>
12
+ <%= link_to 'My Aplications', oauth_client_applications_path %>
13
+ </div>
@@ -0,0 +1,14 @@
1
+ <h2>Oauth Docs</h2>
2
+
3
+
4
+ <p>Oauth shouldn't be hard, and neither should docs</p>
5
+
6
+ <h2>Quick Links</h2>
7
+
8
+ <ul>
9
+ <li><%= link_to 'Quick Start', oauth_doc_path(:quick_start) %></li>
10
+ <li><%= link_to 'Curl', oauth_doc_path(:curl) %></li>
11
+ <li><%= link_to 'Oauth', oauth_doc_path(:oauth) %></li>
12
+ </ul>
13
+
14
+ <%= render_doc(:quick_start) %>
@@ -0,0 +1,6 @@
1
+ This document explains what curl is and how to use it.
2
+
3
+ TODO
4
+
5
+
6
+ In the future I would love to include Hurl in this project. If that interests you, submit a pull request ;)
@@ -0,0 +1 @@
1
+ Oauth is ... TODO
@@ -0,0 +1,70 @@
1
+ ## Quick Start Guide
2
+
3
+ This site is providing OAuth through [Opro](http://github.com/schneems/opro). If this is your first time using Oauth, please visit [What is Oauth]() or follow along with this guide.
4
+
5
+ ## Step 1: Register your Application
6
+
7
+ Sign in as a registered user then visit the [new client application page](/oauth_client_applications/new). Enter in the name of your application for this example we can use `foo`, you can change this later if you desire. Hit enter and you should see a screen that has your application name along with a `client id` and a `secret`, these behave like a username and password for your OAuth application.
8
+
9
+
10
+ Name: foo
11
+ client id: 3234myClientId5678
12
+ Secret: 14321myClientSecret8765
13
+
14
+
15
+ Once you've registered an app successfully we can start to build an OAuth application
16
+
17
+
18
+ ## Step 2: As a User Grant access to your App
19
+
20
+ Now that you have a client id, you'll want to give it access to a user account. Open a new browser window with your currently logged in account, then give your application permission by visiting the url below (please swap out '3234myClientId5678' for your client id)
21
+
22
+ <%= "#{request.base_url}/oauth/authorize?" %>client_id=3234myClientId5678&redirect_uri=/
23
+
24
+ This should land you on a page asking if you would like to grant permission to the application. If not, make sure you're logged in and you put the correct client id in the url.
25
+
26
+ Once you grant your application permission, you will be redirected back to the url provided. In this case we will go back to the home page of our app.
27
+
28
+ Once redirected to the home page take a look in the address bar, we should see a `code` parameter. Copy this for use later:
29
+
30
+ <%= "#{request.base_url}?" %>?code=4857goldfish827423
31
+
32
+ In the url above the `code` would be `4857goldfish827423`. This code can be used to obtain an access token for the user. Once you have a user's access token, you can perform actions for the user as if they were logged in. If you accidentally close this page, don't worry just visit first url and we'll show you the code again.
33
+
34
+
35
+
36
+ ## Step 3: Get AccessToken for User with Curl
37
+
38
+ We'll be using [Curl]() to go through the process of getting an access for our first user, you'll likely use http client libraries in your actual applications, but most systems come with curl and it is a fairly easy way to get started. If you've never used it before read our [curl documentation]()
39
+
40
+ (Note in all code examples the $ character indicates we are on the command line, it does not need to be coppied)
41
+
42
+
43
+ $ curl '<%= "#{request.base_url}/oauth/access_token?" %>?client_id=3234myClientId5678&client_secret=14321myClientSecret8765&code=4857goldfish827423'
44
+
45
+ You'll want to make sure to replace `client_id`, `client_secret`, and `code` with your values.
46
+
47
+ You should get back a response that looks like this
48
+
49
+ $ {"access_token":"9693accessTokena7ca570bbaf","refresh_token":"3a3c129ad02b573de78e65af06c293f1","expires_in":null}
50
+
51
+
52
+ If not, double check the previous steps and ensure you are using the correct values in the query. Copy the `access_token` we'll use it for the rest of our application, in this example it is `9693accessTokena7ca570bbaf`. Treat this access_token as if it were the user's password. It is sensitive information.
53
+
54
+
55
+ Step 4: Use the access token
56
+
57
+ Now we've gone through all the hard work of getting this token, you can use it to make authenticated requests to the server. You'll just need to include the correct `access_token` parameter in your query and you'll be logged in as that user for that request.
58
+
59
+
60
+ Try it out for yourself open up a browser and go to
61
+
62
+
63
+ <%= "#{request.base_url}/oauth/access_token?" %>
64
+
65
+
66
+ ## Security
67
+
68
+
69
+ Don't share your client application's secret or any user's access_token with unknown or untrusted parties. Always use https when available and don't write any of these values to your application's logs.
70
+
@@ -0,0 +1 @@
1
+ <%= render_doc(@doc) %>
@@ -0,0 +1,9 @@
1
+ Rails.application.routes.draw do
2
+
3
+ match 'oauth/new' => 'oauth/auth#new', :as => 'oauth_new'
4
+ match '/oauth/authorize' => 'oauth/auth#authorize', :as => 'oauth_authorize'
5
+ match '/oauth/access_token' => 'oauth/auth#access_token', :as => 'oauth_token'
6
+
7
+ resources :oauth_docs, :controller => 'oauth/docs'
8
+ resources :oauth_client_applications, :controller => 'oauth/client_application'
9
+ end
@@ -0,0 +1,28 @@
1
+ require 'rails/generators/migration'
2
+
3
+
4
+ module ActiveRecord
5
+ module Generators
6
+ class OproGenerator < ::Rails::Generators::Base
7
+ include Rails::Generators::Migration
8
+ source_root File.expand_path('../templates', __FILE__)
9
+
10
+ desc "add the migrations"
11
+
12
+ def self.next_migration_number(path)
13
+ unless @prev_migration_nr
14
+ @prev_migration_nr = Time.now.utc.strftime("%Y%m%d%H%M%S").to_i
15
+ else
16
+ @prev_migration_nr += 1
17
+ end
18
+ @prev_migration_nr.to_s
19
+ end
20
+
21
+
22
+ def copy_migrations
23
+ migration_template "access_grants.rb", "db/migrate/create_opro_access_grants.rb"
24
+ migration_template "client_applications.rb", "db/migrate/create_opro_client_applications.rb"
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,14 @@
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
@@ -0,0 +1,11 @@
1
+ class CreateOproClientApplications < ActiveRecord::Migration
2
+ def change
3
+ create_table :opro_client_applications do |t|
4
+ t.string :name
5
+ t.string :app_id
6
+ t.string :app_secret
7
+ t.integer :user_id
8
+ t.timestamps
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,21 @@
1
+ require 'securerandom'
2
+
3
+ module Opro
4
+ module Generators
5
+ class InstallGenerator < Rails::Generators::Base
6
+ source_root File.expand_path("../../templates", __FILE__)
7
+
8
+ desc "Creates a Opro initializer"
9
+ class_option :orm
10
+
11
+ def copy_initializer
12
+ template "opro.rb", "config/initializers/opro.rb"
13
+ end
14
+
15
+ def run_other_generators
16
+ generate "active_record:opro"
17
+ end
18
+ end
19
+ end
20
+ end
21
+
@@ -0,0 +1,4 @@
1
+ Opro.setup do |config|
2
+ ## Uncomment to configure devise
3
+ # config.auth_strategy = :devise
4
+ end
@@ -0,0 +1,86 @@
1
+ module Opro
2
+
3
+ module Controllers
4
+ end
5
+ # Include helpers in the given scope to AC and AV.
6
+ def self.include_helpers(scope)
7
+ ActiveSupport.on_load(:action_controller) do
8
+ include scope::ApplicationControllerHelper if defined?(scope::ApplicationControllerHelper)
9
+ end
10
+ end
11
+
12
+
13
+ def self.setup
14
+ yield self
15
+ set_login_logout_methods
16
+ end
17
+
18
+ def self.set_login_logout_methods
19
+ case auth_strategy
20
+ when :devise
21
+ login_method { |controller, current_user| controller.sign_in(current_user, :bypass => true) }
22
+ logout_method { |controller, current_user| controller.sign_out(current_user) }
23
+ authenticate_user_method { |controller| controller.authenticate_user! }
24
+ else
25
+ # nothing
26
+ # TODO, be smart here, if they have devise gem in Gemfile and haven't specified auth_strategy use devise
27
+ end
28
+ end
29
+
30
+ # Used by application controller to log user in
31
+ def self.login(*args)
32
+ raise 'login method not set, please specify Opro auth_strategy' if login_method.blank?
33
+ login_method.call(*args)
34
+ end
35
+
36
+ # Used by application controller to log user out
37
+ def self.logout(*args)
38
+ raise 'login method not set, please specify Opro auth_strategy' if login_method.blank?
39
+ logout_method.call(*args)
40
+ end
41
+
42
+
43
+ def self.auth_strategy(auth_strategy = nil)
44
+ if auth_strategy.present?
45
+ @auth_strategy = auth_strategy
46
+ else
47
+ @auth_strategy
48
+ end
49
+ end
50
+
51
+ def self.auth_strategy=(auth_strategy)
52
+ @auth_strategy = auth_strategy
53
+ end
54
+
55
+
56
+ def self.login_method(&block)
57
+ if block.present?
58
+ @login_method = block
59
+ else
60
+ @login_method or raise 'login method not set, please specify Opro auth_strategy'
61
+ end
62
+ end
63
+
64
+
65
+ def self.logout_method(&block)
66
+ if block.present?
67
+ @logout_method = block
68
+ else
69
+ @logout_method or raise 'login method not set, please specify Opro auth_strategy'
70
+ end
71
+ end
72
+
73
+ def self.authenticate_user_method(&block)
74
+ if block.present?
75
+ @authenticate_user_method = block
76
+ else
77
+ @authenticate_user_method or raise 'authenticate user method not set, please specify Opro auth_strategy'
78
+ end
79
+ end
80
+ end
81
+
82
+ # require 'opro/controller/concerns/render_redirect'
83
+ # require 'opro/controller/concerns/steps'
84
+ # require 'opro/controller/concerns/path'
85
+ require 'opro/controllers/application_controller_helper'
86
+ require 'opro/engine'
@@ -0,0 +1,38 @@
1
+ # this concern gets put into ApplicationController
2
+
3
+ module Opro
4
+ module Controllers
5
+ module ApplicationControllerHelper
6
+ extend ActiveSupport::Concern
7
+
8
+ included do
9
+ around_filter :oauth_auth!
10
+ skip_before_filter :verify_authenticity_token, :if => :valid_oauth?
11
+ end
12
+
13
+ def opro_authenticate_user!
14
+ Opro.authenticate_user_method.call(self)
15
+ end
16
+
17
+ protected
18
+ def oauth?
19
+ params[:access_token].present?
20
+ end
21
+
22
+ def oauth_user
23
+ @oauth_user ||= Oauth::AccessGrant.find_user_for_token(params[:access_token])
24
+ end
25
+
26
+ def valid_oauth?
27
+ oauth? && oauth_user.present?
28
+ end
29
+
30
+ def oauth_auth!
31
+ ::Opro.login(self, oauth_user) if valid_oauth?
32
+ yield
33
+ ::Opro.logout(self, oauth_user) if valid_oauth?
34
+ end
35
+
36
+ end
37
+ end
38
+ end