social_stream-oauth2_server 2.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +10 -0
  3. data/Gemfile +5 -0
  4. data/README.rdoc +3 -0
  5. data/Rakefile +26 -0
  6. data/app/assets/images/logos/small/site.png +0 -0
  7. data/app/assets/javascripts/social_stream-oauth2_server.js +6 -0
  8. data/app/assets/javascripts/social_stream/site_client.js +15 -0
  9. data/app/assets/stylesheets/social_stream-oauth2_server.css.sass +24 -0
  10. data/app/assets/stylesheets/social_stream/oauth2_server/applications/_applications-oauth2server.css.sass +45 -0
  11. data/app/assets/stylesheets/social_stream/oauth2_server/applications/layout/_applications-oauth2server.css.sass +51 -0
  12. data/app/assets/stylesheets/social_stream/oauth2_server/applications/responsive/_responsive-1200px-min.css.sass +7 -0
  13. data/app/assets/stylesheets/social_stream/oauth2_server/applications/responsive/_responsive-767px-max.css.sass +35 -0
  14. data/app/assets/stylesheets/social_stream/oauth2_server/applications/responsive/_responsive-768px-979px.css.sass +8 -0
  15. data/app/assets/stylesheets/social_stream/oauth2_server/create/_create-oauth2server.css.sass +11 -0
  16. data/app/assets/stylesheets/social_stream/oauth2_server/create/_error_create-oauth2server.css.sass +13 -0
  17. data/app/assets/stylesheets/social_stream/oauth2_server/create/layout/_create-oauth2server.css.sass +19 -0
  18. data/app/assets/stylesheets/social_stream/oauth2_server/create/responsive/_responsive-1200px-min.css.sass +7 -0
  19. data/app/assets/stylesheets/social_stream/oauth2_server/create/responsive/_responsive-767px-max.css.sass +16 -0
  20. data/app/assets/stylesheets/social_stream/oauth2_server/create/responsive/_responsive-768px-979px.css.sass +8 -0
  21. data/app/assets/stylesheets/social_stream/oauth2_server/show/_show-oauth2server.css.sass +42 -0
  22. data/app/assets/stylesheets/social_stream/oauth2_server/show/layout/_show-oauth2server.css.sass +71 -0
  23. data/app/assets/stylesheets/social_stream/oauth2_server/show/responsive/_responsive-1200px-min.css.sass +7 -0
  24. data/app/assets/stylesheets/social_stream/oauth2_server/show/responsive/_responsive-767px-max.css.sass +16 -0
  25. data/app/assets/stylesheets/social_stream/oauth2_server/show/responsive/_responsive-768px-979px.css.sass +8 -0
  26. data/app/controllers/authorizations_controller.rb +67 -0
  27. data/app/controllers/site/clients_controller.rb +39 -0
  28. data/app/decorators/social_stream/base/actor_decorator.rb +3 -0
  29. data/app/decorators/social_stream/base/user_decorator.rb +3 -0
  30. data/app/helpers/site_client_helper.rb +17 -0
  31. data/app/models/oauth2_token.rb +33 -0
  32. data/app/models/oauth2_token/access_token.rb +32 -0
  33. data/app/models/oauth2_token/authorization_code.rb +5 -0
  34. data/app/models/oauth2_token/refresh_token.rb +7 -0
  35. data/app/models/relation/admin.rb +9 -0
  36. data/app/models/relation/auth.rb +8 -0
  37. data/app/models/site/client.rb +38 -0
  38. data/app/overrides/frontpage/_presentation/client_site_presentation.html.erb.deface +8 -0
  39. data/app/overrides/layouts/_header_dropdown_menu/applications_entry.html.erb.deface +4 -0
  40. data/app/views/authorizations/error.html.erb +4 -0
  41. data/app/views/authorizations/new.html.erb +27 -0
  42. data/app/views/site/clients/_form.html.erb +39 -0
  43. data/app/views/site/clients/_new.modal.html.erb +9 -0
  44. data/app/views/site/clients/_presentation.html.erb +13 -0
  45. data/app/views/site/clients/index.html.erb +42 -0
  46. data/app/views/site/clients/new.html.erb +10 -0
  47. data/app/views/site/clients/show.html.erb +44 -0
  48. data/config/locales/en.yml +29 -0
  49. data/config/locales/es.yml +29 -0
  50. data/config/routes.rb +10 -0
  51. data/db/migrate/20130115102300_create_social_stream_oauth2_server.rb +25 -0
  52. data/lib/generators/social_stream/oauth2_server/install_generator.rb +23 -0
  53. data/lib/social_stream-oauth2_server.rb +19 -0
  54. data/lib/social_stream/migrations/oauth2_server.rb +8 -0
  55. data/lib/social_stream/oauth2_server.rb +5 -0
  56. data/lib/social_stream/oauth2_server/controllers/helpers.rb +41 -0
  57. data/lib/social_stream/oauth2_server/engine.rb +21 -0
  58. data/lib/social_stream/oauth2_server/models/actor.rb +11 -0
  59. data/lib/social_stream/oauth2_server/models/user.rb +35 -0
  60. data/lib/social_stream/oauth2_server/token_endpoint.rb +41 -0
  61. data/lib/social_stream/oauth2_server/version.rb +5 -0
  62. data/lib/tasks/db/populate.rake +37 -0
  63. data/social_stream-oauth2_server.gemspec +19 -0
  64. data/spec/controllers/authorizations_controller_spec.rb +179 -0
  65. data/spec/controllers/dummy_controller_spec.rb +43 -0
  66. data/spec/factories/site_client.rb +6 -0
  67. data/spec/models/relation/auth_spec.rb +15 -0
  68. data/spec/models/site/client_spec.rb +22 -0
  69. metadata +156 -0
