noosfero | 4 new commits pushed to repository

Bráulio Bhavamitra gitlab at gitlab.com
Sun Feb 22 20:21:04 BRT 2015


Bráulio Bhavamitra pushed to refs/heads/master at <a href="https://gitlab.com/noosfero/noosfero">Noosfero / noosfero</a>

Commits:
<a href="https://gitlab.com/noosfero/noosfero/commit/82325df3267f6ea4caf4895fe7453e4a405ac8eb">82325df3</a> by Victor Costa
Add oauth client plugin

- - - - -
<a href="https://gitlab.com/noosfero/noosfero/commit/8f0d8761001c65c52959e215424fc0059e1c7dd4">8f0d8761</a> by Victor Costa
Add oauth provider plugin

- - - - -
<a href="https://gitlab.com/noosfero/noosfero/commit/8408ffac6f660a06510c7d1f1814db71c7f8163a">8408ffac</a> by Victor Costa
Prevent session reset because of cache in signup form

Also a GET is more appropriate for this case.

- - - - -
<a href="https://gitlab.com/noosfero/noosfero/commit/1213fdf1e3ceed079b54779296dcd26cf60e65e4">1213fdf1</a> by Bráulio Bhavamitra
Merge branch 'oauth_rails3' into 'master'

Two oauth plugins: oauth_client and oauth_provider

See merge request !415

- - - - -


Changes:

