From cf8ddd52c4125e9113bea0459ff0c1a10b9febe8 Mon Sep 17 00:00:00 2001 From: Victor Costa Date: Wed, 26 Mar 2014 17:58:21 -0300 Subject: [PATCH] oauth_client: oauth login with google and facebook --- plugins/oauth_client/Gemfile | 3 +++ plugins/oauth_client/README | 11 +++++++++++ plugins/oauth_client/controllers/oauth_client_plugin_admin_controller.rb | 15 +++++++++++++++ plugins/oauth_client/controllers/public/oauth_client_plugin_public_controller.rb | 27 +++++++++++++++++++++++++++ plugins/oauth_client/db/migrate/20140828184930_add_settings_to_users.rb | 9 +++++++++ plugins/oauth_client/lib/ext/user.rb | 40 ++++++++++++++++++++++++++++++++++++++++ plugins/oauth_client/lib/oauth_client_plugin.rb | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ plugins/oauth_client/public/images/facebook-icon.png | Bin 0 -> 831 bytes plugins/oauth_client/public/images/google-icon.png | Bin 0 -> 1615 bytes plugins/oauth_client/public/style.css | 22 ++++++++++++++++++++++ plugins/oauth_client/views/account/_oauth_signup.html.erb | 11 +++++++++++ plugins/oauth_client/views/auth/_facebook.html.erb | 1 + plugins/oauth_client/views/auth/_google_oauth2.html.erb | 1 + plugins/oauth_client/views/auth/_oauth_login.html.erb | 13 +++++++++++++ plugins/oauth_client/views/oauth_client_plugin_admin/index.html.erb | 44 ++++++++++++++++++++++++++++++++++++++++++++ 15 files changed, 267 insertions(+), 0 deletions(-) create mode 100644 plugins/oauth_client/Gemfile create mode 100644 plugins/oauth_client/README create mode 100644 plugins/oauth_client/controllers/oauth_client_plugin_admin_controller.rb create mode 100644 plugins/oauth_client/controllers/public/oauth_client_plugin_public_controller.rb create mode 100644 plugins/oauth_client/db/migrate/20140828184930_add_settings_to_users.rb create mode 100644 plugins/oauth_client/lib/ext/user.rb create mode 100644 plugins/oauth_client/lib/oauth_client_plugin.rb create mode 100644 plugins/oauth_client/public/images/facebook-icon.png create mode 100644 plugins/oauth_client/public/images/google-icon.png create mode 100644 plugins/oauth_client/public/style.css create mode 100644 plugins/oauth_client/views/account/_oauth_signup.html.erb create mode 100644 plugins/oauth_client/views/auth/_facebook.html.erb create mode 100644 plugins/oauth_client/views/auth/_google_oauth2.html.erb create mode 100644 plugins/oauth_client/views/auth/_oauth_login.html.erb create mode 100644 plugins/oauth_client/views/oauth_client_plugin_admin/index.html.erb diff --git a/plugins/oauth_client/Gemfile b/plugins/oauth_client/Gemfile new file mode 100644 index 0000000..454aae0 --- /dev/null +++ b/plugins/oauth_client/Gemfile @@ -0,0 +1,3 @@ +gem 'omniauth' +gem 'omniauth-facebook' +gem "omniauth-google-oauth2" diff --git a/plugins/oauth_client/README b/plugins/oauth_client/README new file mode 100644 index 0000000..71cc886 --- /dev/null +++ b/plugins/oauth_client/README @@ -0,0 +1,11 @@ + + +https://github.com/mkdynamic/omniauth-facebook +https://github.com/zquestz/omniauth-google-oauth2 + +Create Google+ application: + https://developers.google.com/+/web/signin/javascript-flow + +Create Facebook application: + https://developers.facebook.com/docs/facebook-login/v2.1 + https://developers.facebook.com/docs/reference/dialogs/oauth diff --git a/plugins/oauth_client/controllers/oauth_client_plugin_admin_controller.rb b/plugins/oauth_client/controllers/oauth_client_plugin_admin_controller.rb new file mode 100644 index 0000000..50bde52 --- /dev/null +++ b/plugins/oauth_client/controllers/oauth_client_plugin_admin_controller.rb @@ -0,0 +1,15 @@ +class OauthClientPluginAdminController < AdminController + + def index + settings = params[:settings] || {} + + @settings = Noosfero::Plugin::Settings.new(environment, OauthClientPlugin, settings) + @providers = @settings.get_setting(:providers) || {} + if request.post? + @settings.save! + session[:notice] = 'Settings succefully saved.' + redirect_to :action => 'index' + end + end + +end diff --git a/plugins/oauth_client/controllers/public/oauth_client_plugin_public_controller.rb b/plugins/oauth_client/controllers/public/oauth_client_plugin_public_controller.rb new file mode 100644 index 0000000..6c4fe08 --- /dev/null +++ b/plugins/oauth_client/controllers/public/oauth_client_plugin_public_controller.rb @@ -0,0 +1,27 @@ +class OauthClientPluginPublicController < PublicController + + def callback + auth = request.env["omniauth.auth"] + login = auth.info.email.split('@').first + user = environment.users.find_with_omniauth(auth) + + if user + session[:user] = user + redirect_to :controller => :account, :action => :login + else + 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, :oauth_providers => [{:provider => auth.provider, :uid => auth.uid}]}, :profile_data => {:name => name} + end + end + + def failure + redirect_to root_url + end + + def destroy + session[:user] = nil + redirect_to root_url + end + +end diff --git a/plugins/oauth_client/db/migrate/20140828184930_add_settings_to_users.rb b/plugins/oauth_client/db/migrate/20140828184930_add_settings_to_users.rb new file mode 100644 index 0000000..75ffe1f --- /dev/null +++ b/plugins/oauth_client/db/migrate/20140828184930_add_settings_to_users.rb @@ -0,0 +1,9 @@ +class AddSettingsToUsers < ActiveRecord::Migration + def self.up + add_column :users, :settings, :string + end + + def self.down + remove_column :users, :settings + end +end diff --git a/plugins/oauth_client/lib/ext/user.rb b/plugins/oauth_client/lib/ext/user.rb new file mode 100644 index 0000000..014013b --- /dev/null +++ b/plugins/oauth_client/lib/ext/user.rb @@ -0,0 +1,40 @@ +require_dependency 'user' + +class User + + acts_as_having_settings :field => :settings + + settings_items :oauth_providers, :type => Array, :default => [] + + def self.find_with_omniauth(auth) + user = self.find_by_email(auth.info.email) + if user && !user.oauth_providers.empty? #FIXME save new oauth providers + user + else + nil + end + end + + def password_required_with_oauth? + password_required_without_oauth? && oauth_providers.blank? + end + + alias_method_chain :password_required?, :oauth + + after_create :activate_oauth_user + + def activate_oauth_user + activate unless oauth_providers.empty? + end + + def make_activation_code_with_oauth + if oauth_providers.blank? + nil + else + make_activation_code_without_oauth + end + end + + alias_method_chain :make_activation_code, :oauth + +end diff --git a/plugins/oauth_client/lib/oauth_client_plugin.rb b/plugins/oauth_client/lib/oauth_client_plugin.rb new file mode 100644 index 0000000..88ff240 --- /dev/null +++ b/plugins/oauth_client/lib/oauth_client_plugin.rb @@ -0,0 +1,70 @@ +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 => plugin.enabled_providers} + end + end + + def signup_extra_contents + plugin = self + + proc do + unless (plugin.context.params[:user]||{})[:oauth_providers].blank? + render :partial => 'oauth_signup' + else + '' + end + end + end + + def enabled_providers + settings = Noosfero::Plugin::Settings.new(context.environment, OauthClientPlugin) + providers = settings.get_setting(:providers) + providers.select {|provider, options| options[:enabled]} + end + + PROVIDERS = { + :facebook => { + :name => 'Facebook' + }, + :google_oauth2 => { + :name => 'Google' + } + } + + def stylesheet? + true + end + + Rails.application.config.middleware.use OmniAuth::Builder do + PROVIDERS.each do |provider, options| + provider provider, :setup => lambda { |env| + request = Rack::Request.new env + strategy = env['omniauth.strategy'] + + domain = Domain.find_by_name(request.host) + environment = domain.environment rescue Environment.default + settings = Noosfero::Plugin::Settings.new(environment, OauthClientPlugin) + providers = settings.get_setting(:providers) + + strategy.options.client_id = providers[provider][:client_id] + strategy.options.client_secret = providers[provider][:client_secret] + }, :path_prefix => '/plugin/oauth_client', :callback_path => "/plugin/oauth_client/public/callback/#{provider}" + end + + unless Rails.env.production? + provider :developer, :path_prefix => "/plugin/oauth_client", :callback_path => "/plugin/oauth_client/public/callback/developer" + end + end + +end diff --git a/plugins/oauth_client/public/images/facebook-icon.png b/plugins/oauth_client/public/images/facebook-icon.png new file mode 100644 index 0000000..6b48648 Binary files /dev/null and b/plugins/oauth_client/public/images/facebook-icon.png differ diff --git a/plugins/oauth_client/public/images/google-icon.png b/plugins/oauth_client/public/images/google-icon.png new file mode 100644 index 0000000..3909e9d Binary files /dev/null and b/plugins/oauth_client/public/images/google-icon.png differ diff --git a/plugins/oauth_client/public/style.css b/plugins/oauth_client/public/style.css new file mode 100644 index 0000000..2f2b17f --- /dev/null +++ b/plugins/oauth_client/public/style.css @@ -0,0 +1,22 @@ +.oauth-login .provider a { + min-width: 20px; + min-height: 20px; + background-size: 20px; + display: inline-block; + text-decoration: none; + background-repeat: no-repeat; + padding-left: 22px; + line-height: 20px; +} + +.oauth-login .provider .facebook { + background-image: url(images/facebook-icon.png); +} + +.oauth-login .provider .google_oauth2 { + background-image: url(images/google-icon.png); +} + +.oauth-login .provider .developer { + display: none; +} diff --git a/plugins/oauth_client/views/account/_oauth_signup.html.erb b/plugins/oauth_client/views/account/_oauth_signup.html.erb new file mode 100644 index 0000000..561bfe1 --- /dev/null +++ b/plugins/oauth_client/views/account/_oauth_signup.html.erb @@ -0,0 +1,11 @@ +<%= hidden_field_tag 'user[oauth_providers][][provider]', @user.oauth_providers.first[:provider] %> +<%= hidden_field_tag 'user[oauth_providers][][uid]', @user.oauth_providers.first[:uid] %> + + diff --git a/plugins/oauth_client/views/auth/_facebook.html.erb b/plugins/oauth_client/views/auth/_facebook.html.erb new file mode 100644 index 0000000..96a203c --- /dev/null +++ b/plugins/oauth_client/views/auth/_facebook.html.erb @@ -0,0 +1 @@ +<%= _('Login with Facebook') %> diff --git a/plugins/oauth_client/views/auth/_google_oauth2.html.erb b/plugins/oauth_client/views/auth/_google_oauth2.html.erb new file mode 100644 index 0000000..5defae3 --- /dev/null +++ b/plugins/oauth_client/views/auth/_google_oauth2.html.erb @@ -0,0 +1 @@ +<%= _('Login with Google') %> diff --git a/plugins/oauth_client/views/auth/_oauth_login.html.erb b/plugins/oauth_client/views/auth/_oauth_login.html.erb new file mode 100644 index 0000000..bf33a02 --- /dev/null +++ b/plugins/oauth_client/views/auth/_oauth_login.html.erb @@ -0,0 +1,13 @@ +
+ <% providers.each do |provider, options| %> + + <%= render :partial => "auth/#{provider}", :locals => {:app_id => options['client_id'] } %> + + <% end %> + + + <% unless Rails.env.production? %> + <%= link_to _('Developer Login'), "/plugin/oauth/developer", :class => 'developer' %> + <% end %> + +
diff --git a/plugins/oauth_client/views/oauth_client_plugin_admin/index.html.erb b/plugins/oauth_client/views/oauth_client_plugin_admin/index.html.erb new file mode 100644 index 0000000..9be9852 --- /dev/null +++ b/plugins/oauth_client/views/oauth_client_plugin_admin/index.html.erb @@ -0,0 +1,44 @@ +

<%= _('Oauth Client Settings') %>

+ +<%= form_for(:settings) do |f| %> +
+

<%= _('Providers') %>

+ <%= f.fields_for :providers, OpenStruct.new(@providers) do |p| %> + + <% OauthClientPlugin::PROVIDERS.each do |available_provider, options| %> + <% provider = OpenStruct.new(@providers[available_provider]) %> + + <%= p.fields_for available_provider, provider do |o| %> +
+
+

<%= o.check_box :enabled, {:class => 'enable', :checked => provider.enabled=='true'}, true, false %> + <%= options[:name] %>

+
+
+
+ <%= _('Client ID') %> + <%= o.text_field :client_id %> +
+
+ <%= _('Client Secret') %> + <%= o.text_field :client_secret %> +
+
+
+ <% end %> + <% end %> + <% end %> + + <% button_bar do %> + <%= submit_button(:save, _('Save'), :cancel => {:controller => 'plugins', :action => 'index'}) %> + <% end %> +
+<% end %> + + -- libgit2 0.21.2