@@ -0,0 +1,7 @@
1
+ //
2
+ // Responsive: Large desktop and up
3
+ // --------------------------------------------------
4
+
5
+
6
+ @media (min-width: 1200px)
7
+
@@ -0,0 +1,16 @@
1
+ //
2
+ // Responsive: Landscape phone to desktop/tablet
3
+ // --------------------------------------------------
4
+
5
+
6
+ @media (max-width: 767px)
7
+
8
+
9
+
10
+
11
+ // UP TO LANDSCAPE PHONE
12
+ // ---------------------
13
+
14
+ @media (max-width: 480px)
15
+
16
+
@@ -0,0 +1,8 @@
1
+ //
2
+ // Responsive: Tablet to desktop
3
+ // --------------------------------------------------
4
+
5
+
6
+ @media (min-width: 768px) and (max-width: 1119px)
7
+
8
+
@@ -0,0 +1,67 @@
1
+ class AuthorizationsController < ApplicationController
2
+ before_filter :authenticate_user!
3
+
4
+ rescue_from Rack::OAuth2::Server::Authorize::BadRequest do |e|
5
+ @error = e
6
+ render :error, :status => e.status
7
+ end
8
+
9
+ def new
10
+ respond *authorize_endpoint.call(request.env)
11
+ end
12
+
13
+ def create
14
+ respond *authorize_endpoint(:allow_approval).call(request.env)
15
+ end
16
+
17
+ private
18
+
19
+ def respond(status, header, response)
20
+ ["WWW-Authenticate"].each do |key|
21
+ headers[key] = header[key] if header[key].present?
22
+ end
23
+
24
+ if response.redirect?
25
+ redirect_to header['Location']
26
+ else
27
+ render :new
28
+ end
29
+ end
30
+
31
+ def authorize_endpoint(allow_approval = false)
32
+ Rack::OAuth2::Server::Authorize.new do |req, res|
33
+ @client = Site::Client.find(req.client_id) || req.bad_request!
34
+
35
+ res.redirect_uri = @redirect_uri = req.verify_redirect_uri!(@client.callback_url)
36
+
37
+ if allow_approval
38
+ if params[:accept]
39
+ current_user.client_authorize!(@client)
40
+
41
+ approve!(req, res, @client)
42
+ else
43
+ req.access_denied!
44
+ end
45
+ else
46
+ if current_user.client_authorized?(@client)
47
+ approve!(req, res, @client)
48
+ else
49
+ @response_type = req.response_type
50
+ @state = req.state
51
+ end
52
+ end
53
+ end
54
+ end
55
+
56
+ def approve!(req, res, client)
57
+ case req.response_type
58
+ when :code
59
+ authorization_code = current_user.authorization_codes.create!(:client => client, :redirect_uri => res.redirect_uri)
60
+ res.code = authorization_code.token
61
+ when :token
62
+ res.access_token = current_user.access_tokens.create!(:client => client).to_bearer_token
63
+ end
64
+
65
+ res.approve!
66
+ end
67
+ end
@@ -0,0 +1,39 @@
1
+ class Site::ClientsController < ApplicationController
2
+ before_filter :authenticate_user!
3
+
4
+ before_filter :set_author_ids, only: [ :create, :update ]
5
+
6
+ def index
7
+ @developer_clients = current_subject.developer_site_clients
8
+ end
9
+
10
+ def show
11
+ @client = Site::Client.find params[:id]
12
+ end
13
+
14
+ def new
15
+ @client = Site::Client.new
16
+ end
17
+
18
+ def create
19
+ @client = Site::Client.new params[:site_client]
20
+
21
+ if @client.save
22
+ respond_to do |format|
23
+ format.html { redirect_to @client }
24
+ end
25
+ else
26
+ respond_to do |format|
27
+ format.html { render :new }
28
+ end
29
+ end
30
+ end
31
+
32
+ private
33
+
34
+ def set_author_ids
35
+ params[:site_client][:author_id] = current_subject.actor_id
36
+ params[:site_client][:user_author_id] = current_user.actor_id
37
+ params[:site_client][:owner_id] = current_subject.actor_id
38
+ end
39
+ end
@@ -0,0 +1,3 @@
1
+ Actor.class_eval do
2
+ include SocialStream::Oauth2Server::Models::Actor
3
+ end
@@ -0,0 +1,3 @@
1
+ User.class_eval do
2
+ include SocialStream::Oauth2Server::Models::User
3
+ end
@@ -0,0 +1,17 @@
1
+ module SiteClientHelper
2
+ # Extract {Site::Client} id form Devise's redirect_to
3
+ def redirect_to_site_client_id
4
+ uri = URI.parse session["user_return_to"]
5
+
6
+ Rack::Utils.parse_query(uri.query)["client_id"]
7
+ rescue
8
+ end
9
+
10
+ def redirect_to_site_client?
11
+ redirect_to_site_client_id.present?
12
+ end
13
+
14
+ def redirecting_site_client
15
+ Site::Client.find redirect_to_site_client_id
16
+ end
17
+ end
@@ -0,0 +1,33 @@
1
+ class Oauth2Token < ActiveRecord::Base
2
+ cattr_accessor :default_lifetime
3
+ self.default_lifetime = 1.minute
4
+
5
+ belongs_to :user
6
+ belongs_to :client,
7
+ class_name: "Site::Client",
8
+ foreign_key: :site_id
9
+
10
+ validates :client, :expires_at, presence: true
11
+ validates :token, presence: true, uniqueness: true
12
+
13
+ before_validation :setup, on: :create
14
+
15
+ scope :valid, lambda {
16
+ where('expires_at >= ?', Time.now.utc)
17
+ }
18
+
19
+ def expires_in
20
+ (expires_at - Time.now.utc).to_i
21
+ end
22
+
23
+ def expire!
24
+ update_attribute(:expires_at, Time.now.utc) || raise(ActiveRecord::RecordInvalid)
25
+ end
26
+
27
+ protected
28
+
29
+ def setup
30
+ self.token = SecureRandom.base64(64)
31
+ self.expires_at ||= default_lifetime.from_now
32
+ end
33
+ end
@@ -0,0 +1,32 @@
1
+ class Oauth2Token::AccessToken < Oauth2Token
2
+ self.default_lifetime = 15.minutes
3
+
4
+ belongs_to :refresh_token,
5
+ class_name: "Oauth2Token::RefreshToken"
6
+
7
+ def to_bearer_token(with_refresh_token = false)
8
+ bearer_token = Rack::OAuth2::AccessToken::Bearer.new(
9
+ access_token: token,
10
+ expires_in: expires_in
11
+ )
12
+
13
+ if with_refresh_token
14
+ bearer_token.refresh_token = create_refresh_token!(
15
+ user: user,
16
+ client: client
17
+ ).token
18
+ end
19
+
20
+ bearer_token
21
+ end
22
+
23
+ def setup
24
+ super
25
+
26
+ if refresh_token
27
+ self.user = refresh_token.user
28
+ self.client = refresh_token.client
29
+ self.expires_at = [ expires_at, refresh_token.expires_at ].min
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,5 @@
1
+ class Oauth2Token::AuthorizationCode < Oauth2Token
2
+ def access_token
3
+ @access_token ||= expire! && user.access_tokens.create!(client: client)
4
+ end
5
+ end
@@ -0,0 +1,7 @@
1
+ class Oauth2Token::RefreshToken < Oauth2Token
2
+ self.default_lifetime = 1.month
3
+
4
+ has_many :access_tokens,
5
+ class_name: 'Oauth2Token::AccessToken'
6
+
7
+ end
@@ -0,0 +1,9 @@
1
+ # Administer client sites
2
+ class Relation::Admin < Relation::Single
3
+ class << self
4
+ def create_activity?
5
+ false
6
+ end
7
+ end
8
+ end
9
+
@@ -0,0 +1,8 @@
1
+ # Authorize a {Site::Client} to access data
2
+ class Relation::Auth < Relation::Single
3
+ class << self
4
+ def create_activity?
5
+ false
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,38 @@
1
+ class Site::Client < Site
2
+ validates_presence_of :url, :callback_url, :secret
3
+
4
+ before_validation :set_secret,
5
+ on: :create
6
+
7
+ after_create :set_admin
8
+
9
+ scope :administered_by, lambda { |actor|
10
+ joins(actor: :sent_ties).
11
+ merge(Contact.received_by(actor)).
12
+ merge(Tie.related_by(Relation::Admin.instance))
13
+ }
14
+
15
+ %w{ url callback_url secret }.each do |m|
16
+ define_method m do
17
+ config[m]
18
+ end
19
+
20
+ define_method "#{ m }=" do |arg|
21
+ config[m] = arg
22
+ end
23
+ end
24
+
25
+ def to_param
26
+ id
27
+ end
28
+
29
+ private
30
+
31
+ def set_secret
32
+ self.secret = SecureRandom.hex(64)
33
+ end
34
+
35
+ def set_admin
36
+ contact_to!(author).relation_ids = [ Relation::Admin.instance.id ]
37
+ end
38
+ end
@@ -0,0 +1,8 @@
1
+ <!-- surround_contents '#presentation' -->
2
+
3
+ <% if redirect_to_site_client? %>
4
+ <%= render partial: 'site/clients/presentation',
5
+ locals: { client: redirecting_site_client } %>
6
+ <% else %>
7
+ <%= render_original %>
8
+ <% end %>
@@ -0,0 +1,4 @@
1
+ <!-- insert_after "code[erb-loud]:contains('header_dropdown_menu_sessions')" -->
2
+ <li>
3
+ <%= link_to t('account.applications'), site_clients_path %>
4
+ </li>
@@ -0,0 +1,4 @@
1
+ <h2>Invalid Authorization Request</h2>
2
+
3
+ <h3><%= @error.error %></h3>
4
+ <p><%= @error.description %></p>
@@ -0,0 +1,27 @@
1
+ <article class="authorization">
2
+ <h2>
3
+ <%= t 'authorization.new.title', client: @client.name %>
4
+ </h2>
5
+
6
+ <%= raw t('authorization.new.permission.title', client: link_to(@client.name, @client.url)) %>
7
+
8
+ <ul>
9
+ <li>
10
+ &#8226&#32<%= t 'permission.public_info' %>
11
+ </li>
12
+ </ul>
13
+
14
+ <%= form_tag authorizations_path do %>
15
+ <%= hidden_field_tag :client_id, @client.id %>
16
+ <%= hidden_field_tag :response_type, @response_type %>
17
+ <%= hidden_field_tag :redirect_uri, @redirect_uri %>
18
+ <%= hidden_field_tag :state, @state %>
19
+
20
+ <%= button_tag class: "btn btn-danger", name: "cancel" do %>
21
+ <%= t 'authorization.form.cancel' %>
22
+ <% end %>
23
+ <%= button_tag class: "btn btn-success", name: "accept" do %>
24
+ <%= t 'authorization.form.accept' %>
25
+ <% end %>
26
+ <% end %>
27
+ </article>
@@ -0,0 +1,39 @@
1
+ <article>
2
+ <%= form_for(@client || Site::Client.new) do |f| %>
3
+
4
+ <% if f.object.errors.any? %>
5
+ <div id="error_explanation" class="alert alert-error">
6
+ <h2><%= pluralize(f.object.errors.count, "error") %> prohibited this client site from being saved:</h2>
7
+
8
+ <ul>
9
+ <% f.object.errors.full_messages.each do |msg| %>
10
+ <li><%= msg %></li>
11
+ <% end %>
12
+ </ul>
13
+
14
+ </div>
15
+ <% end %>
16
+ <article id="new_application">
17
+ <section class="name">
18
+ <%= f.label :name %>
19
+ <%= f.text_field :name %>
20
+ </section>
21
+
22
+ <section class="description">
23
+ <%= f.label :description %>
24
+ <%= f.text_area :description %>
25
+ </section>
26
+
27
+ <section class="url">
28
+ <%= f.label :url %>
29
+ <%= f.text_area :url %>
30
+ </section>
31
+
32
+ <section class="callback_url">
33
+ <%= f.label :callback_url %>
34
+ <%= f.text_area :callback_url %>
35
+ </section>
36
+ <%= f.submit :class => "btn pull-right" %>
37
+ </article>
38
+ <% end %>
39
+ </article>
@@ -0,0 +1,9 @@
1
+ <div id="new_site_client-modal" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="new_site_client-modal-title" aria-hidden="true">
2
+ <div class="modal-header">
3
+ <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
4
+ <h3 id="new_site_client-modal-title"><%= t 'site.client.new.title' %></h3>
5
+ </div>
6
+ <div class="modal-body">
7
+ <%= render partial: 'form' %>
8
+ </div>
9
+ </div>
@@ -0,0 +1,13 @@
1
+ <article class="media">
2
+ <%= link_to client.url, class: 'pull-left' do %>
3
+ <%= image_tag client.logo.url(:small), style: "width: 70px; height: 70px;" %>
4
+ <% end %>
5
+
6
+ <div class="media-body">
7
+ <h2 class="media-heading">
8
+ <%= client.name %>
9
+ </h2>
10
+
11
+ <%= client.description %>
12
+ </div>
13
+ </article>
@@ -0,0 +1,42 @@
1
+ <section id="site_clients" class="first-img">
2
+
3
+ <%= render partial: 'toolbar/home' %>
4
+
5
+ <section class="site_clients">
6
+ <header>
7
+ <h1>
8
+ <%= t 'site.client.added' %>
9
+ </h1>
10
+
11
+ <%= link_to t('site.client.new.link'), new_site_client_path, class: "btn new_site_client-modal-link", 'data-toggle' => 'modal' %>
12
+
13
+ <%= render partial: 'new.modal' %>
14
+
15
+ <hr class="soften">
16
+ </header>
17
+
18
+ <% @developer_clients.each do |client| %>
19
+
20
+ <%= image_tag client.logo.url(:small), style: "width: 40px; height: 40px;" %>
21
+
22
+ <div class="name">
23
+ <%= link_to client.name, client %>
24
+ </div>
25
+ <div class="url">
26
+ <%= link_to client.url, client.url, target: '_blank' %>
27
+ </div>
28
+ <div class="users">
29
+ <span>
30
+ 5
31
+ </span>
32
+ users
33
+ </div>
34
+ <hr class="soften">
35
+ <% end %>
36
+
37
+ <%= javascript_tag do %>
38
+ SocialStream.SiteClient.index();
39
+ <% end %>
40
+
41
+ </section>
42
+ </section>