=====================================
app/views/account/_signup_form.html.erb
=====================================
--- a/app/views/account/_signup_form.html.erb
+++ b/app/views/account/_signup_form.html.erb
@@ -16,7 +16,7 @@
 <input type="hidden" id="signup_time_key" name="signup_time_key" />
 <script type="text/javascript">
   jQuery.ajax({
-    type: "POST",
+    type: "GET",
     url: "<%= url_for :controller=>'account', :action=>'signup_time' %>",
     dataType: 'json',
     success: function(data) {

=====================================
plugins/oauth_client/Gemfile
=====================================
--- /dev/null
+++ b/plugins/oauth_client/Gemfile
@@ -0,0 +1,3 @@
+gem 'omniauth', '~> 1.2.2'
+gem 'omniauth-facebook', '~> 2.0.0'
+gem "omniauth-google-oauth2", '~> 0.2.6'

=====================================
plugins/oauth_client/README.md
=====================================
--- /dev/null
+++ b/plugins/oauth_client/README.md
@@ -0,0 +1,72 @@
+README - Oauth Client Plugin
+================================
+
+OauthClient is a plugin which allow users to login/signup to noosfero with some oauth providers (for now, google, facebook and noosfero itself).
+
+Install
+=======
+
+Enable Plugin
+-------------
+
+cd <your_noosfero_dir>
+./script/noosfero-plugins enable oauth_client
+
+Active Plugin
+-------------
+
+As a Noosfero administrator user, go to administrator panel:
+
+- Click on "Enable/disable plugins" option
+- Click on "Oauth Client Plugin" check-box
+
+Provider Settings
+=================
+
+Goggle
+------
+
+[Create Google+ application](https://developers.google.com/+/web/signin/javascript-flow)
+
+Facebook
+--------
+
+[Create Facebook application](https://developers.facebook.com/docs/facebook-login/v2.1)
+
+Varnish Settings
+================
+If varnish has been used in your stack, you've to bypass the cache for signup page and prevent cookies to be removed when calling the oauth_client plugin callback. E.g.:
+
+```
+if (req.url !~ "^/account/*" && req.url !~ "^/plugin/oauth_provider/*" && req.url !~ "^/plugin/oauth_client/*" && req.http.cookie !~ "_noosfero_.*") {
+  unset req.http.cookie;
+  return(lookup);
+}
+```
+
+Using Oauth Provider Plugin
+===========================
+The oauth_provider plugin may be used as a provider in the same noosfero installation that hosts your oauth_client plugin (this is usefull in a multi environment setup).
+
+However, you've to use a distinct set of thin processes to handle the authorization requests (to avoid deadlock).
+
+Apache settings example:
+```
+RewriteRule ^/oauth_provider/oauth/(authorize|token).*$ balancer://noosfero-oauth-provider%{REQUEST_URI} [P,QSA,L]
+```
+
+
+Development
+===========
+
+Running OauthClient tests
+--------------------
+
+$ rake test:noosfero_plugins:oauth_client
+
+License
+=======
+
+Copyright (c) The Author developers.
+
+See Noosfero license.

=====================================
plugins/oauth_client/controllers/oauth_client_plugin_admin_controller.rb
=====================================
--- /dev/null
+++ b/plugins/oauth_client/controllers/oauth_client_plugin_admin_controller.rb
@@ -0,0 +1,27 @@
+class OauthClientPluginAdminController < AdminController
+
+  def index
+  end
+
+  def new
+    @provider = environment.oauth_providers.new
+    render :file => 'oauth_client_plugin_admin/edit'
+  end
+
+  def remove
+    environment.oauth_providers.find(params[:id]).destroy
+    redirect_to :action => 'index'
+  end
+
+  def edit
+    @provider = params[:id] ? environment.oauth_providers.find(params[:id]) : environment.oauth_providers.new
+    if request.post?
+      if @provider.update_attributes(params['oauth_client_plugin_provider'])
+        session[:notice] = _('Saved!')
+      else
+        session[:notice] = _('Error!')
+      end
+    end
+  end
+
+end

=====================================
plugins/oauth_client/controllers/public/oauth_client_plugin_public_controller.rb
=====================================
--- /dev/null
+++ b/plugins/oauth_client/controllers/public/oauth_client_plugin_public_controller.rb
@@ -0,0 +1,46 @@
+class OauthClientPluginPublicController < PublicController
+
+  skip_before_filter :login_required
+
+  def callback
+    auth = request.env["omniauth.auth"]
+    user = environment.users.find_by_email(auth.info.email)
+    user ? login(user) : signup(auth)
+  end
+
+  def failure
+    session[:notice] = _('Failed to login')
+    redirect_to root_url
+  end
+
+  def destroy
+    session[:user] = nil
+    redirect_to root_url
+  end
+
+  protected
+
+  def login(user)
+    provider = OauthClientPlugin::Provider.find(session[:provider_id])
+    user_provider = user.oauth_user_providers.find_by_provider_id(provider.id)
+    unless user_provider
+      user_provider = user.oauth_user_providers.create(:user => user, :provider => provider, :enabled => true)
+    end
+    if user_provider.enabled? && provider.enabled?
+      session[:user] = user.id
+    else
+      session[:notice] = _("Can't login with #{provider.name}")
+    end
+
+    redirect_to :controller => :account, :action => :login
+  end
+
+  def signup(auth)
+    login = auth.info.email.split('@').first
+    session[:oauth_data] = auth
+    name = auth.info.name
+    name ||= auth.extra && auth.extra.raw_info ? auth.extra.raw_info.name : ''
+    redirect_to :controller => :account, :action => :signup, :user => {:login => login, :email => auth.info.email}, :profile_data => {:name => name}
+  end
+
+end

=====================================
plugins/oauth_client/db/migrate/20141010135314_create_oauth_client_plugin_provider.rb
=====================================
--- /dev/null
+++ b/plugins/oauth_client/db/migrate/20141010135314_create_oauth_client_plugin_provider.rb
@@ -0,0 +1,19 @@
+class CreateOauthClientPluginProvider < ActiveRecord::Migration
+
+  def self.up
+    create_table :oauth_client_plugin_providers do |t|
+      t.integer :environment_id
+      t.string :strategy
+      t.string :name
+      t.text :options
+      t.boolean :enabled
+      t.integer :image_id
+
+      t.timestamps
+    end
+  end
+
+  def self.down
+    drop_table :oauth_client_plugin_providers
+  end
+end

=====================================
plugins/oauth_client/db/migrate/20141014162710_create_oauth_client_user_providers.rb
=====================================
--- /dev/null
+++ b/plugins/oauth_client/db/migrate/20141014162710_create_oauth_client_user_providers.rb
@@ -0,0 +1,14 @@
+class CreateOauthClientUserProviders < ActiveRecord::Migration
+  def self.up
+    create_table :oauth_client_plugin_user_providers do |t|
+      t.references :user
+      t.references :provider
+      t.boolean :enabled
+      t.timestamps
+    end
+  end
+
+  def self.down
+    drop_table :oauth_client_plugin_user_providers
+  end
+end

=====================================
plugins/oauth_client/lib/ext/environment.rb
=====================================
--- /dev/null
+++ b/plugins/oauth_client/lib/ext/environment.rb
@@ -0,0 +1,7 @@
+require_dependency 'environment'
+
+class Environment
+
+  has_many :oauth_providers, :class_name => 'OauthClientPlugin::Provider'
+
+end

=====================================
plugins/oauth_client/lib/ext/user.rb
=====================================
--- /dev/null
+++ b/plugins/oauth_client/lib/ext/user.rb
@@ -0,0 +1,31 @@
+require_dependency 'user'
+
+class User
+
+  has_many :oauth_user_providers, :class_name => 'OauthClientPlugin::UserProvider'
+  has_many :oauth_providers, :through => :oauth_user_providers, :source => :provider
+
+  def password_required_with_oauth?
+    password_required_without_oauth? && oauth_providers.empty?
+  end
+
+  alias_method_chain :password_required?, :oauth
+
+  after_create :activate_oauth_user
+
+  def activate_oauth_user
+    unless oauth_providers.empty?
+      activate
+      oauth_providers.each do |provider|
+        OauthClientPlugin::UserProvider.create!(:user => self, :provider => provider, :enabled => true)
+      end
+    end
+  end
+
+  def make_activation_code_with_oauth
+    oauth_providers.blank? ? make_activation_code_without_oauth : nil
+  end
+
+  alias_method_chain :make_activation_code, :oauth
+
+end

=====================================
plugins/oauth_client/lib/oauth_client_plugin.rb
=====================================
--- /dev/null
+++ b/plugins/oauth_client/lib/oauth_client_plugin.rb
@@ -0,0 +1,95 @@
+require 'omniauth/strategies/noosfero_oauth2'
+
+class OauthClientPlugin < Noosfero::Plugin
+
+  def self.plugin_name
+    "Oauth Client Plugin"
+  end
+
+  def self.plugin_description
+    _("Login with Oauth.")
+  end
+
+  def login_extra_contents
+    plugin = self
+    proc do
+      render :partial => 'auth/oauth_login', :locals => {:providers => environment.oauth_providers.enabled}
+    end
+  end
+
+  def signup_extra_contents
+    plugin = self
+
+    proc do
+      if plugin.context.session[:oauth_data].present?
+        render :partial => 'account/oauth_signup'
+      else
+        ''
+      end
+    end
+  end
+
+  PROVIDERS = {
+    :facebook => {
+      :name => 'Facebook'
+    },
+    :google_oauth2 => {
+      :name => 'Google'
+    },
+    :noosfero_oauth2 => {
+      :name => 'Noosfero'
+    }
+  }
+
+  def stylesheet?
+    true
+  end
+
+  OmniAuth.config.on_failure = OauthClientPluginPublicController.action(:failure)
+
+  Rails.application.config.middleware.use OmniAuth::Builder do
+    PROVIDERS.each do |provider, options|
+      setup = lambda { |env|
+        request = Rack::Request.new(env)
+        strategy = env['omniauth.strategy']
+
+        Noosfero::MultiTenancy.setup!(request.host)
+        domain = Domain.find_by_name(request.host)
+        environment = domain.environment rescue Environment.default
+
+        provider_id = request.params['id']
+        provider_id ||= request.session['omniauth.params']['id'] if request.session['omniauth.params']
+        provider = environment.oauth_providers.find(provider_id)
+        strategy.options.merge!(provider.options.symbolize_keys)
+
+        request.session[:provider_id] = provider_id
+      }
+
+      provider provider, :setup => setup,
+        :path_prefix => '/plugin/oauth_client',
+        :callback_path => "/plugin/oauth_client/public/callback/#{provider}",
+        :client_options => { :connection_opts => { :proxy => ENV["OAUTH_HTTP_PROXY"] } }
+    end
+
+    unless Rails.env.production?
+      provider :developer, :path_prefix => "/plugin/oauth_client", :callback_path => "/plugin/oauth_client/public/callback/developer"
+    end
+  end
+
+  def account_controller_filters
+    {
+      :type => 'before_filter', :method_name => 'signup',
+      :block => proc {
+        auth = session[:oauth_data]
+
+        if auth.present? && params[:user].present?
+          params[:user][:oauth_providers] = [OauthClientPlugin::Provider.find(session[:provider_id])]
+          if request.post? && auth.info.email != params[:user][:email]
+            raise "Wrong email for oauth signup"
+          end
+        end
+      }
+    }
+  end
+
+end

=====================================
plugins/oauth_client/lib/oauth_client_plugin/provider.rb
=====================================
--- /dev/null
+++ b/plugins/oauth_client/lib/oauth_client_plugin/provider.rb
@@ -0,0 +1,20 @@
+class OauthClientPlugin::Provider < Noosfero::Plugin::ActiveRecord
+
+  belongs_to :environment
+
+  validates_presence_of :name, :strategy
+
+  acts_as_having_image
+  acts_as_having_settings :field => :options
+
+  settings_items :client_id, :type => :string
+  settings_items :client_secret, :type => :string
+  settings_items :client_options, :type => Hash
+
+  attr_accessible :name, :environment, :strategy, :client_id, :client_secret, :enabled, :client_options, :image_builder
+
+  scope :enabled, :conditions => {:enabled => true}
+
+  acts_as_having_image
+
+end

=====================================
plugins/oauth_client/lib/oauth_client_plugin/user_provider.rb
=====================================
--- /dev/null
+++ b/plugins/oauth_client/lib/oauth_client_plugin/user_provider.rb
@@ -0,0 +1,10 @@
+class OauthClientPlugin::UserProvider < Noosfero::Plugin::ActiveRecord
+
+   belongs_to :user, :class_name => 'User'
+   belongs_to :provider, :class_name => 'OauthClientPlugin::Provider'
+
+   set_table_name :oauth_client_plugin_user_providers
+
+   attr_accessible :user, :provider, :enabled
+
+end

=====================================
plugins/oauth_client/lib/omniauth/strategies/noosfero_oauth2.rb
=====================================
--- /dev/null
+++ b/plugins/oauth_client/lib/omniauth/strategies/noosfero_oauth2.rb
@@ -0,0 +1,26 @@
+require 'omniauth/strategies/oauth2'
+
+module OmniAuth
+  module Strategies
+    class NoosferoOauth2 < OmniAuth::Strategies::OAuth2
+      option :name, :noosfero_oauth2
+      option :client_options, {
+        :authorize_url => '/oauth_provider/oauth/authorize',
+        :token_url     => '/oauth_provider/oauth/token'
+      }
+
+      uid { raw_info["id"] }
+
+      info do
+        {
+          :email => raw_info["email"]
+        }
+      end
+
+      def raw_info
+        #FIXME access the noosfero api (coming soon)
+        @raw_info ||= access_token.get('/plugin/oauth_provider/public/me').parsed
+      end
+    end
+  end
+end

=====================================
plugins/oauth_client/public/style.css
=====================================
--- /dev/null
+++ b/plugins/oauth_client/public/style.css
@@ -0,0 +1,18 @@
+.oauth-login .provider a {
+  min-width: 20px;
+  min-height: 20px;
+  background-size: 20px;
+  display: inline-block;
+  text-decoration: none;
+  background-repeat: no-repeat;
+  line-height: 20px;
+}
+.oauth-login .provider a img {
+  max-width: 40px;
+}
+.oauth-login .provider a:hover {
+  opacity: 0.7;
+}
+.oauth-login .provider .developer {
+  display: none;
+}

=====================================
plugins/oauth_client/test/functional/oauth_client_plugin_public_controller_test.rb
=====================================
--- /dev/null
+++ b/plugins/oauth_client/test/functional/oauth_client_plugin_public_controller_test.rb
@@ -0,0 +1,80 @@
+require File.dirname(__FILE__) + '/../test_helper'
+
+class OauthClientPluginPublicControllerTest < ActionController::TestCase
+
+  def setup
+    @auth = mock
+    @auth.stubs(:info).returns(mock)
+    request.env["omniauth.auth"] = @auth
+    @environment = Environment.default
+    @provider = OauthClientPlugin::Provider.create!(:name => 'provider', :strategy => 'provider', :enabled => true)
+  end
+  attr_reader :auth, :environment, :provider
+
+  should 'redirect to signup when user is not found' do
+    auth.info.stubs(:email).returns("xyz123 at noosfero.org")
+    auth.info.stubs(:name).returns('xyz123')
+    session[:provider_id] = provider.id
+
+    get :callback
+    assert_match /.*\/account\/signup/, @response.redirect_url
+  end
+
+  should 'redirect to login when user is found' do
+    user = fast_create(User, :environment_id => environment.id)
+    auth.info.stubs(:email).returns(user.email)
+    auth.info.stubs(:name).returns(user.name)
+    session[:provider_id] = provider.id
+
+    get :callback
+    assert_redirected_to :controller => :account, :action => :login
+    assert_equal user.id, session[:user]
+  end
+
+  should 'do not login when the provider is disabled' do
+    user = fast_create(User, :environment_id => environment.id)
+    auth.info.stubs(:email).returns(user.email)
+    auth.info.stubs(:name).returns(user.name)
+    session[:provider_id] = provider.id
+    provider.update_attribute(:enabled, false)
+
+    get :callback
+    assert_redirected_to :controller => :account, :action => :login
+    assert_equal nil, session[:user]
+  end
+
+  should 'do not login when the provider is disabled for a user' do
+    user = fast_create(User, :environment_id => environment.id)
+    auth.info.stubs(:email).returns(user.email)
+    auth.info.stubs(:name).returns(user.name)
+    session[:provider_id] = provider.id
+    user.oauth_user_providers.create(:user => user, :provider => provider, :enabled => false)
+
+    get :callback
+    assert_redirected_to :controller => :account, :action => :login
+    assert_equal nil, session[:user]
+  end
+
+  should 'save provider when an user login with it' do
+    user = fast_create(User, :environment_id => environment.id)
+    auth.info.stubs(:email).returns(user.email)
+    auth.info.stubs(:name).returns(user.name)
+    session[:provider_id] = provider.id
+
+    get :callback
+    assert_equal [provider], user.oauth_providers
+  end
+
+  should 'do not duplicate relations between an user and a provider when the same provider was used again in a login' do
+    user = fast_create(User, :environment_id => environment.id)
+    auth.info.stubs(:email).returns(user.email)
+    auth.info.stubs(:name).returns(user.name)
+    session[:provider_id] = provider.id
+
+    get :callback
+    assert_no_difference 'user.oauth_user_providers.count' do
+      3.times { get :callback }
+    end
+  end
+
+end

=====================================
plugins/oauth_client/test/test_helper.rb
=====================================
--- /dev/null
+++ b/plugins/oauth_client/test/test_helper.rb
@@ -0,0 +1 @@
+require File.dirname(__FILE__) + '/../../../test/test_helper'

=====================================
plugins/oauth_client/test/unit/environment_test.rb
=====================================
--- /dev/null
+++ b/plugins/oauth_client/test/unit/environment_test.rb
@@ -0,0 +1,10 @@
+require File.dirname(__FILE__) + '/../test_helper'
+
+class UserTest < ActiveSupport::TestCase
+
+  should 'be able to add oauth providers in a environment' do
+    env = fast_create(Environment)
+    env.oauth_providers << OauthClientPlugin::Provider.new(:name => 'test', :strategy => 'test')
+  end
+
+end

=====================================
plugins/oauth_client/test/unit/oauth_client_plugin_test.rb
=====================================
--- /dev/null
+++ b/plugins/oauth_client/test/unit/oauth_client_plugin_test.rb
@@ -0,0 +1,86 @@
+require File.dirname(__FILE__) + '/../test_helper'
+
+class OauthClientPluginTest < ActiveSupport::TestCase
+
+  def setup
+    @plugin = OauthClientPlugin.new(self)
+    @params = {}
+    @plugin.stubs(:context).returns(self)
+    @environment = Environment.default
+    @session = {}
+    @request = mock
+    @provider = OauthClientPlugin::Provider.create!(:name => 'name', :strategy => 'strategy')
+  end
+
+  attr_reader :params, :plugin, :environment, :session, :request, :provider
+
+  should 'has extra contents for login' do
+    assert plugin.login_extra_contents
+  end
+
+  should 'has no signup extra contents if no provider was enabled' do
+    assert_equal '', instance_eval(&plugin.signup_extra_contents)
+  end
+
+  should 'has signup extra contents if oauth_data exists in session' do
+    session[:oauth_data] = {:oauth => 'test'}
+    expects(:render).with(:partial => 'account/oauth_signup').once
+    instance_eval(&plugin.signup_extra_contents)
+  end
+
+  should 'define before filter for account controller' do
+    assert plugin.account_controller_filters
+  end
+
+  should 'raise error if oauth email was changed' do
+    request.expects(:post?).returns(true)
+
+    oauth_data = mock
+    info = mock
+    oauth_data.stubs(:info).returns(info)
+    oauth_data.stubs(:uid).returns('uid')
+    oauth_data.stubs(:provider).returns('provider')
+    info.stubs(:email).returns('test at example.com')
+    session[:oauth_data] = oauth_data
+    session[:provider_id] = provider.id
+
+    params[:user] = {:email => 'test2 at example.com'}
+    assert_raises RuntimeError do
+      instance_eval(&plugin.account_controller_filters[:block])
+    end
+  end
+
+  should 'do not raise error if oauth email was not changed' do
+    request.expects(:post?).returns(true)
+
+    oauth_data = mock
+    info = mock
+    oauth_data.stubs(:info).returns(info)
+    oauth_data.stubs(:uid).returns('uid')
+    oauth_data.stubs(:provider).returns('provider')
+    info.stubs(:email).returns('test at example.com')
+    session[:oauth_data] = oauth_data
+    session[:provider_id] = provider.id
+
+    params[:user] = {:email => 'test at example.com'}
+    instance_eval(&plugin.account_controller_filters[:block])
+  end
+
+  should 'do not raise error if oauth session is not set' do
+    instance_eval(&plugin.account_controller_filters[:block])
+  end
+
+  should 'do not raise error if it is not a post' do
+    request.expects(:post?).returns(false)
+    params[:user] = {:email => 'test2 at example.com'}
+
+    oauth_data = mock
+    oauth_data.stubs(:uid).returns('uid')
+    oauth_data.stubs(:provider).returns('provider')
+    session[:provider_id] = provider.id
+
+    session[:oauth_data] = oauth_data
+    instance_eval(&plugin.account_controller_filters[:block])
+  end
+
+end

=====================================
plugins/oauth_client/test/unit/user_test.rb
=====================================
--- /dev/null
+++ b/plugins/oauth_client/test/unit/user_test.rb
@@ -0,0 +1,40 @@
+require File.dirname(__FILE__) + '/../test_helper'
+
+class UserTest < ActiveSupport::TestCase
+
+  def setup
+    @provider = OauthClientPlugin::Provider.create!(:name => 'name', :strategy => 'strategy')
+  end
+  attr_reader :provider
+
+  should 'password is not required if there is a oauth provider' do
+    User.create!(:email => 'testoauth at example.com', :login => 'testoauth', :oauth_providers => [provider])
+  end
+
+  should 'password is required if there is a oauth provider' do
+    user = User.new(:email => 'testoauth at example.com', :login => 'testoauth')
+    user.save
+    assert user.errors[:password].present?
+  end
+
+  should 'activate user when created with oauth' do
+    user = User.create!(:email => 'testoauth at example.com', :login => 'testoauth', :oauth_providers => [provider])
+    assert user.activated?
+  end
+
+  should 'not activate user when created without oauth' do
+    user = fast_create(User)
+    assert !user.activated?
+  end
+
+  should 'not make activation code when created with oauth' do
+    user = User.create!(:email => 'testoauth at example.com', :login => 'testoauth', :oauth_providers => [provider])
+    assert !user.activation_code
+  end
+
+  should 'make activation code when created without oauth' do
+    user = User.create!(:email => 'testoauth at example.com', :login => 'testoauth', :password => 'test', :password_confirmation => 'test')
+    assert user.activation_code
+  end
+
+end

=====================================
plugins/oauth_client/views/account/_oauth_signup.html.erb
=====================================
--- /dev/null
+++ b/plugins/oauth_client/views/account/_oauth_signup.html.erb
@@ -0,0 +1,11 @@
+<%= hidden_field_tag 'return_to', '/' %>
+
+<style>
+  #signup-password, #signup-password-confirmation, #signup-email {
+    display: none;
+  }
+</style>
+
+<div id='signup-email-readonly'>
+  <%= labelled_form_field(_('Email'), text_field(:user, :email, :class => "disabled", :readonly => true)) %>
+</div>

=====================================
plugins/oauth_client/views/auth/_oauth_login.html.erb
=====================================
--- /dev/null
+++ b/plugins/oauth_client/views/auth/_oauth_login.html.erb
@@ -0,0 +1,16 @@
+<div class="oauth-login">
+  <% unless providers.empty? %>
+    <%= _('Login with:') %>
+  <% end %>
+  <% providers.each do |provider| %>
+    <span class="provider">
+      <%= link_to provider.image ? image_tag(provider.image.public_filename) : provider.name, "/plugin/oauth_client/#{provider.strategy}?id=#{provider.id}", :class => provider.strategy, :title => provider.name %>
+    </span>
+  <% end %>
+
+  <span class="provider">
+    <% unless Rails.env.production? %>
+      <%= link_to _('Developer Login'), "/plugin/oauth_client/developer", :class => 'developer' %>
+    <% end %>
+  </span>
+</div>

=====================================
plugins/oauth_client/views/oauth_client_plugin_admin/_noosfero_oauth2.html.erb
=====================================
--- /dev/null
+++ b/plugins/oauth_client/views/oauth_client_plugin_admin/_noosfero_oauth2.html.erb
@@ -0,0 +1,5 @@
+<%= f.fields_for :client_options, OpenStruct.new(provider.options[:client_options]) do |c| %>
+  <div class="client-url">
+    <%= labelled_form_field _('Client Url'), c.text_field(:site) %>
+  </div>
+<% end %>

=====================================
plugins/oauth_client/views/oauth_client_plugin_admin/edit.html.erb
=====================================
--- /dev/null
+++ b/plugins/oauth_client/views/oauth_client_plugin_admin/edit.html.erb
@@ -0,0 +1,39 @@
+<h1><%= _('Oauth Client Settings') %></h1>
+<h3><%= _('Edit Provider') %></h3>
+
+<%= form_for @provider, :url => {:action => 'edit'}, :method => 'post' do |f| %>
+
+  <div class="enabled">
+    <%= labelled_form_field f.check_box(:enabled) + _('Enabled'), '' %>
+  </div>
+
+  <div class="name">
+    <%= labelled_form_field _('Name'), f.text_field(:name) %>
+  </div>
+
+  <div class="strategy">
+    <%= labelled_form_field _('Strategy'), f.select(:strategy, OauthClientPlugin::PROVIDERS) %>
+  </div>
+
+  <div class="client-id">
+    <%= labelled_form_field _('Client Id'), f.text_field(:client_id) %>
+  </div>
+
+  <div class="client-secret">
+    <%= labelled_form_field _('Client Secret'), f.text_field(:client_secret) %>
+  </div>
+
+  <% if File.exists?(File.join(File.dirname(__FILE__), "_#{@provider.strategy}.html.erb")) %>
+    <%= render :partial => "#{@provider.strategy}", :locals => {:f => f, :provider => @provider} %>
+  <% end %>
+
+  <div class="image-icon">
+    <%= f.fields_for :image_builder, @provider.image do |i| %>
+      <%= file_field_or_thumbnail(_('Image:'), @provider.image, i) %><%= _("Max size: %s (.jpg, .gif, .png)")% Image.max_size.to_humanreadable %>
+    <% end %>
+  </div>
+
+  <% button_bar do %>
+    <%= submit_button(:save, _('Save'), :cancel => {:action => 'index'}) %>
+  <% end %>
+<% end %>

=====================================
plugins/oauth_client/views/oauth_client_plugin_admin/index.html.erb
=====================================
--- /dev/null
+++ b/plugins/oauth_client/views/oauth_client_plugin_admin/index.html.erb
@@ -0,0 +1,24 @@
+<h1><%= _('Oauth Client Settings') %></h1>
+<h3><%= _('Providers') %></h3>
+<%= button :add, _('New'), {:action => 'new'} %>
+<table>
+  <tr>
+    <th><%= _('Name') %></th>
+    <th><%= _('Strategy') %></th>
+    <th><%= _('Actions') %></th>
+  </tr>
+
+  <% environment.oauth_providers.each do |provider| %>
+    <tr>
+      <td><%= provider.name %></td>
+      <td><%= provider.strategy %></td>
+      <td>
+        <%= link_to _('Edit'), {:action => 'edit', :id => provider.id} %>
+        <%= link_to _('Remove'), {:action => 'remove', :id => provider.id} %>
+      </td>
+    </tr>
+  <% end %>
+</table>
+<div class="actions">
+  <%= button(:back, _('Go back'), {:controller => 'plugins', :action => 'index'}) %>
+</div>

=====================================
plugins/oauth_provider/Gemfile
=====================================
--- /dev/null
+++ b/plugins/oauth_provider/Gemfile
@@ -0,0 +1 @@
+gem 'doorkeeper', '~> 1.4.0'

=====================================
plugins/oauth_provider/README.md
=====================================
--- /dev/null
+++ b/plugins/oauth_provider/README.md
@@ -0,0 +1,47 @@
+README - Oauth Provider Plugin
+================================
+
+OauthProvider is a plugin which allow noosfero to be used as an oauth provider 
+
+Install
+=======
+
+Enable Plugin
+-------------
+
+cd <your_noosfero_dir>
+./script/noosfero-plugins enable oauth_provider
+
+Active Plugin
+-------------
+
+As a Noosfero administrator user, go to administrator panel:
+
+- Click on "Enable/disable plugins" option
+- Click on "Oauth Provider Plugin" check-box
+
+Varnish Settings
+================
+If varnish has been used in your stack, you've to prevent cookies to be removed when calling authorization actions for  oauth_provider. E.g.:
+
+```
+if (req.url !~ "^/plugin/oauth_provider/*" && req.http.cookie !~ "_noosfero_.*") {
+  unset req.http.cookie;
+  return(lookup);
+}
+```
+
+Development
+===========
+
+Running OauthProvider tests
+--------------------
+
+$ rake test:noosfero_plugins:oauth_provider
+
+License
+=======
+
+Copyright (c) The Author developers.
+
+See Noosfero license.

=====================================
plugins/oauth_provider/controllers/doorkeeper/application_controller.rb
=====================================
--- /dev/null
+++ b/plugins/oauth_provider/controllers/doorkeeper/application_controller.rb
@@ -0,0 +1,8 @@
+module Doorkeeper
+  class ApplicationController < ApplicationController
+
+    include Helpers::Controller
+    helper 'doorkeeper/form_errors'
+
+  end
+end

=====================================
plugins/oauth_provider/controllers/oauth_provider_applications_controller.rb
=====================================
--- /dev/null
+++ b/plugins/oauth_provider/controllers/oauth_provider_applications_controller.rb
@@ -0,0 +1,9 @@
+class OauthProviderApplicationsController < Doorkeeper::ApplicationsController
+
+  no_design_blocks
+  layout :get_layout
+
+  def show
+  end
+
+end

=====================================
plugins/oauth_provider/controllers/oauth_provider_authorizations_controller.rb
=====================================
--- /dev/null
+++ b/plugins/oauth_provider/controllers/oauth_provider_authorizations_controller.rb
@@ -0,0 +1,9 @@
+class OauthProviderAuthorizationsController < Doorkeeper::AuthorizationsController
+
+  no_design_blocks
+  layout :get_layout
+
+  def index
+  end
+
+end

=====================================
plugins/oauth_provider/controllers/oauth_provider_authorized_applications_controller.rb
=====================================
--- /dev/null
+++ b/plugins/oauth_provider/controllers/oauth_provider_authorized_applications_controller.rb
@@ -0,0 +1,6 @@
+class OauthProviderAuthorizedApplicationsController < Doorkeeper::AuthorizedApplicationsController
+
+  no_design_blocks
+  layout :get_layout
+
+end

=====================================
plugins/oauth_provider/controllers/oauth_provider_plugin_admin_controller.rb
=====================================
--- /dev/null
+++ b/plugins/oauth_provider/controllers/oauth_provider_plugin_admin_controller.rb
@@ -0,0 +1,6 @@
+class OauthProviderPluginAdminController < AdminController
+
+  def index
+  end
+
+end

=====================================
plugins/oauth_provider/controllers/public/oauth_provider_plugin_public_controller.rb
=====================================
--- /dev/null
+++ b/plugins/oauth_provider/controllers/public/oauth_provider_plugin_public_controller.rb
@@ -0,0 +1,10 @@
+class OauthProviderPluginPublicController < PublicController
+
+  doorkeeper_for :me
+
+  def me
+    user = environment.users.find(doorkeeper_token.resource_owner_id) if doorkeeper_token
+    render :json => {:id =>user.login, :email => user.email}.to_json
+  end
+
+end

=====================================
plugins/oauth_provider/db/migrate/20140829153047_create_doorkeeper_tables.rb
=====================================
--- /dev/null
+++ b/plugins/oauth_provider/db/migrate/20140829153047_create_doorkeeper_tables.rb
@@ -0,0 +1,41 @@
+class CreateDoorkeeperTables < ActiveRecord::Migration
+  def change
+    create_table :oauth_applications do |t|
+      t.string  :name,         null: false
+      t.string  :uid,          null: false
+      t.string  :secret,       null: false
+      t.text    :redirect_uri, null: false
+      t.timestamps
+    end
+
+    add_index :oauth_applications, :uid, unique: true
+
+    create_table :oauth_access_grants do |t|
+      t.integer  :resource_owner_id, null: false
+      t.integer  :application_id,    null: false
+      t.string   :token,             null: false
+      t.integer  :expires_in,        null: false
+      t.text     :redirect_uri,      null: false
+      t.datetime :created_at,        null: false
+      t.datetime :revoked_at
+      t.string   :scopes
+    end
+
+    add_index :oauth_access_grants, :token, unique: true
+
+    create_table :oauth_access_tokens do |t|
+      t.integer  :resource_owner_id
+      t.integer  :application_id
+      t.string   :token,             null: false
+      t.string   :refresh_token
+      t.integer  :expires_in
+      t.datetime :revoked_at
+      t.datetime :created_at,        null: false
+      t.string   :scopes
+    end
+
+    add_index :oauth_access_tokens, :token, unique: true
+    add_index :oauth_access_tokens, :resource_owner_id
+    add_index :oauth_access_tokens, :refresh_token, unique: true
+  end
+end

=====================================
plugins/oauth_provider/lib/oauth_provider_plugin.rb
=====================================
--- /dev/null
+++ b/plugins/oauth_provider/lib/oauth_provider_plugin.rb
@@ -0,0 +1,55 @@
+class OauthProviderPlugin < Noosfero::Plugin
+
+  def self.plugin_name
+    "Oauth Provider Plugin"
+  end
+
+  def self.plugin_description
+    _("Oauth Provider.")
+  end
+
+  def stylesheet?
+    true
+  end
+
+  Doorkeeper.configure do
+    orm :active_record
+
+    resource_owner_authenticator do
+      domain = Domain.find_by_name(request.host)
+      environment = domain ? domain.environment : Environment.default
+      environment.users.find_by_id(session[:user]) || redirect_to('/account/login')
+    end
+
+    admin_authenticator do
+      domain = Domain.find_by_name(request.host)
+      environment = domain ? domain.environment : Environment.default
+      user = environment.users.find_by_id(session[:user])
+      unless user && user.person.is_admin?(environment)
+        redirect_to('/account/login')
+      end
+      user
+    end
+
+    default_scopes :public
+  end
+
+  Rails.configuration.to_prepare do
+    Rails.application.routes.prepend do
+      scope 'oauth_provider' do
+        use_doorkeeper do
+          controllers ({
+            :applications => 'oauth_provider_applications',
+            :authorized_applications => 'oauth_provider_authorized_applications',
+            :authorizations => 'oauth_provider_authorizations'
+          })
+        end
+      end
+    end
+  end
+
+  SCOPE_TRANSLATION = {
+    'public' => _('Access your public data')
+  }
+
+end

=====================================
plugins/oauth_provider/public/style.css
=====================================
--- /dev/null
+++ b/plugins/oauth_provider/public/style.css
@@ -0,0 +1,13 @@
+.oauth-provider-authorize .actions form {
+  display: inline-block;
+}
+.oauth-provider-authorize .h4 {
+  font-size: 14px;
+  color: rgb(36, 36, 36)
+}
+.oauth-provider-authorize #oauth-permissions {
+  color: rgb(92, 92, 92);
+}
+.oauth-provider .actions {
+  margin-top: 10px;
+}

=====================================
plugins/oauth_provider/views/doorkeeper/applications/_delete_form.html.erb
=====================================
--- /dev/null
+++ b/plugins/oauth_provider/views/doorkeeper/applications/_delete_form.html.erb
@@ -0,0 +1,5 @@
+<%- submit_btn_css ||= 'btn btn-link' %>
+<%= form_tag [:oauth, application] do %>
+  <input type="hidden" name="_method" value="delete">
+  <%= submit_tag 'Destroy', onclick: "return confirm('Are you sure?')", class: submit_btn_css %>
+<% end %>

=====================================
plugins/oauth_provider/views/doorkeeper/applications/_form.html.erb
=====================================
--- /dev/null
+++ b/plugins/oauth_provider/views/doorkeeper/applications/_form.html.erb
@@ -0,0 +1,39 @@
+<%= form_for [:oauth, application], html: {class: 'form-horizontal', role: 'form'} do |f| %>
+  <% if application.errors.any? %>
+    <div class="alert alert-danger" data-alert>
+      <p><%= _('Whoops! Check your form for possible errors') %></p>
+    </div>
+  <% end %>
+
+  <%= content_tag :div, class: "form-group#{' has-error' if application.errors[:name].present?}" do %>
+    <%= f.label :name, class: 'col-sm-2 control-label', for: 'application_name' %>
+    <div class="col-sm-10">
+      <%= f.text_field :name, class: 'form-control' %>
+      <%= doorkeeper_errors_for application, :name %>
+    </div>
+  <% end %>
+
+  <%= content_tag :div, class: "form-group#{' has-error' if application.errors[:redirect_uri].present?}" do %>
+    <%= f.label :redirect_uri, class: 'col-sm-2 control-label', for: 'application_redirect_uri' %>
+    <div class="col-sm-10">
+      <%= f.text_area :redirect_uri, class: 'form-control' %>
+      <%= doorkeeper_errors_for application, :redirect_uri %>
+      <span class="help-block">
+        <%= _('Use one line per URI') %>
+        </span>
+      <% if Doorkeeper.configuration.native_redirect_uri %>
+          <span class="help-block">
+            Use <code><%= Doorkeeper.configuration.native_redirect_uri %></code> for local tests
+          </span>
+      <% end %>
+    </div>
+  <% end %>
+
+  <div class="form-group">
+    <div class="col-sm-offset-2 col-sm-10">
+      <%= f.submit _('Submit'), class: "btn btn-primary" %>
+      <%= link_to _("Cancel"), oauth_applications_path, :class => "btn btn-default" %>
+    </div>
+  </div>
+<% end %>
+

=====================================
plugins/oauth_provider/views/doorkeeper/applications/edit.html.erb
=====================================
--- /dev/null
+++ b/plugins/oauth_provider/views/doorkeeper/applications/edit.html.erb
@@ -0,0 +1,5 @@
+<div class="page-header">
+  <h1><%= _('Edit application') %></h1>
+</div>
+
+<%= render 'form', application: @application %>

=====================================
plugins/oauth_provider/views/doorkeeper/applications/index.html.erb
=====================================
--- /dev/null
+++ b/plugins/oauth_provider/views/doorkeeper/applications/index.html.erb
@@ -0,0 +1,31 @@
+<div class="oauth-provider">
+<div class="page-header">
+  <h3><%= link_to _('Oauh Provider'), '/admin/plugin/oauth_provider' %></h3>
+</div>
+
+<p><%= link_to _('New Application'), new_oauth_application_path, class: 'btn btn-success' %></p>
+
+<table class="table table-striped">
+  <thead>
+  <tr>
+    <th><%= _('Name') %></th>
+    <th><%= _('Callback URL') %></th>
+    <th></th>
+    <th></th>
+  </tr>
+  </thead>
+  <tbody>
+  <% @applications.each do |application| %>
+    <tr id="application_<%= application.id %>">
+      <td><%= link_to application.name, [:oauth, application] %></td>
+      <td><%= application.redirect_uri %></td>
+      <td><%= link_to _('Edit'), edit_oauth_application_path(application), class: 'btn btn-link' %></td>
+      <td><%= render 'delete_form', application: application %></td>
+    </tr>
+  <% end %>
+  </tbody>
+</table>
+<div class="actions">
+  <%= button(:back, _('Go back'), {:controller => 'oauth_provider_plugin_admin', :action => 'index'}) %>
+</div>
+</div>

=====================================
plugins/oauth_provider/views/doorkeeper/applications/new.html.erb
=====================================
--- /dev/null
+++ b/plugins/oauth_provider/views/doorkeeper/applications/new.html.erb
@@ -0,0 +1,5 @@
+<div class="page-header">
+  <h1>New application</h1>
+</div>
+
+<%= render 'form', application: @application %>

=====================================
plugins/oauth_provider/views/doorkeeper/applications/show.html.erb
=====================================
--- /dev/null
+++ b/plugins/oauth_provider/views/doorkeeper/applications/show.html.erb
@@ -0,0 +1,40 @@
+<div class="page-header">
+  <h1><%= _('Application: %s' % @application.name) %></h1>
+</div>
+
+<div class="row">
+  <div class="col-md-8">
+    <h4><%= _('Application Id:') %></h4>
+
+    <p><code id="application_id"><%= @application.uid %></code></p>
+
+    <h4><%= _('Secret:') %></h4>
+
+    <p><code id="secret"><%= @application.secret %></code></p>
+
+    <h4><%= _('Callback urls:') %></h4>
+
+    <table>
+      <% @application.redirect_uri.split.each do |uri| %>
+        <tr>
+          <td>
+            <code><%= uri %></code>
+          </td>
+          <td>
+          </td>
+        </tr>
+      <% end %>
+    </table>
+  </div>
+
+  <div class="col-md-4">
+    <h3><%= _('Actions') %></h3>
+
+    <p>
+      <%= link_to _('Edit'), edit_oauth_application_path(@application), class: 'btn btn-primary' %>
+      <%= link_to _("Cancel"), oauth_applications_path, :class => "btn btn-default" %>
+    </p>
+
+    <p><%= render 'delete_form', application: @application, submit_btn_css: 'btn btn-danger' %></p>
+  </div>
+</div>

=====================================
plugins/oauth_provider/views/doorkeeper/authorizations/error.html.erb
=====================================
--- /dev/null
+++ b/plugins/oauth_provider/views/doorkeeper/authorizations/error.html.erb
@@ -0,0 +1,7 @@
+<div class="page-header">
+  <h1>An error has occurred</h1>
+</div>
+
+<main role="main">
+  <pre><%= @pre_auth.error_response.body[:error_description] %></pre>
+</main>

=====================================
plugins/oauth_provider/views/doorkeeper/authorizations/new.html.erb
=====================================
--- /dev/null
+++ b/plugins/oauth_provider/views/doorkeeper/authorizations/new.html.erb
@@ -0,0 +1,43 @@
+<div class="oauth-provider-authorize">
+
+<header class="page-header" role="banner">
+  <h1><%= _('Authorize required') %></h1>
+</header>
+
+<main role="main">
+  <p class="h4">
+  <%= _('Authorize %s to use your account?' % "<strong class=\"text-info\">#{@pre_auth.client.name}</strong>") %>
+  </p>
+
+  <% if @pre_auth.scopes %>
+    <div id="oauth-permissions">
+      <p><%= _('This application will be able to:') %></p>
+
+      <ul class="text-info">
+        <% @pre_auth.scopes.each do |scope| %>
+          <li><%= OauthProviderPlugin::SCOPE_TRANSLATION[scope] %></li>
+        <% end %>
+      </ul>
+    </div>
+  <% end %>
+
+  <div class="actions">
+    <%= form_tag oauth_authorization_path, method: :post do %>
+      <%= hidden_field_tag :client_id, @pre_auth.client.uid %>
+      <%= hidden_field_tag :redirect_uri, @pre_auth.redirect_uri %>
+      <%= hidden_field_tag :state, @pre_auth.state %>
+      <%= hidden_field_tag :response_type, @pre_auth.response_type %>
+      <%= hidden_field_tag :scope, @pre_auth.scope %>
+      <%= submit_button :ok, _("Authorize") %>
+    <% end %>
+    <%= form_tag oauth_authorization_path, method: :delete do %>
+      <%= hidden_field_tag :client_id, @pre_auth.client.uid %>
+      <%= hidden_field_tag :redirect_uri, @pre_auth.redirect_uri %>
+      <%= hidden_field_tag :state, @pre_auth.state %>
+      <%= hidden_field_tag :response_type, @pre_auth.response_type %>
+      <%= hidden_field_tag :scope, @pre_auth.scope %>
+      <%= submit_button :cancel, _("Deny") %>
+    <% end %>
+  </div>
+</main>
+</div>

=====================================
plugins/oauth_provider/views/doorkeeper/authorizations/show.html.erb
=====================================
--- /dev/null
+++ b/plugins/oauth_provider/views/doorkeeper/authorizations/show.html.erb
@@ -0,0 +1,7 @@
+<header class="page-header">
+  <h1>Authorization code:</h1>
+</header>
+
+<main role="main">
+  <code id="authorization_code"><%= params[:code] %></code>
+</main>

=====================================
plugins/oauth_provider/views/doorkeeper/authorized_applications/_delete_form.html.erb
=====================================
--- /dev/null
+++ b/plugins/oauth_provider/views/doorkeeper/authorized_applications/_delete_form.html.erb
@@ -0,0 +1,5 @@
+<%- submit_btn_css ||= 'btn btn-link' %>
+<%= form_tag oauth_authorized_application_path(application) do %>
+  <input type="hidden" name="_method" value="delete">
+  <%= submit_tag 'Revoke', onclick: "return confirm('Are you sure?')", class: submit_btn_css %>
+<% end %>

=====================================
plugins/oauth_provider/views/doorkeeper/authorized_applications/index.html.erb
=====================================
--- /dev/null
+++ b/plugins/oauth_provider/views/doorkeeper/authorized_applications/index.html.erb
@@ -0,0 +1,31 @@
+<div class="oauth-provider">
+<header class="page-header">
+  <h1>Your authorized applications</h1>
+</header>
+
+<main role="main">
+  <table class="table table-striped">
+    <thead>
+    <tr>
+      <th>Application</th>
+      <th>Created At</th>
+      <th></th>
+      <th></th>
+    </tr>
+    </thead>
+    <tbody>
+    <% @applications.each do |application| %>
+      <tr>
+        <td><%= application.name %></td>
+        <td><%= application.created_at.strftime('%Y-%m-%d %H:%M:%S') %></td>
+        <td><%= render 'delete_form', application: application %></td>
+      </tr>
+    <% end %>
+    </tbody>
+  </table>
+</main>
+
+<div class="actions">
+  <%= button(:back, _('Go back'), :back) %>
+</div>
+</div>

=====================================
plugins/oauth_provider/views/oauth_provider_plugin_admin/index.html.erb
=====================================
--- /dev/null
+++ b/plugins/oauth_provider/views/oauth_provider_plugin_admin/index.html.erb
@@ -0,0 +1,14 @@
+<div class="oauth-provider">
+<h3><%= _('Oauh Provider') %></h3>
+
+  <div class="applications">
+    <%= link_to _('Applications'), oauth_applications_path %>
+  </div>
+  <div class="authorized-applications">
+    <%= link_to _('Authorized Applications'), oauth_authorized_applications_path %>
+  </div>
+
+  <div class="actions">
+    <%= button(:back, _('Go back'), {:controller => 'plugins', :action => 'index'}) %>
+  </div>
+</div>

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://listas.softwarelivre.org/pipermail/noosfero-dev/attachments/20150222/97ba69fd/attachment-0001.html>


More information about the Noosfero-dev mailing list